zidane-ui 9.1.4 → 9.1.5
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/dist/adapters/server-extensions-host.js +1 -1
- package/dist/adapters/server-host.js +2 -1
- package/dist/adapters/server-machines-host.js +1 -1
- package/dist/adapters/server-session-host.js +87 -13
- package/dist/adapters/server-settings-host.js +1 -1
- package/dist/appearance/AppearanceProvider.js +2 -2
- package/dist/appearance/headless/index.js +1 -1
- package/dist/approvals/headless/index.js +2 -2
- package/dist/chat/HostTranscript.d.ts +5 -1
- package/dist/chat/HostTranscript.js +16 -4
- package/dist/chat/RunEstimateChip.d.ts +5 -3
- package/dist/chat/RunEstimateChip.js +33 -3
- package/dist/chat/Transcript.js +1 -1
- package/dist/chat/composer/ComposerEditor.js +1 -1
- package/dist/chat/composer/ConversationBadges.js +16 -10
- package/dist/chat/composer/composer-bus.d.ts +2 -2
- package/dist/chat/composer/composer-bus.js +2 -2
- package/dist/chat/composer/use-composer-stores.js +1 -1
- package/dist/chat/composer/use-run-meter.js +1 -1
- package/dist/chat/headless/composer/conversation-badges.d.ts +8 -3
- package/dist/chat/headless/composer/conversation-badges.js +26 -11
- package/dist/chat/headless/composer/index.js +2 -2
- package/dist/chat/headless/composer/labels-chrome.d.ts +3 -1
- package/dist/chat/headless/composer/labels-chrome.js +3 -1
- package/dist/chat/headless/index.d.ts +5 -3
- package/dist/chat/headless/index.js +16 -14
- package/dist/chat/headless/labels.d.ts +54 -1
- package/dist/chat/headless/labels.js +62 -2
- package/dist/chat/headless/secrets.d.ts +32 -0
- package/dist/chat/headless/secrets.js +43 -0
- package/dist/chat/headless/session-list.d.ts +45 -0
- package/dist/chat/headless/sidebar/estimates.js +13 -1
- package/dist/chat/headless/sidebar/index.d.ts +2 -2
- package/dist/chat/headless/sidebar/labels.d.ts +50 -0
- package/dist/chat/headless/sidebar/labels.js +1 -0
- package/dist/chat/headless/sidebar/query.d.ts +2 -2
- package/dist/chat/headless/sidebar/query.js +6 -3
- package/dist/chat/headless/sidebar/types.d.ts +7 -1
- package/dist/chat/headless/sidebar/view.js +2 -0
- package/dist/chat/headless/transcript/auth-failure.d.ts +67 -0
- package/dist/chat/headless/transcript/auth-failure.js +87 -0
- package/dist/chat/headless/transcript/index.d.ts +2 -1
- package/dist/chat/headless/transcript/index.js +2 -1
- package/dist/chat/headless/transcript/nesting.d.ts +3 -3
- package/dist/chat/headless/transcript/nesting.js +12 -4
- package/dist/chat/index.d.ts +4 -2
- package/dist/chat/index.js +3 -1
- package/dist/chat/interactions/InboxPanel.d.ts +6 -2
- package/dist/chat/interactions/InboxPanel.js +82 -44
- package/dist/chat/interactions/PlanCard.d.ts +2 -2
- package/dist/chat/interactions/PlanCard.js +1 -1
- package/dist/chat/interactions/QuestionField.d.ts +8 -3
- package/dist/chat/interactions/QuestionField.js +89 -8
- package/dist/chat/interactions/QuestionForm.d.ts +3 -1
- package/dist/chat/interactions/QuestionForm.js +48 -10
- package/dist/chat/interactions/SecretInput.d.ts +32 -0
- package/dist/chat/interactions/SecretInput.js +72 -0
- package/dist/chat/interactions/card-ui.d.ts +5 -3
- package/dist/chat/interactions/card-ui.js +5 -3
- package/dist/chat/interactions/index.d.ts +2 -1
- package/dist/chat/interactions/index.js +2 -1
- package/dist/chat/sidebar/SessionSidebar.js +2 -0
- package/dist/chat/sidebar/SidebarFilterMenu.d.ts +7 -2
- package/dist/chat/sidebar/SidebarFilterMenu.js +26 -2
- package/dist/chat/sidebar/SidebarSessionRow.d.ts +3 -1
- package/dist/chat/sidebar/SidebarSessionRow.js +8 -3
- package/dist/chat/sidebar/sidebar-live.js +8 -4
- package/dist/chat/transcript/AuthFailureCard.d.ts +34 -0
- package/dist/chat/transcript/AuthFailureCard.js +358 -0
- package/dist/chat/transcript/InteractionToolBody.js +12 -2
- package/dist/chat/transcript/actions.d.ts +24 -1
- package/dist/chat/transcript/index.d.ts +3 -2
- package/dist/chat/transcript/index.js +2 -1
- package/dist/chat/transcript/notices.d.ts +2 -1
- package/dist/chat/transcript/notices.js +13 -1
- package/dist/chat/transcript/script-input.d.ts +1 -1
- package/dist/chat/transcript/shell-block.js +1 -1
- package/dist/components/HowItWorks.d.ts +8 -1
- package/dist/components/HowItWorks.js +2 -2
- package/dist/components/RowActionsMenu.d.ts +6 -1
- package/dist/components/RowActionsMenu.js +4 -0
- package/dist/core.css +24 -0
- package/dist/dist/{index-WlE93Q6d.d.ts → index-BI6RZc60.d.ts} +36 -3
- package/dist/dist/index-f-XWIoYo.d.ts +1 -0
- package/dist/dist/index.d.ts +6 -0
- package/dist/dist/sandbox-B4OW6oNx.d.ts +2 -0
- package/dist/dist/timeout-B5pO5I5a.d.ts +30 -0
- package/dist/extensions/ExtensionSettingsPage.js +1 -1
- package/dist/extensions/ExtensionSettingsSidebar.js +1 -1
- package/dist/extensions/headless/fixture-host.js +1 -1
- package/dist/extensions/headless/index.js +4 -4
- package/dist/extensions/hooks.js +1 -1
- package/dist/files/DiffsTab.js +1 -1
- package/dist/files/EditorColumn.js +1 -1
- package/dist/files/MediaDiff.js +1 -1
- package/dist/files/SearchPanel.js +121 -53
- package/dist/files/headless/name-match.js +29 -14
- package/dist/files/useEntryActions.js +1 -1
- package/dist/files/useOpenFiles.js +1 -1
- package/dist/git/WherePicker.js +2 -2
- package/dist/git/headless/environment.d.ts +6 -1
- package/dist/git/headless/environment.js +5 -2
- package/dist/git/headless/labels.d.ts +2 -0
- package/dist/git/headless/labels.js +2 -0
- package/dist/git/index.d.ts +2 -1
- package/dist/git/index.js +2 -1
- package/dist/git/useStartFromPanel.d.ts +22 -0
- package/dist/git/useStartFromPanel.js +91 -0
- package/dist/keybindings/KeyCommands.js +1 -1
- package/dist/keybindings/KeybindingsProvider.js +1 -1
- package/dist/keybindings/headless/catalog.js +2 -2
- package/dist/keybindings/headless/index.js +2 -2
- package/dist/keybindings/headless/overrides.js +1 -1
- package/dist/machines/HostSyncPanel.js +1 -1
- package/dist/machines/SyncOutcomeBadge.js +1 -1
- package/dist/machines/headless/index.js +1 -1
- package/dist/onboarding/demos/features.d.ts +9 -1
- package/dist/onboarding/demos/features.js +107 -2
- package/dist/onboarding/demos/how-it-works.d.ts +5 -1
- package/dist/onboarding/demos/how-it-works.js +120 -2
- package/dist/onboarding/demos/index.js +1 -1
- package/dist/onboarding/headless/labels.d.ts +17 -0
- package/dist/onboarding/headless/labels.js +17 -0
- package/dist/onboarding/index.js +4 -4
- package/dist/onboarding/marks.d.ts +1 -2
- package/dist/onboarding/marks.js +4 -12
- package/dist/onboarding/steps/ConnectorsStep.js +1 -1
- package/dist/onboarding/steps/ReadyStep.js +1 -1
- package/dist/onboarding/steps/SkillsStep.js +1 -1
- package/dist/onboarding/steps/connect/ProviderPanel.js +1 -1
- package/dist/onboarding/tutorials.d.ts +3 -1
- package/dist/onboarding/tutorials.js +2 -1
- package/dist/palette/app-sources.js +1 -1
- package/dist/session/ArtifactsPanel.js +1 -1
- package/dist/session/PanelAttention.d.ts +14 -6
- package/dist/session/PanelAttention.js +35 -24
- package/dist/session/PlanTracker.d.ts +54 -0
- package/dist/session/PlanTracker.js +412 -0
- package/dist/session/ProjectHome.d.ts +15 -2
- package/dist/session/ProjectHome.js +158 -85
- package/dist/session/RemindersPanel.d.ts +25 -0
- package/dist/session/RemindersPanel.js +526 -0
- package/dist/session/SecretsPanel.d.ts +19 -0
- package/dist/session/SecretsPanel.js +241 -0
- package/dist/session/SessionProvider.d.ts +26 -5
- package/dist/session/SessionProvider.js +51 -6
- package/dist/session/StepStatusIcon.d.ts +24 -0
- package/dist/session/StepStatusIcon.js +50 -0
- package/dist/session/TodoList.d.ts +4 -3
- package/dist/session/TodoList.js +6 -5
- package/dist/session/headless/fixture-host.d.ts +32 -22
- package/dist/session/headless/fixture-host.js +86 -51
- package/dist/session/headless/fixture-plans.d.ts +57 -0
- package/dist/session/headless/fixture-plans.js +141 -0
- package/dist/session/headless/fixture-schedules.d.ts +49 -0
- package/dist/session/headless/fixture-schedules.js +133 -0
- package/dist/session/headless/home-layout.d.ts +10 -2
- package/dist/session/headless/home-layout.js +7 -2
- package/dist/session/headless/host.d.ts +85 -13
- package/dist/session/headless/index.d.ts +5 -3
- package/dist/session/headless/index.js +5 -3
- package/dist/session/headless/labels.d.ts +95 -12
- package/dist/session/headless/labels.js +67 -18
- package/dist/session/headless/plans.d.ts +53 -0
- package/dist/session/headless/plans.js +78 -0
- package/dist/session/headless/reminder-labels.d.ts +63 -0
- package/dist/session/headless/reminder-labels.js +84 -0
- package/dist/session/headless/schedules.d.ts +93 -0
- package/dist/session/headless/schedules.js +190 -0
- package/dist/session/headless/secrets.d.ts +28 -0
- package/dist/session/headless/secrets.js +48 -0
- package/dist/session/index.d.ts +7 -5
- package/dist/session/index.js +6 -4
- package/dist/session/testing/contract.d.ts +18 -5
- package/dist/session/testing/contract.js +351 -43
- package/dist/session/testing/index.d.ts +4 -2
- package/dist/session/testing/index.js +4 -2
- package/dist/settings/headless/catalog.js +17 -1
- package/dist/settings/headless/index.d.ts +2 -2
- package/dist/settings/headless/index.js +3 -3
- package/dist/settings/headless/labels.d.ts +0 -2
- package/dist/settings/headless/labels.js +0 -2
- package/dist/settings/headless/layout.js +7 -1
- package/dist/settings/headless/providers.d.ts +17 -1
- package/dist/settings/headless/providers.js +19 -1
- package/dist/settings/headless/search.d.ts +1 -1
- package/dist/settings/rows.d.ts +1 -1
- package/dist/settings/rows.js +2 -2
- package/dist/settings/sections/appearance/AppearanceSection.js +2 -2
- package/dist/settings/sections/claude-import/ClaudeImportDialog.js +1 -1
- package/dist/settings/sections/editor/EditorSection.js +1 -1
- package/dist/settings/sections/environments/EnvironmentsSection.js +1 -1
- package/dist/settings/sections/extensions/ChangeOriginDialog.js +1 -1
- package/dist/settings/sections/extensions/CreateExtensionDialog.js +1 -1
- package/dist/settings/sections/extensions/ExtensionsSection.js +1 -1
- package/dist/settings/sections/host-catalog/HostCatalogSection.js +1 -1
- package/dist/settings/sections/instructions/InstructionsSection.js +1 -1
- package/dist/settings/sections/mcp/McpSection.js +1 -1
- package/dist/settings/sections/mcp/McpServerRow.js +1 -1
- package/dist/settings/sections/models/ModelRows.js +2 -2
- package/dist/settings/sections/providers/ProvidersSection.js +209 -201
- package/dist/settings/sections/providers/ServerProvidersSection.js +1 -1
- package/dist/settings/sections/shared/catalog.js +1 -1
- package/dist/settings/sections/skills/SkillsSection.js +2 -2
- package/dist/styles.css +59 -1
- package/dist/terminal/HostTerminalSurface.js +2 -2
- package/dist/workspace/PanelContentView.d.ts +22 -4
- package/dist/workspace/PanelContentView.js +112 -16
- package/dist/workspace/PanelGlyph.d.ts +21 -0
- package/dist/workspace/PanelGlyph.js +33 -0
- package/dist/workspace/PanelHome.js +5 -3
- package/dist/workspace/PanelStrip.js +11 -4
- package/dist/workspace/PanelToolbar.d.ts +32 -0
- package/dist/workspace/PanelToolbar.js +194 -0
- package/dist/workspace/WorkspaceProvider.d.ts +3 -1
- package/dist/workspace/WorkspaceProvider.js +6 -2
- package/dist/workspace/extension-tabs.js +5 -2
- package/dist/workspace/headless/host.d.ts +4 -0
- package/dist/workspace/headless/index.d.ts +3 -1
- package/dist/workspace/headless/index.js +4 -2
- package/dist/workspace/headless/labels.d.ts +10 -0
- package/dist/workspace/headless/labels.js +11 -1
- package/dist/workspace/headless/pages.d.ts +15 -0
- package/dist/workspace/headless/pages.js +49 -0
- package/dist/workspace/headless/tab-mark.d.ts +14 -0
- package/dist/workspace/headless/tab-mark.js +27 -0
- package/dist/workspace/headless/view.d.ts +7 -1
- package/dist/workspace/index.d.ts +3 -2
- package/dist/workspace/index.js +3 -2
- package/dist/workspace/testing/index.js +6 -0
- package/dist/workspace/workspace-key-commands.js +3 -3
- package/package.json +2 -2
- package/src/styles/motion.css +13 -0
- package/src/styles/onboarding.css +0 -1
- package/src/styles/primitives.css +10 -0
- package/src/styles/workspace.css +17 -0
- package/dist/session/TodosPanel.d.ts +0 -19
- package/dist/session/TodosPanel.js +0 -251
- package/dist/session/headless/todos.d.ts +0 -22
- package/dist/session/headless/todos.js +0 -38
|
@@ -5,4 +5,5 @@ import { InteractionCard, InteractionCardProps } from "./InteractionCard.js";
|
|
|
5
5
|
import { PlanBody, PlanBodyProps, PlanCard, PlanCardProps } from "./PlanCard.js";
|
|
6
6
|
import { QuestionField, QuestionFieldProps, isRequired } from "./QuestionField.js";
|
|
7
7
|
import { AnsweredQuestions, AnsweredQuestionsProps, QuestionForm, QuestionFormProps, seedDefaults } from "./QuestionForm.js";
|
|
8
|
-
|
|
8
|
+
import { SecretInput, SecretInputProps } from "./SecretInput.js";
|
|
9
|
+
export { AnsweredQuestions, AnsweredQuestionsProps, HostInteractions, HostInteractionsProps, InboxPanel, InboxPanelProps, InteractionCard, InteractionCardProps, PlanBody, PlanBodyProps, PlanCard, PlanCardProps, QuestionField, QuestionFieldProps, QuestionForm, QuestionFormProps, SecretInput, SecretInputProps, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useAllInteractions, useInteractionHead, usePendingInteractions } from "./hooks.js";
|
|
2
2
|
import { PlanBody, PlanCard } from "./PlanCard.js";
|
|
3
|
+
import { SecretInput } from "./SecretInput.js";
|
|
3
4
|
import { QuestionField, isRequired } from "./QuestionField.js";
|
|
4
5
|
import { AnsweredQuestions, QuestionForm, seedDefaults } from "./QuestionForm.js";
|
|
5
6
|
import { InteractionCard } from "./InteractionCard.js";
|
|
6
7
|
import { HostInteractions } from "./HostInteractions.js";
|
|
7
8
|
import { InboxPanel } from "./InboxPanel.js";
|
|
8
|
-
export { AnsweredQuestions, HostInteractions, InboxPanel, InteractionCard, PlanBody, PlanCard, QuestionField, QuestionForm, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
|
|
9
|
+
export { AnsweredQuestions, HostInteractions, InboxPanel, InteractionCard, PlanBody, PlanCard, QuestionField, QuestionForm, SecretInput, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
|
|
@@ -525,6 +525,7 @@ function SessionSidebar(props) {
|
|
|
525
525
|
isRenaming,
|
|
526
526
|
archived: session.archived === true,
|
|
527
527
|
favorite: session.favorite,
|
|
528
|
+
scheduled: Boolean(session.scheduleId),
|
|
528
529
|
renameValue: isRenaming ? renameValue : "",
|
|
529
530
|
menuOpen: menuForId === session.id,
|
|
530
531
|
...rowHandlers,
|
|
@@ -548,6 +549,7 @@ function SessionSidebar(props) {
|
|
|
548
549
|
isRenaming: session.id === renamingId,
|
|
549
550
|
archived: session.archived === true,
|
|
550
551
|
favorite: session.favorite,
|
|
552
|
+
scheduled: Boolean(session.scheduleId),
|
|
551
553
|
renameValue: session.id === renamingId ? renameValue : "",
|
|
552
554
|
menuOpen: menuForId === session.id,
|
|
553
555
|
...rowHandlers,
|
|
@@ -20,17 +20,22 @@ interface SidebarFilterMenuProps {
|
|
|
20
20
|
* and groupings join the menu, and the space's own grouping and sort are a choice.
|
|
21
21
|
*/
|
|
22
22
|
query?: Pick<SidebarQueryLayer, 'space' | 'filters' | 'sorts' | 'groups'>;
|
|
23
|
+
/**
|
|
24
|
+
* Offer the Origin filter: All, Scheduled (a reminder started the session), Not scheduled. Pass it while
|
|
25
|
+
* reminders are on. A view that has an origin picked shows the row anyway, so it can be cleared.
|
|
26
|
+
*/
|
|
27
|
+
origin?: boolean;
|
|
23
28
|
/** Saves the view as a space of its own. Absent: no such row. */
|
|
24
29
|
onSaveView?: () => void;
|
|
25
30
|
/** Extra classes on the trigger button. */
|
|
26
31
|
className?: string;
|
|
27
32
|
}
|
|
28
33
|
/**
|
|
29
|
-
* The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, sort,
|
|
34
|
+
* The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, origin, sort,
|
|
30
35
|
* and what extensions contribute (filters, sorts, groupings), with Save view as space.
|
|
31
36
|
*
|
|
32
37
|
* @param props - The {@link SidebarFilterMenuProps}.
|
|
33
38
|
*/
|
|
34
|
-
declare function SidebarFilterMenu({ view, projects, onChange, hosts, agents, agentNames: agentNamesProp, query, onSaveView, className }: SidebarFilterMenuProps): import("react").JSX.Element;
|
|
39
|
+
declare function SidebarFilterMenu({ view, projects, onChange, hosts, agents, agentNames: agentNamesProp, query, origin, onSaveView, className }: SidebarFilterMenuProps): import("react").JSX.Element;
|
|
35
40
|
//#endregion
|
|
36
41
|
export { SidebarFilterMenu, SidebarFilterMenuProps };
|
|
@@ -26,6 +26,12 @@ const SORTS = [
|
|
|
26
26
|
"recency"
|
|
27
27
|
];
|
|
28
28
|
const ALL_AGENTS = "__all__";
|
|
29
|
+
const ALL_ORIGINS = "all";
|
|
30
|
+
const ORIGIN_CHOICES = [
|
|
31
|
+
ALL_ORIGINS,
|
|
32
|
+
"scheduled",
|
|
33
|
+
"unscheduled"
|
|
34
|
+
];
|
|
29
35
|
const ANY = "__any__";
|
|
30
36
|
const SPACE = "@space";
|
|
31
37
|
const NO_GROUPS = [];
|
|
@@ -43,12 +49,12 @@ function withExtension(view, change) {
|
|
|
43
49
|
return out;
|
|
44
50
|
}
|
|
45
51
|
/**
|
|
46
|
-
* The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, sort,
|
|
52
|
+
* The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, origin, sort,
|
|
47
53
|
* and what extensions contribute (filters, sorts, groupings), with Save view as space.
|
|
48
54
|
*
|
|
49
55
|
* @param props - The {@link SidebarFilterMenuProps}.
|
|
50
56
|
*/
|
|
51
|
-
function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, agentNames: agentNamesProp, query, onSaveView, className }) {
|
|
57
|
+
function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, agentNames: agentNamesProp, query, origin = false, onSaveView, className }) {
|
|
52
58
|
const labels = useChatLabels();
|
|
53
59
|
const catalogNames = useAgentNames();
|
|
54
60
|
const agentNames = agentNamesProp ?? catalogNames;
|
|
@@ -209,6 +215,23 @@ function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, ag
|
|
|
209
215
|
onChange: (next) => onChange({ agent: next === ALL_AGENTS ? null : next })
|
|
210
216
|
});
|
|
211
217
|
}
|
|
218
|
+
if (origin || view.origin) {
|
|
219
|
+
const current = view.origin ?? ALL_ORIGINS;
|
|
220
|
+
out.push({
|
|
221
|
+
kind: "choice",
|
|
222
|
+
id: "origin",
|
|
223
|
+
label: labels.filterOrigin,
|
|
224
|
+
placement: "filter",
|
|
225
|
+
value: labels.filterOrigins[current],
|
|
226
|
+
atDefault: !view.origin,
|
|
227
|
+
options: ORIGIN_CHOICES.map((id) => ({
|
|
228
|
+
id,
|
|
229
|
+
label: labels.filterOrigins[id]
|
|
230
|
+
})),
|
|
231
|
+
current,
|
|
232
|
+
onChange: (next) => onChange({ origin: next === ALL_ORIGINS ? null : next })
|
|
233
|
+
});
|
|
234
|
+
}
|
|
212
235
|
return out;
|
|
213
236
|
}, [
|
|
214
237
|
view,
|
|
@@ -222,6 +245,7 @@ function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, ag
|
|
|
222
245
|
query,
|
|
223
246
|
agents,
|
|
224
247
|
agentNames,
|
|
248
|
+
origin,
|
|
225
249
|
labels,
|
|
226
250
|
onChange
|
|
227
251
|
]);
|
|
@@ -60,6 +60,8 @@ interface SidebarSessionRowProps extends SidebarRowHandlers {
|
|
|
60
60
|
archived: boolean;
|
|
61
61
|
/** Starred. */
|
|
62
62
|
favorite?: boolean;
|
|
63
|
+
/** A reminder started it (zidane's `scheduleId`): a clock mark beside the title. */
|
|
64
|
+
scheduled?: boolean;
|
|
63
65
|
/** The rename field's text. */
|
|
64
66
|
renameValue: string;
|
|
65
67
|
/** Its menu is the open one. */
|
|
@@ -90,6 +92,6 @@ interface SidebarSessionRowProps extends SidebarRowHandlers {
|
|
|
90
92
|
style?: CSSProperties;
|
|
91
93
|
}
|
|
92
94
|
/** Renders one session of the sidebar list. Memoized: keep every prop stable. */
|
|
93
|
-
declare const SidebarSessionRow: import("react").MemoExoticComponent<({ sessionId, title, cwd, hostId, hostBadge, spaceId, isMain, isActive, isRenaming, archived, favorite, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }: SidebarSessionRowProps) => import("react").JSX.Element>;
|
|
95
|
+
declare const SidebarSessionRow: import("react").MemoExoticComponent<({ sessionId, title, cwd, hostId, hostBadge, spaceId, isMain, isActive, isRenaming, archived, favorite, scheduled, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }: SidebarSessionRowProps) => import("react").JSX.Element>;
|
|
94
96
|
//#endregion
|
|
95
97
|
export { SidebarRowHandlers, SidebarSessionRow, SidebarSessionRowProps };
|
|
@@ -32,7 +32,7 @@ const ExcerptHighlight = memo(({ text, query }) => {
|
|
|
32
32
|
});
|
|
33
33
|
ExcerptHighlight.displayName = "ExcerptHighlight";
|
|
34
34
|
/** Renders one session of the sidebar list. Memoized: keep every prop stable. */
|
|
35
|
-
const SidebarSessionRow = memo(({ sessionId, title, cwd, hostId, hostBadge = true, spaceId, isMain, isActive, isRenaming, archived, favorite = false, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }) => {
|
|
35
|
+
const SidebarSessionRow = memo(({ sessionId, title, cwd, hostId, hostBadge = true, spaceId, isMain, isActive, isRenaming, archived, favorite = false, scheduled = false, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }) => {
|
|
36
36
|
const { SessionStatusDot, RowMeta, RowArtifacts } = live;
|
|
37
37
|
const host = useSidebarHost();
|
|
38
38
|
const labels = useSidebarLabels();
|
|
@@ -106,10 +106,15 @@ const SidebarSessionRow = memo(({ sessionId, title, cwd, hostId, hostBadge = tru
|
|
|
106
106
|
surface: "title",
|
|
107
107
|
links: false
|
|
108
108
|
}) : void 0,
|
|
109
|
-
...decoration && (decoration.icon || decoration.chips.length > 0 || decoration.component) ? { badges: /* @__PURE__ */ jsx(
|
|
109
|
+
...scheduled || decoration && (decoration.icon || decoration.chips.length > 0 || decoration.component) ? { badges: /* @__PURE__ */ jsxs(Fragment, { children: [scheduled && /* @__PURE__ */ jsx("span", {
|
|
110
|
+
role: "img",
|
|
111
|
+
"aria-label": labels.rowScheduled,
|
|
112
|
+
title: labels.rowScheduled,
|
|
113
|
+
className: "i-ph-clock shrink-0 text-zg-label text-[var(--zg-text-muted)]"
|
|
114
|
+
}), decoration && /* @__PURE__ */ jsx(SidebarDecoration, {
|
|
110
115
|
decoration,
|
|
111
116
|
sessionId
|
|
112
|
-
}) } : {},
|
|
117
|
+
})] }) } : {},
|
|
113
118
|
meta: typeof updatedAt === "number" ? /* @__PURE__ */ jsx(RowMeta, {
|
|
114
119
|
sessionId,
|
|
115
120
|
updatedAt,
|
|
@@ -20,7 +20,7 @@ import { useSessionActivity } from "./useSessionActivity.js";
|
|
|
20
20
|
import { useSessionBadges } from "./useSessionBadges.js";
|
|
21
21
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
22
22
|
import { memo, useCallback, useEffect, useMemo, useReducer, useState } from "react";
|
|
23
|
-
import { sessionBadgeTarget } from "zidane/chat/pure";
|
|
23
|
+
import { isRunEstimated, sessionBadgeTarget } from "zidane/chat/pure";
|
|
24
24
|
//#region src/chat/sidebar/sidebar-live.tsx
|
|
25
25
|
/**
|
|
26
26
|
* What a sidebar row says about its session beyond the title, from the
|
|
@@ -319,10 +319,14 @@ function createSidebarLive(options) {
|
|
|
319
319
|
function useSessionEstimate(sessionId) {
|
|
320
320
|
return useRunEstimate(estimatesStore ? sessionId : void 0, void 0, estimatesStore);
|
|
321
321
|
}
|
|
322
|
-
/**
|
|
322
|
+
/**
|
|
323
|
+
* The run's time: what it has left while the host estimated it, else how long it has gone (with a mark
|
|
324
|
+
* saying why, when the host could not estimate it).
|
|
325
|
+
*/
|
|
323
326
|
function RunTime({ sessionId }) {
|
|
324
327
|
const estimate = useSessionEstimate(sessionId);
|
|
325
|
-
|
|
328
|
+
if (estimate && isRunEstimated(estimate)) return /* @__PURE__ */ jsx(EstimateChip, { estimate });
|
|
329
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [estimate && /* @__PURE__ */ jsx(RunEstimateChip, { estimate }), /* @__PURE__ */ jsx(Elapsed, { sessionId })] });
|
|
326
330
|
}
|
|
327
331
|
/**
|
|
328
332
|
* The estimate chip. Its tooltip says how long the run has gone, read from the run's start when the
|
|
@@ -352,7 +356,7 @@ function createSidebarLive(options) {
|
|
|
352
356
|
className: "self-center w-1.5 h-1.5 rounded-full bg-[var(--zg-accent)]"
|
|
353
357
|
}),
|
|
354
358
|
labels.rowWorking,
|
|
355
|
-
estimate && /* @__PURE__ */ jsx(EstimateChip, { estimate })
|
|
359
|
+
estimate && (isRunEstimated(estimate) ? /* @__PURE__ */ jsx(EstimateChip, { estimate }) : /* @__PURE__ */ jsx(RunEstimateChip, { estimate }))
|
|
356
360
|
]
|
|
357
361
|
}) : /* @__PURE__ */ jsx(Ago, {
|
|
358
362
|
at: updatedAt,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RunFailure } from "../headless/transcript/run-failures.js";
|
|
2
|
+
import "../headless/transcript/index.js";
|
|
3
|
+
import { CSSProperties } from "react";
|
|
4
|
+
import { AuthFailure } from "zidane/chat/pure";
|
|
5
|
+
import { StreamEvent } from "zidane/chat";
|
|
6
|
+
//#region src/chat/transcript/AuthFailureCard.d.ts
|
|
7
|
+
/** Props for {@link AuthFailureCard}. */
|
|
8
|
+
interface AuthFailureCardProps {
|
|
9
|
+
/** The sign-in that failed (`detail.auth`). */
|
|
10
|
+
auth: AuthFailure;
|
|
11
|
+
/** The run's stop reason, shown muted under the headline. */
|
|
12
|
+
text: string;
|
|
13
|
+
/** The error's structured detail: the provider's own words, for the tooltip and Copy details. */
|
|
14
|
+
detail?: StreamEvent['detail'];
|
|
15
|
+
/** How the run ended and how it would resume. */
|
|
16
|
+
failure: RunFailure;
|
|
17
|
+
/** The card is the transcript's last word, with no run in progress: it offers its actions. */
|
|
18
|
+
resumable: boolean;
|
|
19
|
+
/** Called with the prompt that resumes the run (Retry, and after a sign-in or a switch). Absent: no Retry. */
|
|
20
|
+
onResume?: (prompt: string) => void;
|
|
21
|
+
/** Extra classes on the root element. */
|
|
22
|
+
className?: string;
|
|
23
|
+
/** Inline styles on the root element, merged after the component's own. */
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Renders a sign-in failure as a card with its fixes; see the module
|
|
28
|
+
* comment for the rules.
|
|
29
|
+
*
|
|
30
|
+
* @param props - Component props.
|
|
31
|
+
*/
|
|
32
|
+
declare const AuthFailureCard: import("react").MemoExoticComponent<({ auth, text, detail, failure, resumable, onResume, className, style }: AuthFailureCardProps) => import("react").JSX.Element>;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { AuthFailureCard, AuthFailureCardProps };
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { buttonClass } from "../../components/button.js";
|
|
2
|
+
import "../../components/Form.js";
|
|
3
|
+
import { useReadable } from "../headless/store.js";
|
|
4
|
+
import { RoutedLink } from "../../extensions/links.js";
|
|
5
|
+
import { useChatLabels } from "../useChatLabels.js";
|
|
6
|
+
import { useTranscriptActions } from "./actions.js";
|
|
7
|
+
import { failureTooltip } from "../headless/transcript/run-failures.js";
|
|
8
|
+
import { authFailureDetails, createAuthFixes, isAuthFixed, planAuthCard } from "../headless/transcript/auth-failure.js";
|
|
9
|
+
import { useSignIn } from "../../onboarding/useSignIn.js";
|
|
10
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { memo, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
12
|
+
import { CONTINUE_PROMPT, authOffersSignInFallback, authPrimaryAction } from "zidane/chat/pure";
|
|
13
|
+
//#region src/chat/transcript/AuthFailureCard.tsx
|
|
14
|
+
/**
|
|
15
|
+
* A run that stopped because a sign-in failed (`detail.auth`): instead of the
|
|
16
|
+
* quiet "Stopped" line, a compact card with what failed (the provider's
|
|
17
|
+
* name, the account), the reason, and what fixes it, in place: sign that
|
|
18
|
+
* account in again (the browser flow runs inside the card, a pasted code
|
|
19
|
+
* included), retry, switch to another stored account, open Settings there,
|
|
20
|
+
* or copy the details. A sign-in that succeeds resends the failed prompt
|
|
21
|
+
* when the stop is still the transcript's last word.
|
|
22
|
+
*
|
|
23
|
+
* Only the last stop is interactive (the rule the Retry button follows);
|
|
24
|
+
* older cards keep their headline. Once a sign-in is fixed, every card for
|
|
25
|
+
* it in the session says so. The accounts come from the transcript actions
|
|
26
|
+
* (`TranscriptActions.accounts`): a member the app leaves out hides its
|
|
27
|
+
* button.
|
|
28
|
+
*/
|
|
29
|
+
/** The sign-ins fixed from a card in this page's life, per session. */
|
|
30
|
+
const FIXES = createAuthFixes();
|
|
31
|
+
const BODY_TEXT = "text-sm leading-[1.6]";
|
|
32
|
+
const BTN_MAIN = buttonClass({
|
|
33
|
+
variant: "primary",
|
|
34
|
+
size: "xs"
|
|
35
|
+
});
|
|
36
|
+
const BTN_OTHER = buttonClass({
|
|
37
|
+
variant: "secondary",
|
|
38
|
+
size: "xs"
|
|
39
|
+
});
|
|
40
|
+
const BTN_QUIET = buttonClass({
|
|
41
|
+
variant: "ghost",
|
|
42
|
+
size: "xs"
|
|
43
|
+
});
|
|
44
|
+
const COPIED_MS = 1200;
|
|
45
|
+
const noop = () => () => {};
|
|
46
|
+
const idle = () => void 0;
|
|
47
|
+
/** A host's provider list, re-rendering when it changes (`undefined` without one). */
|
|
48
|
+
function useProviderList(resource) {
|
|
49
|
+
return useSyncExternalStore(resource ? resource.subscribe : noop, resource ? resource.get : idle, resource ? resource.get : idle);
|
|
50
|
+
}
|
|
51
|
+
/** A rejected action's words: a `SettingsError`'s detail, an `Error`'s message. */
|
|
52
|
+
function messageOf(error) {
|
|
53
|
+
if (error && typeof error === "object") {
|
|
54
|
+
if ("detail" in error && typeof error.detail === "string" && error.detail) return error.detail;
|
|
55
|
+
if ("message" in error && typeof error.message === "string" && error.message) return error.message;
|
|
56
|
+
if ("kind" in error && typeof error.kind === "string") return error.kind;
|
|
57
|
+
}
|
|
58
|
+
return String(error);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Renders a sign-in failure as a card with its fixes; see the module
|
|
62
|
+
* comment for the rules.
|
|
63
|
+
*
|
|
64
|
+
* @param props - Component props.
|
|
65
|
+
*/
|
|
66
|
+
const AuthFailureCard = memo(function AuthFailureCard({ auth, text, detail, failure, resumable, onResume, className, style }) {
|
|
67
|
+
const labels = useChatLabels();
|
|
68
|
+
const { sessionId, accounts } = useTranscriptActions();
|
|
69
|
+
const cwd = accounts?.cwd ?? "";
|
|
70
|
+
const providers = auth.source === "provider" ? accounts?.providers : void 0;
|
|
71
|
+
const list = useProviderList(useMemo(() => providers?.list(cwd) ?? null, [providers, cwd]))?.data;
|
|
72
|
+
const plan = useMemo(() => planAuthCard(auth, list), [auth, list]);
|
|
73
|
+
const fixes = useReadable(FIXES.fixed(sessionId));
|
|
74
|
+
const headline = labels.authHeadline(auth, plan.label);
|
|
75
|
+
const prompt = failure.resume === "retry" && failure.prompt ? failure.prompt : CONTINUE_PROMPT;
|
|
76
|
+
const latest = useRef({
|
|
77
|
+
resumable,
|
|
78
|
+
onResume,
|
|
79
|
+
prompt
|
|
80
|
+
});
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
latest.current = {
|
|
83
|
+
resumable,
|
|
84
|
+
onResume,
|
|
85
|
+
prompt
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
/** Resends the failed prompt if the stop is still the last word; says whether it did. */
|
|
89
|
+
const resumeIfLast = () => {
|
|
90
|
+
const now = latest.current;
|
|
91
|
+
if (!now.resumable || !now.onResume) return false;
|
|
92
|
+
now.onResume(now.prompt);
|
|
93
|
+
return true;
|
|
94
|
+
};
|
|
95
|
+
const [outcome, setOutcome] = useState(null);
|
|
96
|
+
const signIn = useSignIn(() => {
|
|
97
|
+
FIXES.add(sessionId, auth);
|
|
98
|
+
setOutcome(resumeIfLast() ? "retrying" : "signed-in");
|
|
99
|
+
});
|
|
100
|
+
const [switching, setSwitching] = useState(null);
|
|
101
|
+
const [copied, setCopied] = useState(false);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (!copied) return void 0;
|
|
104
|
+
const timer = window.setTimeout(() => setCopied(false), COPIED_MS);
|
|
105
|
+
return () => window.clearTimeout(timer);
|
|
106
|
+
}, [copied]);
|
|
107
|
+
const flow = signIn.state;
|
|
108
|
+
const running = flow !== null && flow.kind !== "done" && flow.kind !== "error";
|
|
109
|
+
const fixed = outcome !== null || !resumable && !running && isAuthFixed(fixes, auth);
|
|
110
|
+
const open = resumable || running;
|
|
111
|
+
const begin = useMemo(() => {
|
|
112
|
+
if (auth.source === "provider") {
|
|
113
|
+
const provider = plan.provider;
|
|
114
|
+
if (!providers?.signIn || !provider?.oauth) return null;
|
|
115
|
+
const replaceKey = plan.replaceKey;
|
|
116
|
+
return () => providers.signIn(provider.key, replaceKey ? { replaceKey } : void 0);
|
|
117
|
+
}
|
|
118
|
+
const mcp = accounts?.mcp;
|
|
119
|
+
if (auth.source === "mcp" && mcp?.signIn) return () => mcp.signIn(cwd, auth.provider);
|
|
120
|
+
return null;
|
|
121
|
+
}, [
|
|
122
|
+
auth,
|
|
123
|
+
plan,
|
|
124
|
+
providers,
|
|
125
|
+
accounts?.mcp,
|
|
126
|
+
cwd
|
|
127
|
+
]);
|
|
128
|
+
const other = plan.otherAccount;
|
|
129
|
+
const canSwitch = Boolean(other?.key && plan.provider && providers?.setPreferred);
|
|
130
|
+
const switchAccount = async () => {
|
|
131
|
+
setSwitching({});
|
|
132
|
+
try {
|
|
133
|
+
await providers.setPreferred(cwd, plan.provider.key, { key: other.key });
|
|
134
|
+
setSwitching(null);
|
|
135
|
+
resumeIfLast();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
setSwitching({ error: messageOf(error) });
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const switchBusy = switching !== null && switching.error === void 0;
|
|
141
|
+
const primary = authPrimaryAction(auth);
|
|
142
|
+
const offerSignIn = begin !== null && (primary === "sign-in" || authOffersSignInFallback(auth));
|
|
143
|
+
const offerRetry = onResume !== void 0 && (primary === "retry" || !offerSignIn);
|
|
144
|
+
const otherLabel = other ? other.label ?? other.detail : "";
|
|
145
|
+
const copy = async () => {
|
|
146
|
+
try {
|
|
147
|
+
await navigator.clipboard.writeText(authFailureDetails(headline, text, detail?.raw));
|
|
148
|
+
setCopied(true);
|
|
149
|
+
} catch {}
|
|
150
|
+
};
|
|
151
|
+
const signInButton = offerSignIn && /* @__PURE__ */ jsxs("button", {
|
|
152
|
+
type: "button",
|
|
153
|
+
className: primary === "sign-in" ? BTN_MAIN : BTN_OTHER,
|
|
154
|
+
onClick: () => signIn.start(begin),
|
|
155
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
156
|
+
"aria-hidden": true,
|
|
157
|
+
className: "i-ph-sign-in"
|
|
158
|
+
}), labels.authSignInAgain]
|
|
159
|
+
});
|
|
160
|
+
const retryButton = offerRetry && /* @__PURE__ */ jsxs("button", {
|
|
161
|
+
type: "button",
|
|
162
|
+
className: primary === "retry" ? BTN_MAIN : BTN_OTHER,
|
|
163
|
+
title: failure.resume === "retry" ? labels.retryHint : labels.continueHint,
|
|
164
|
+
onClick: () => onResume(prompt),
|
|
165
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
166
|
+
"aria-hidden": true,
|
|
167
|
+
className: "i-ph-arrow-clockwise"
|
|
168
|
+
}), labels.retry]
|
|
169
|
+
});
|
|
170
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
171
|
+
role: "group",
|
|
172
|
+
"aria-label": labels.authCard,
|
|
173
|
+
"data-testid": "run-failure",
|
|
174
|
+
"data-cause": failure.cause,
|
|
175
|
+
"data-auth": auth.kind,
|
|
176
|
+
"data-fixed": fixed ? "" : void 0,
|
|
177
|
+
className: [`flex flex-col gap-1 min-w-0 pl-3 border-l-2 ${fixed ? "border-zg-success" : "border-zg-danger"} ${BODY_TEXT}`, className].filter(Boolean).join(" "),
|
|
178
|
+
style,
|
|
179
|
+
children: [
|
|
180
|
+
/* @__PURE__ */ jsxs("div", {
|
|
181
|
+
className: "flex items-center gap-2 min-w-0",
|
|
182
|
+
title: failureTooltip(text, detail, labels.resetsAt),
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ jsx("span", {
|
|
185
|
+
"aria-hidden": true,
|
|
186
|
+
className: `shrink-0 ${fixed ? "i-ph-check-circle text-zg-success" : "i-ph-key text-zg-danger"}`
|
|
187
|
+
}),
|
|
188
|
+
/* @__PURE__ */ jsx("span", {
|
|
189
|
+
className: "min-w-0 truncate font-medium text-[var(--zg-text)]",
|
|
190
|
+
children: headline
|
|
191
|
+
}),
|
|
192
|
+
fixed && outcome === null && /* @__PURE__ */ jsxs("span", {
|
|
193
|
+
className: "zg-meta-chip zg-meta shrink-0 gap-1 text-zg-success",
|
|
194
|
+
"data-testid": "auth-fixed",
|
|
195
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
196
|
+
"aria-hidden": true,
|
|
197
|
+
className: "i-ph-check"
|
|
198
|
+
}), labels.authFixed]
|
|
199
|
+
})
|
|
200
|
+
]
|
|
201
|
+
}),
|
|
202
|
+
(open || outcome !== null) && text && /* @__PURE__ */ jsx("div", {
|
|
203
|
+
className: "min-w-0 text-[var(--zg-text-muted)] whitespace-pre-wrap break-words",
|
|
204
|
+
children: text
|
|
205
|
+
}),
|
|
206
|
+
outcome !== null ? /* @__PURE__ */ jsxs("div", {
|
|
207
|
+
role: "status",
|
|
208
|
+
className: "flex items-center gap-1.5 text-zg-success",
|
|
209
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
210
|
+
"aria-hidden": true,
|
|
211
|
+
className: "i-ph-check"
|
|
212
|
+
}), outcome === "retrying" ? labels.authSignedInRetrying : labels.authSignedIn]
|
|
213
|
+
}) : !open ? null : running ? /* @__PURE__ */ jsx(SignInProgress, {
|
|
214
|
+
state: flow,
|
|
215
|
+
submit: signIn.submit,
|
|
216
|
+
onCancel: signIn.cancel
|
|
217
|
+
}) : flow?.kind === "error" ? /* @__PURE__ */ jsxs("div", {
|
|
218
|
+
className: "flex flex-col gap-1.5",
|
|
219
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
220
|
+
role: "alert",
|
|
221
|
+
className: "text-zg-danger break-words",
|
|
222
|
+
children: labels.authFailed(flow.message)
|
|
223
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
224
|
+
className: "flex flex-wrap items-center gap-1.5",
|
|
225
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
226
|
+
type: "button",
|
|
227
|
+
className: BTN_MAIN,
|
|
228
|
+
onClick: () => signIn.start(begin),
|
|
229
|
+
children: labels.authTryAgain
|
|
230
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
231
|
+
type: "button",
|
|
232
|
+
className: BTN_OTHER,
|
|
233
|
+
onClick: signIn.cancel,
|
|
234
|
+
children: labels.authCancel
|
|
235
|
+
})]
|
|
236
|
+
})]
|
|
237
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
238
|
+
className: "flex flex-col gap-1.5",
|
|
239
|
+
children: [switching?.error !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
240
|
+
role: "alert",
|
|
241
|
+
className: "text-zg-danger break-words",
|
|
242
|
+
children: labels.authFailed(switching.error)
|
|
243
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
244
|
+
className: "flex flex-wrap items-center gap-1.5",
|
|
245
|
+
children: [
|
|
246
|
+
primary === "sign-in" ? signInButton : retryButton,
|
|
247
|
+
primary === "sign-in" ? retryButton : signInButton,
|
|
248
|
+
canSwitch && /* @__PURE__ */ jsxs("button", {
|
|
249
|
+
type: "button",
|
|
250
|
+
className: BTN_OTHER,
|
|
251
|
+
disabled: switchBusy,
|
|
252
|
+
onClick: () => void switchAccount(),
|
|
253
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
254
|
+
"aria-hidden": true,
|
|
255
|
+
className: "i-ph-user-switch"
|
|
256
|
+
}), switchBusy ? labels.authSwitching(otherLabel) : labels.authUseAccount(otherLabel)]
|
|
257
|
+
}),
|
|
258
|
+
accounts?.openSettings && /* @__PURE__ */ jsxs("button", {
|
|
259
|
+
type: "button",
|
|
260
|
+
className: BTN_QUIET,
|
|
261
|
+
title: labels.authSettingsHint,
|
|
262
|
+
onClick: () => accounts.openSettings(plan.settings),
|
|
263
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
264
|
+
"aria-hidden": true,
|
|
265
|
+
className: "i-ph-gear"
|
|
266
|
+
}), labels.authSettings]
|
|
267
|
+
}),
|
|
268
|
+
/* @__PURE__ */ jsxs("button", {
|
|
269
|
+
type: "button",
|
|
270
|
+
className: BTN_QUIET,
|
|
271
|
+
onClick: () => void copy(),
|
|
272
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
273
|
+
"aria-hidden": true,
|
|
274
|
+
className: copied ? "i-ph-check" : "i-ph-copy"
|
|
275
|
+
}), copied ? labels.authCopied : labels.authCopyDetails]
|
|
276
|
+
})
|
|
277
|
+
]
|
|
278
|
+
})]
|
|
279
|
+
})
|
|
280
|
+
]
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
/** A sign-in while it runs, inside the card: where it is, the page's link, a pasted code, Cancel. */
|
|
284
|
+
function SignInProgress({ state, submit, onCancel }) {
|
|
285
|
+
const labels = useChatLabels();
|
|
286
|
+
const [pasted, setPasted] = useState("");
|
|
287
|
+
const page = state.kind === "url" || state.kind === "device" ? state : null;
|
|
288
|
+
const instructions = state.kind === "url" && "instructions" in state && typeof state.instructions === "string" ? state.instructions : null;
|
|
289
|
+
const line = state.kind === "url" ? labels.authWaiting : state.kind === "device" ? labels.authEnterCode(state.userCode) : state.kind === "prompt" || state.kind === "progress" ? state.message : labels.authOpeningBrowser;
|
|
290
|
+
const takesInput = submit !== void 0 && (state.kind === "url" || state.kind === "prompt");
|
|
291
|
+
const send = (event) => {
|
|
292
|
+
event.preventDefault();
|
|
293
|
+
if (!pasted.trim()) return;
|
|
294
|
+
submit?.(pasted.trim());
|
|
295
|
+
setPasted("");
|
|
296
|
+
};
|
|
297
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
298
|
+
className: "flex flex-col gap-1.5",
|
|
299
|
+
"data-testid": "auth-sign-in",
|
|
300
|
+
children: [
|
|
301
|
+
/* @__PURE__ */ jsxs("div", {
|
|
302
|
+
role: "status",
|
|
303
|
+
"aria-live": "polite",
|
|
304
|
+
className: "flex items-center gap-2 min-w-0 text-[var(--zg-text)]",
|
|
305
|
+
children: [
|
|
306
|
+
/* @__PURE__ */ jsx("span", {
|
|
307
|
+
"aria-hidden": true,
|
|
308
|
+
className: "zg-spin-ring zg-loop block shrink-0 text-[var(--zg-accent)]"
|
|
309
|
+
}),
|
|
310
|
+
/* @__PURE__ */ jsx("span", {
|
|
311
|
+
className: "min-w-0 break-words",
|
|
312
|
+
children: line
|
|
313
|
+
}),
|
|
314
|
+
page && /* @__PURE__ */ jsx(RoutedLink, {
|
|
315
|
+
href: page.url,
|
|
316
|
+
source: "auth",
|
|
317
|
+
className: "shrink-0 text-[var(--zg-accent-hover)] underline underline-offset-2",
|
|
318
|
+
children: labels.authOpenPage
|
|
319
|
+
})
|
|
320
|
+
]
|
|
321
|
+
}),
|
|
322
|
+
instructions && /* @__PURE__ */ jsx("div", {
|
|
323
|
+
className: "text-[var(--zg-text-muted)] break-words",
|
|
324
|
+
children: instructions
|
|
325
|
+
}),
|
|
326
|
+
state.kind === "prompt" && state.options && /* @__PURE__ */ jsx("ol", {
|
|
327
|
+
className: "m-0 pl-5 text-[var(--zg-text-muted)]",
|
|
328
|
+
children: state.options.map((option) => /* @__PURE__ */ jsx("li", { children: option }, option))
|
|
329
|
+
}),
|
|
330
|
+
/* @__PURE__ */ jsxs("form", {
|
|
331
|
+
className: "flex flex-wrap items-center gap-1.5",
|
|
332
|
+
onSubmit: send,
|
|
333
|
+
children: [takesInput && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
|
|
334
|
+
type: "text",
|
|
335
|
+
autoComplete: "off",
|
|
336
|
+
spellCheck: false,
|
|
337
|
+
"aria-label": labels.authPaste,
|
|
338
|
+
placeholder: state.kind === "prompt" && state.placeholder ? state.placeholder : labels.authPaste,
|
|
339
|
+
value: pasted,
|
|
340
|
+
onChange: (event) => setPasted(event.target.value),
|
|
341
|
+
className: `zg-well w-full h-8 px-2.5 text-zg-ui placeholder:text-[var(--zg-text-subtle)] disabled:opacity-zg-disabled flex-1 !w-auto min-w-40 h-6`
|
|
342
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
343
|
+
type: "submit",
|
|
344
|
+
className: BTN_MAIN,
|
|
345
|
+
disabled: !pasted.trim(),
|
|
346
|
+
children: labels.authPasteSend
|
|
347
|
+
})] }), /* @__PURE__ */ jsx("button", {
|
|
348
|
+
type: "button",
|
|
349
|
+
className: BTN_OTHER,
|
|
350
|
+
onClick: onCancel,
|
|
351
|
+
children: labels.authCancel
|
|
352
|
+
})]
|
|
353
|
+
})
|
|
354
|
+
]
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
//#endregion
|
|
358
|
+
export { AuthFailureCard };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useChatLabels } from "../useChatLabels.js";
|
|
2
2
|
import { ProseMarkdown } from "./ProseMarkdown.js";
|
|
3
|
+
import { useOptionalWorkspaceActions, useOptionalWorkspaceView } from "../../workspace/WorkspaceProvider.js";
|
|
3
4
|
import { PlanBody } from "../interactions/PlanCard.js";
|
|
4
5
|
import { AnsweredQuestions } from "../interactions/QuestionForm.js";
|
|
5
6
|
import { TodoListView } from "../../session/TodoList.js";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { SECRETS_PANEL_ID } from "zidane/chat/pure";
|
|
7
9
|
//#region src/chat/transcript/InteractionToolBody.tsx
|
|
8
10
|
/**
|
|
9
11
|
* The tools this body knows how to render.
|
|
@@ -20,7 +22,7 @@ function hasInteractionBody(tool) {
|
|
|
20
22
|
function parseResult(result) {
|
|
21
23
|
if (!result) return null;
|
|
22
24
|
try {
|
|
23
|
-
const parsed = JSON.parse(result);
|
|
25
|
+
const parsed = JSON.parse(result.split("\n\n", 1)[0]);
|
|
24
26
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
25
27
|
} catch {
|
|
26
28
|
return null;
|
|
@@ -109,6 +111,12 @@ function waiting(tool, label) {
|
|
|
109
111
|
label
|
|
110
112
|
}) : null;
|
|
111
113
|
}
|
|
114
|
+
/** Opens the Secrets tab, when the workspace around offers it (`Settings.secrets` on). */
|
|
115
|
+
function useOpenSecrets() {
|
|
116
|
+
const actions = useOptionalWorkspaceActions();
|
|
117
|
+
const offered = useOptionalWorkspaceView()?.tabs.some((tab) => tab.id === SECRETS_PANEL_ID) ?? false;
|
|
118
|
+
return actions && offered ? () => actions.focusTab(SECRETS_PANEL_ID) : void 0;
|
|
119
|
+
}
|
|
112
120
|
/**
|
|
113
121
|
* The expanded body of a `present_plan`, `ask_user` or `todowrite` call (see the module comment); `null` for any other.
|
|
114
122
|
*
|
|
@@ -116,6 +124,7 @@ function waiting(tool, label) {
|
|
|
116
124
|
*/
|
|
117
125
|
function InteractionToolBody({ tool }) {
|
|
118
126
|
const labels = useChatLabels();
|
|
127
|
+
const openSecrets = useOpenSecrets();
|
|
119
128
|
if (!hasInteractionBody(tool)) return null;
|
|
120
129
|
const input = tool.rawInput;
|
|
121
130
|
const response = parseResult(tool.result);
|
|
@@ -162,7 +171,8 @@ function InteractionToolBody({ tool }) {
|
|
|
162
171
|
answers: answers ?? {},
|
|
163
172
|
instructions,
|
|
164
173
|
id: tool.id,
|
|
165
|
-
Markdown: ProseMarkdown
|
|
174
|
+
Markdown: ProseMarkdown,
|
|
175
|
+
onOpenSecrets: openSecrets
|
|
166
176
|
}),
|
|
167
177
|
!answers && (waiting(tool, labels.interactionWaitingAnswers) ?? (tool.result ? /* @__PURE__ */ jsx(Outcome, {
|
|
168
178
|
icon: "i-ph-minus-circle",
|