@adecore/agents-react 0.39.0 → 0.40.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/dist/agents/AgentModelLabel.js +2 -1
- package/dist/agents/model-name.js +2 -1
- package/dist/agents/provider-paths.d.ts +2 -1
- package/dist/agents/provider-paths.js +7 -3
- package/dist/chat/account-choice.js +57 -28
- package/dist/chat/bookmarks.js +2 -1
- package/dist/chat/drafts.d.ts +0 -1
- package/dist/chat/drafts.js +9 -28
- package/dist/chat/logic/picker-entries.js +2 -8
- package/dist/chat/logic/resume-compaction.js +2 -5
- package/dist/chat/logic/timeline-copy.js +2 -8
- package/dist/chat/logic/timeline.js +9 -10
- package/dist/chat/logic/workflow.js +2 -4
- package/dist/chat/subagent-conversation.js +2 -1
- package/dist/chat/ui/GoalDock.js +2 -1
- package/dist/chat/ui/LimitState.js +4 -6
- package/dist/chat/ui/composer/use-continuable-turn.js +0 -1
- package/dist/chat/ui/composer/use-notice.js +2 -1
- package/dist/chat/ui/composer/use-prompt-history.js +1 -1
- package/dist/chat/ui/composer/use-prompt-menus.js +216 -253
- package/dist/chat/ui/composer/use-take-back.js +2 -2
- package/dist/chat/ui/diff/ApprovalReview.js +1 -1
- package/dist/chat/ui/highlighter.d.ts +0 -6
- package/dist/chat/ui/highlighter.js +0 -12
- package/dist/chat/ui/icons.d.ts +0 -1
- package/dist/chat/ui/icons.js +0 -3
- package/dist/chat/ui/rows/MessageRows.js +2 -5
- package/dist/chat/ui/rows/row-rhythm.js +2 -5
- package/dist/chat/ui/theme-watch.js +3 -7
- package/dist/prompts/logic/usePromptSession.js +2 -1
- package/dist/providers/AddAccountForm.js +2 -1
- package/dist/providers/CliDetail.js +104 -130
- package/dist/providers/account-actions.js +6 -9
- package/dist/state/chats.d.ts +1 -0
- package/dist/state/chats.js +6 -11
- package/dist/state/provider-accounts.d.ts +1 -1
- package/dist/state/provider-accounts.js +2 -8
- package/dist/transport.d.ts +2 -0
- package/dist/transport.js +14 -0
- package/dist/usage/ChartLogo.d.ts +5 -0
- package/dist/usage/ChartLogo.js +48 -0
- package/dist/usage/LimitsList.js +6 -16
- package/dist/usage/UsageBreakdown.js +17 -40
- package/dist/usage/UsageLimits.js +183 -211
- package/dist/usage/UsagePage.js +3 -17
- package/dist/usage/UsageSummary.js +4 -9
- package/dist/usage/limits.js +16 -31
- package/dist/usage/summary.d.ts +1 -1
- package/dist/usage/summary.js +3 -5
- package/package.json +26 -26
- package/src/agents/AccountDot.tsx +1 -0
- package/src/agents/AgentIcon.tsx +2 -0
- package/src/agents/AgentModelLabel.tsx +4 -6
- package/src/agents/ModelOptionControl.tsx +8 -0
- package/src/agents/account-limits.ts +3 -0
- package/src/agents/accounts.ts +12 -0
- package/src/agents/model-name.ts +13 -1
- package/src/agents/model-options.ts +2 -0
- package/src/agents/model-requirement.ts +4 -0
- package/src/agents/option-words.ts +2 -0
- package/src/agents/provider-paths.ts +8 -3
- package/src/agents/status-look.ts +1 -0
- package/src/chat/account-choice.ts +25 -19
- package/src/chat/actions.ts +5 -0
- package/src/chat/attachments.ts +8 -0
- package/src/chat/bookmarks.ts +13 -1
- package/src/chat/chat-client.ts +63 -0
- package/src/chat/chat-references.ts +3 -0
- package/src/chat/composer-effort.ts +5 -0
- package/src/chat/composer-send.ts +4 -0
- package/src/chat/drafts.ts +21 -17
- package/src/chat/forks.ts +4 -0
- package/src/chat/guards.ts +2 -0
- package/src/chat/index.ts +7 -0
- package/src/chat/logic/ansi.ts +47 -0
- package/src/chat/logic/bookmarks.ts +7 -0
- package/src/chat/logic/command-looks.ts +29 -0
- package/src/chat/logic/context-usage.ts +3 -0
- package/src/chat/logic/continue-after-stop.ts +5 -0
- package/src/chat/logic/effort.ts +4 -0
- package/src/chat/logic/embedded-code.ts +63 -0
- package/src/chat/logic/fork.ts +22 -0
- package/src/chat/logic/generated-image.ts +7 -0
- package/src/chat/logic/goal.ts +7 -0
- package/src/chat/logic/handback.ts +2 -0
- package/src/chat/logic/limit.ts +8 -0
- package/src/chat/logic/picker-entries.ts +16 -4
- package/src/chat/logic/resume-compaction.ts +22 -5
- package/src/chat/logic/scrubber.ts +38 -5
- package/src/chat/logic/thought.ts +5 -0
- package/src/chat/logic/thread-cards.ts +6 -0
- package/src/chat/logic/timeline-copy.ts +4 -9
- package/src/chat/logic/timeline-target.ts +15 -0
- package/src/chat/logic/timeline.ts +113 -10
- package/src/chat/logic/tools.ts +30 -0
- package/src/chat/logic/visual-height.ts +5 -0
- package/src/chat/logic/visual-viewport.ts +1 -0
- package/src/chat/logic/welcome.ts +3 -0
- package/src/chat/logic/workflow.ts +26 -7
- package/src/chat/mentions.ts +56 -0
- package/src/chat/pending-prompts.ts +16 -0
- package/src/chat/persisted-json.ts +15 -0
- package/src/chat/preferences.ts +16 -0
- package/src/chat/prompt-hold.ts +2 -0
- package/src/chat/quote.ts +7 -0
- package/src/chat/reading-width.ts +1 -0
- package/src/chat/recent-messages.ts +5 -0
- package/src/chat/resume-compaction-dismissals.ts +1 -0
- package/src/chat/stash.ts +12 -0
- package/src/chat/subagent-conversation.ts +24 -4
- package/src/chat/subagent-list.ts +14 -0
- package/src/chat/subagent-support.ts +1 -0
- package/src/chat/subagent-view.ts +9 -0
- package/src/chat/thumbnails.ts +14 -0
- package/src/chat/timeline-flash.ts +2 -0
- package/src/chat/timeline-scroll.ts +23 -0
- package/src/chat/ui/AccountPill.tsx +4 -0
- package/src/chat/ui/AnsiOutput.tsx +1 -0
- package/src/chat/ui/BookmarkMarker.tsx +5 -0
- package/src/chat/ui/BookmarkSubmenu.tsx +1 -0
- package/src/chat/ui/ChatActivity.tsx +13 -0
- package/src/chat/ui/CodeBlock.tsx +8 -0
- package/src/chat/ui/Composer.tsx +15 -0
- package/src/chat/ui/ComposerInput.tsx +22 -0
- package/src/chat/ui/DiffPool.tsx +3 -0
- package/src/chat/ui/EditDiff.tsx +5 -0
- package/src/chat/ui/GoalDock.tsx +13 -1
- package/src/chat/ui/ImageView.tsx +11 -0
- package/src/chat/ui/LimitState.tsx +23 -6
- package/src/chat/ui/Markdown.tsx +41 -0
- package/src/chat/ui/MermaidBlock.tsx +16 -0
- package/src/chat/ui/MessageActions.tsx +8 -0
- package/src/chat/ui/ModelMarks.tsx +1 -0
- package/src/chat/ui/Pickers.tsx +26 -0
- package/src/chat/ui/PromptComposer.tsx +2 -0
- package/src/chat/ui/PromptEditor.tsx +6 -0
- package/src/chat/ui/QuoteButton.tsx +12 -0
- package/src/chat/ui/ReferenceChip.tsx +3 -0
- package/src/chat/ui/ResumeCompactionDock.tsx +1 -0
- package/src/chat/ui/RowTime.tsx +1 -0
- package/src/chat/ui/RunSettings.tsx +38 -0
- package/src/chat/ui/Scrubber.tsx +14 -0
- package/src/chat/ui/SessionLine.tsx +1 -0
- package/src/chat/ui/ShellCommand.tsx +32 -0
- package/src/chat/ui/SubagentControls.tsx +7 -0
- package/src/chat/ui/SubagentInfo.tsx +1 -0
- package/src/chat/ui/SubagentStopButton.tsx +6 -0
- package/src/chat/ui/SubagentTimeline.tsx +10 -0
- package/src/chat/ui/Timeline.tsx +119 -0
- package/src/chat/ui/TimelineMenu.tsx +5 -0
- package/src/chat/ui/UnifiedDiff.tsx +6 -0
- package/src/chat/ui/UploadThumb.tsx +2 -0
- package/src/chat/ui/VisualDialogs.tsx +3 -0
- package/src/chat/ui/VisualFrame.tsx +15 -0
- package/src/chat/ui/Welcome.tsx +1 -0
- package/src/chat/ui/chip-clipboard.ts +20 -0
- package/src/chat/ui/code-lines.ts +14 -0
- package/src/chat/ui/code-theme.ts +1 -0
- package/src/chat/ui/composer/ComposerControls.tsx +5 -0
- package/src/chat/ui/composer/ComposerMenu.tsx +12 -0
- package/src/chat/ui/composer/DraftParts.tsx +2 -0
- package/src/chat/ui/composer/QueuedMessages.tsx +4 -0
- package/src/chat/ui/composer/chip-paste.ts +16 -0
- package/src/chat/ui/composer/chips.ts +6 -0
- package/src/chat/ui/composer/editor.ts +9 -0
- package/src/chat/ui/composer/insert.ts +2 -0
- package/src/chat/ui/composer/key-handler.ts +39 -0
- package/src/chat/ui/composer/keys.ts +23 -0
- package/src/chat/ui/composer/placeholder.ts +6 -0
- package/src/chat/ui/composer/prompt-picks.ts +1 -0
- package/src/chat/ui/composer/surface.ts +5 -0
- package/src/chat/ui/composer/use-chat-controls.ts +13 -0
- package/src/chat/ui/composer/use-compaction-offer.ts +3 -0
- package/src/chat/ui/composer/use-composer-menus.ts +2 -0
- package/src/chat/ui/composer/use-composer-submit.ts +27 -0
- package/src/chat/ui/composer/use-continuable-turn.ts +3 -5
- package/src/chat/ui/composer/use-draft-files.ts +24 -0
- package/src/chat/ui/composer/use-effort-stepper.ts +8 -0
- package/src/chat/ui/composer/use-notice.ts +4 -1
- package/src/chat/ui/composer/use-pending-requests.ts +3 -0
- package/src/chat/ui/composer/use-prompt-history.ts +20 -11
- package/src/chat/ui/composer/use-prompt-hold.ts +3 -0
- package/src/chat/ui/composer/use-prompt-menus.ts +34 -14
- package/src/chat/ui/composer/use-take-back.ts +20 -2
- package/src/chat/ui/diff/ApprovalReview.tsx +18 -15
- package/src/chat/ui/diff/DiffFallbackBoundary.tsx +1 -0
- package/src/chat/ui/diff/DiffOmitted.tsx +1 -0
- package/src/chat/ui/diff/DiffStack.tsx +2 -0
- package/src/chat/ui/diff/DiffUnavailable.tsx +1 -0
- package/src/chat/ui/diff/EditorEditDiff.tsx +13 -0
- package/src/chat/ui/diff/EditorPatchDiff.tsx +4 -0
- package/src/chat/ui/diff/LegacyDiffPool.tsx +2 -0
- package/src/chat/ui/diff/LegacyEditDiff.tsx +2 -0
- package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +8 -0
- package/src/chat/ui/diff/RawDiff.tsx +1 -0
- package/src/chat/ui/diff/ReviewDiff.tsx +1 -0
- package/src/chat/ui/diff/diff-source-budget.ts +8 -0
- package/src/chat/ui/diff/editor-edit-model.ts +4 -0
- package/src/chat/ui/diff/review-plan.ts +9 -0
- package/src/chat/ui/diff/review-settle.ts +1 -0
- package/src/chat/ui/diff/syntax-runtime.ts +52 -0
- package/src/chat/ui/diff/use-review-stack.ts +9 -0
- package/src/chat/ui/diff-syntax.ts +12 -0
- package/src/chat/ui/diff-theme.ts +2 -0
- package/src/chat/ui/file-links.ts +2 -0
- package/src/chat/ui/find-reveal.ts +1 -0
- package/src/chat/ui/full-diff.ts +1 -0
- package/src/chat/ui/highlighter.ts +29 -15
- package/src/chat/ui/icons.tsx +2 -4
- package/src/chat/ui/index.ts +4 -0
- package/src/chat/ui/intelligent-ui/UiBlockFrame.tsx +25 -0
- package/src/chat/ui/intelligent-ui/UiFallbackPart.tsx +1 -0
- package/src/chat/ui/intelligent-ui/UiReply.tsx +63 -0
- package/src/chat/ui/intelligent-ui/block-local.ts +5 -0
- package/src/chat/ui/intelligent-ui/chart-data.ts +15 -0
- package/src/chat/ui/intelligent-ui/node-text.ts +17 -0
- package/src/chat/ui/intelligent-ui/renderers/binding.ts +1 -0
- package/src/chat/ui/intelligent-ui/renderers/chart.tsx +31 -0
- package/src/chat/ui/intelligent-ui/renderers/choices.tsx +4 -0
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +18 -0
- package/src/chat/ui/intelligent-ui/renderers/data.tsx +11 -0
- package/src/chat/ui/intelligent-ui/renderers/inputs.tsx +13 -0
- package/src/chat/ui/intelligent-ui/renderers/links.tsx +9 -0
- package/src/chat/ui/intelligent-ui/renderers/map-slots.ts +15 -0
- package/src/chat/ui/intelligent-ui/renderers/map-style.ts +15 -0
- package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +48 -0
- package/src/chat/ui/intelligent-ui/renderers/map.tsx +20 -0
- package/src/chat/ui/intelligent-ui/renderers/place-point.ts +3 -0
- package/src/chat/ui/intelligent-ui/renderers/structure.tsx +3 -0
- package/src/chat/ui/intelligent-ui/renderers/text.tsx +8 -0
- package/src/chat/ui/intelligent-ui/reply-parts.ts +5 -0
- package/src/chat/ui/intelligent-ui/table-data.ts +17 -0
- package/src/chat/ui/intelligent-ui/use-in-view.ts +4 -0
- package/src/chat/ui/intelligent-ui/use-later.ts +4 -0
- package/src/chat/ui/intelligent-ui/use-truncated.ts +5 -0
- package/src/chat/ui/intelligent-ui/use-ui-links.ts +29 -0
- package/src/chat/ui/intelligent-ui/use-ui-queries.ts +60 -0
- package/src/chat/ui/markdown-blocks.ts +64 -0
- package/src/chat/ui/mermaid.ts +4 -0
- package/src/chat/ui/quote-selection.ts +10 -0
- package/src/chat/ui/rehype-chips.ts +5 -0
- package/src/chat/ui/rehype-fade.ts +2 -0
- package/src/chat/ui/remark-html-as-text.ts +5 -0
- package/src/chat/ui/reveal.ts +18 -0
- package/src/chat/ui/rows/ForksRow.tsx +5 -0
- package/src/chat/ui/rows/GeneratedImageRow.tsx +10 -0
- package/src/chat/ui/rows/MessageRows.tsx +29 -5
- package/src/chat/ui/rows/RowContainer.tsx +1 -0
- package/src/chat/ui/rows/Rows.tsx +2 -0
- package/src/chat/ui/rows/SubagentRow.tsx +13 -0
- package/src/chat/ui/rows/TaskRow.tsx +7 -0
- package/src/chat/ui/rows/VisualRow.tsx +4 -0
- package/src/chat/ui/rows/WorkRows.tsx +46 -0
- package/src/chat/ui/rows/WorkflowRow.tsx +10 -0
- package/src/chat/ui/rows/row-rhythm.ts +7 -5
- package/src/chat/ui/theme-watch.ts +8 -7
- package/src/chat/ui/thread-references.ts +7 -0
- package/src/chat/ui/use-diff-source-tokens.ts +8 -0
- package/src/chat/ui/useToggleSet.ts +3 -0
- package/src/chat/ui/visual-theme.ts +30 -0
- package/src/chat/visual-bridge.ts +23 -0
- package/src/chat/visual-viewport.ts +12 -0
- package/src/host-hooks.ts +6 -4
- package/src/host.ts +2 -0
- package/src/index.ts +3 -0
- package/src/lazy.tsx +9 -0
- package/src/mounted-registry.ts +4 -0
- package/src/port-transport.ts +32 -0
- package/src/prompts/index.ts +2 -0
- package/src/prompts/logic/focus.ts +5 -0
- package/src/prompts/logic/keys.ts +12 -0
- package/src/prompts/logic/prompts.ts +8 -0
- package/src/prompts/logic/subjects.ts +8 -0
- package/src/prompts/logic/useFocusAfterAnswer.ts +2 -0
- package/src/prompts/logic/usePromptSession.ts +13 -1
- package/src/prompts/ui/ApprovalBody.tsx +2 -0
- package/src/prompts/ui/PromptActions.tsx +2 -0
- package/src/prompts/ui/PromptCard.tsx +6 -0
- package/src/prompts/ui/PromptView.tsx +6 -0
- package/src/prompts/ui/QuestionBody.tsx +11 -0
- package/src/providers/AccountColors.tsx +1 -0
- package/src/providers/AccountDetail.tsx +7 -0
- package/src/providers/AccountVariables.tsx +2 -0
- package/src/providers/AddAccountForm.tsx +5 -1
- package/src/providers/CliDetail.tsx +6 -5
- package/src/providers/InstallPage.tsx +11 -0
- package/src/providers/ProviderList.tsx +3 -0
- package/src/providers/ProvidersPane.tsx +18 -0
- package/src/providers/account-actions.ts +10 -8
- package/src/providers/install-steps.ts +3 -0
- package/src/providers/pane-target.ts +5 -0
- package/src/providers/provider-abilities.ts +1 -0
- package/src/providers/provider-groups.ts +6 -0
- package/src/providers/variables.ts +12 -0
- package/src/scope.ts +2 -0
- package/src/state/chats.ts +61 -14
- package/src/state/index.ts +2 -0
- package/src/state/provider-accounts.ts +7 -9
- package/src/state/providers.ts +1 -0
- package/src/state/usage.ts +6 -0
- package/src/storage.ts +18 -0
- package/src/testing/prompts.ts +5 -0
- package/src/transport.ts +18 -0
- package/src/usage/ChartLogo.tsx +12 -0
- package/src/usage/LimitsList.tsx +7 -8
- package/src/usage/UsageBreakdown.tsx +11 -4
- package/src/usage/UsageChart.tsx +5 -0
- package/src/usage/UsageLimits.tsx +10 -7
- package/src/usage/UsageLimitsCard.tsx +2 -0
- package/src/usage/UsagePage.tsx +16 -19
- package/src/usage/UsageSummary.tsx +4 -5
- package/src/usage/UsageTiles.tsx +2 -0
- package/src/usage/format.ts +7 -0
- package/src/usage/limit-groups.ts +14 -0
- package/src/usage/limits.ts +11 -13
- package/src/usage/money.ts +1 -0
- package/src/usage/summary.ts +15 -7
|
@@ -37,6 +37,7 @@ export function AccountVariables({ id, account, secretsAvailable }: AccountVaria
|
|
|
37
37
|
const env = variablesOf(drafts);
|
|
38
38
|
const { env: _env, ...rest } = account;
|
|
39
39
|
setSaving(true);
|
|
40
|
+
|
|
40
41
|
try {
|
|
41
42
|
await saveAccount(scope, host, id, env.length === 0 ? rest : { ...rest, env });
|
|
42
43
|
} finally {
|
|
@@ -63,6 +64,7 @@ export function AccountVariables({ id, account, secretsAvailable }: AccountVaria
|
|
|
63
64
|
const lockLabel = draft.sensitive ? t('account.variables.unlock', { name }) : t('account.variables.lock', { name });
|
|
64
65
|
// Off a keychain a value can only be made plain, never secret.
|
|
65
66
|
const lockDisabled = !secretsAvailable && !draft.sensitive;
|
|
67
|
+
|
|
66
68
|
return (
|
|
67
69
|
<div key={draft.key} className="flex min-w-0 items-center gap-2 px-3.5 py-3 font-mono text-code">
|
|
68
70
|
<Input
|
|
@@ -12,6 +12,7 @@ import { DetailHeader, SettingsRow, SettingsSection } from '@adecore/ui/settings
|
|
|
12
12
|
import { Button, FormError, Icon, Input } from '@adecore/ui';
|
|
13
13
|
import { CliTile } from './parts';
|
|
14
14
|
import { providerAccountsOf } from '../state/provider-accounts';
|
|
15
|
+
import { errorMessage } from '../transport';
|
|
15
16
|
|
|
16
17
|
interface AddAccountFormProps {
|
|
17
18
|
provider: ProviderInfo;
|
|
@@ -41,11 +42,14 @@ export function AddAccountForm({ provider, entries, login, onCancel, onAdded }:
|
|
|
41
42
|
|
|
42
43
|
const submit = async (event: FormEvent): Promise<void> => {
|
|
43
44
|
event.preventDefault();
|
|
45
|
+
|
|
44
46
|
if (label === '' || busy) {
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
49
|
+
|
|
47
50
|
setBusy(true);
|
|
48
51
|
setError(null);
|
|
52
|
+
|
|
49
53
|
try {
|
|
50
54
|
if (linking) {
|
|
51
55
|
const taken = new Set(Object.keys(providerAccountsOf(scope.id).accounts?.accounts ?? {}));
|
|
@@ -56,7 +60,7 @@ export function AddAccountForm({ provider, entries, login, onCancel, onAdded }:
|
|
|
56
60
|
onAdded(await createAccount(scope, provider.kind, label, color), label, true);
|
|
57
61
|
}
|
|
58
62
|
} catch (e) {
|
|
59
|
-
setError(
|
|
63
|
+
setError(errorMessage(e));
|
|
60
64
|
setBusy(false);
|
|
61
65
|
}
|
|
62
66
|
};
|
|
@@ -5,14 +5,14 @@ import { AccountDot } from '../agents/AccountDot';
|
|
|
5
5
|
import { ModelOptionControl } from '../agents/ModelOptionControl';
|
|
6
6
|
import { carryOptions } from '../agents/model-options';
|
|
7
7
|
import { optionWord } from '../agents/option-words';
|
|
8
|
-
import { ACCOUNT_TONE_CLASSES, accountName, accountStatusLine, type AccountEntry, type AccountLogin } from '../agents/accounts';
|
|
8
|
+
import { ACCOUNT_TONE_CLASSES, accountName, accountStatusLine, offeredAccounts, type AccountEntry, type AccountLogin } from '../agents/accounts';
|
|
9
9
|
import { accountFor, forgetChatSelection, rememberChatAccount, rememberChatSelection, selectionFor, useChatPreferences } from '../chat/preferences';
|
|
10
10
|
import { useChatScope } from '../scope';
|
|
11
11
|
import { providerAbilities } from './provider-abilities';
|
|
12
12
|
import { DetailHeader, SettingsRow, SettingsSection } from '@adecore/ui/settings';
|
|
13
13
|
import { Button, Icon, Select } from '@adecore/ui';
|
|
14
14
|
import { CliTile } from './parts';
|
|
15
|
-
import {
|
|
15
|
+
import { knownAccounts, useProviderAccounts } from '../state/provider-accounts';
|
|
16
16
|
|
|
17
17
|
const PROVIDER_DEFAULT = '';
|
|
18
18
|
|
|
@@ -21,6 +21,7 @@ function ModelOptionRows({ provider, model, options }: { provider: AgentKind; mo
|
|
|
21
21
|
const setOption = (id: string, value: string | boolean): void => {
|
|
22
22
|
rememberChatSelection(provider, { model: model.slug, options: { ...options, [id]: value } });
|
|
23
23
|
};
|
|
24
|
+
|
|
24
25
|
return (
|
|
25
26
|
<>
|
|
26
27
|
{model.options.map((option) => (
|
|
@@ -53,10 +54,9 @@ export function CliDetail({ provider, entries, defaults, login, onAddAccount, on
|
|
|
53
54
|
const preferences = useChatPreferences();
|
|
54
55
|
const selection = selectionFor(preferences, provider.kind);
|
|
55
56
|
const model = provider.models.find((entry) => entry.slug === selection?.model);
|
|
56
|
-
const machineAccounts =
|
|
57
|
+
const machineAccounts = useProviderAccounts(knownAccounts);
|
|
57
58
|
const picked = accountFor(preferences, scopeId, provider.kind, machineAccounts) ?? provider.kind;
|
|
58
|
-
|
|
59
|
-
const choosable = (entries ?? []).filter((entry) => entry.account.enabled !== false || entry.id === picked);
|
|
59
|
+
const choosable = offeredAccounts(entries ?? [], picked);
|
|
60
60
|
const canAddAccount = login !== null;
|
|
61
61
|
|
|
62
62
|
return (
|
|
@@ -137,6 +137,7 @@ export function CliDetail({ provider, entries, defaults, login, onAddAccount, on
|
|
|
137
137
|
<SettingsSection title={t('cli.accounts')} footer={canAddAccount ? undefined : t('cli.onlyDefault', { provider: provider.name })}>
|
|
138
138
|
{entries.map((entry) => {
|
|
139
139
|
const status = accountStatusLine(entry.status, login === 'terminal');
|
|
140
|
+
|
|
140
141
|
return (
|
|
141
142
|
<button
|
|
142
143
|
key={entry.id}
|
|
@@ -13,6 +13,7 @@ import { CliMark } from './parts';
|
|
|
13
13
|
function CommandBlock({ command }: { command: string }) {
|
|
14
14
|
const { t } = useTranslation('agent-providers');
|
|
15
15
|
const [copied, setCopied] = useState<string | null>(null);
|
|
16
|
+
|
|
16
17
|
return (
|
|
17
18
|
<div className="flex min-w-0 items-center gap-2 rounded-lg border border-border bg-surface-sunken py-1 pr-1 pl-3">
|
|
18
19
|
<code className="min-w-0 grow font-mono text-code break-all text-text select-text">{command}</code>
|
|
@@ -58,6 +59,7 @@ function Step({ index, state, title, children }: { index: number; state: Install
|
|
|
58
59
|
function SignInWay({ way, canRun, onRun }: { way: ProviderSignIn; canRun: boolean; onRun(command: string): void }) {
|
|
59
60
|
const { t } = useTranslation('agent-providers');
|
|
60
61
|
const { providerKeyNote } = useChatHost();
|
|
62
|
+
|
|
61
63
|
switch (way.kind) {
|
|
62
64
|
case 'command':
|
|
63
65
|
return (
|
|
@@ -74,6 +76,7 @@ function SignInWay({ way, canRun, onRun }: { way: ProviderSignIn; canRun: boolea
|
|
|
74
76
|
);
|
|
75
77
|
case 'env': {
|
|
76
78
|
const note = providerKeyNote?.(way.variable) ?? null;
|
|
79
|
+
|
|
77
80
|
return (
|
|
78
81
|
<p className="text-xs text-text-muted">
|
|
79
82
|
<Trans
|
|
@@ -110,10 +113,13 @@ export function InstallPage({ provider, signedIn, extra }: InstallPageProps) {
|
|
|
110
113
|
const platform = chosen ?? initial;
|
|
111
114
|
const install = provider.install;
|
|
112
115
|
const run = host.runProviderCommand;
|
|
116
|
+
|
|
113
117
|
const onRun = (command: string): void => run?.(scopeId, provider.kind, command);
|
|
118
|
+
|
|
114
119
|
const command = platform === null ? undefined : install?.commands[platform];
|
|
115
120
|
|
|
116
121
|
const steps: { title: string; done: boolean; body: ReactNode }[] = [];
|
|
122
|
+
|
|
117
123
|
steps.push({
|
|
118
124
|
title: t('install.install.title'),
|
|
119
125
|
done: provider.installed,
|
|
@@ -151,10 +157,13 @@ export function InstallPage({ provider, signedIn, extra }: InstallPageProps) {
|
|
|
151
157
|
</>
|
|
152
158
|
)
|
|
153
159
|
});
|
|
160
|
+
|
|
154
161
|
if (extra !== null) {
|
|
155
162
|
steps.push(extra);
|
|
156
163
|
}
|
|
164
|
+
|
|
157
165
|
const ways = install?.signIn ?? [];
|
|
166
|
+
|
|
158
167
|
steps.push({
|
|
159
168
|
title: t('install.signIn.title'),
|
|
160
169
|
done: provider.installed && signedIn,
|
|
@@ -170,11 +179,13 @@ export function InstallPage({ provider, signedIn, extra }: InstallPageProps) {
|
|
|
170
179
|
))
|
|
171
180
|
)
|
|
172
181
|
});
|
|
182
|
+
|
|
173
183
|
steps.push({
|
|
174
184
|
title: t('install.start.title'),
|
|
175
185
|
done: false,
|
|
176
186
|
body: <p className="text-xs text-text-muted">{t('install.start.description', { provider: provider.name })}</p>
|
|
177
187
|
});
|
|
188
|
+
|
|
178
189
|
const states = installStepStates(steps.map((step) => step.done));
|
|
179
190
|
|
|
180
191
|
return (
|
|
@@ -63,13 +63,16 @@ interface ProviderListProps {
|
|
|
63
63
|
/* The providers by whether they are ready, need setup or are not installed; a group without providers is left out. */
|
|
64
64
|
export function ProviderList({ groups, current, canAddAccount, canAddProvider = false, onPick }: ProviderListProps) {
|
|
65
65
|
const { t } = useTranslation('agent-providers');
|
|
66
|
+
|
|
66
67
|
const picksCli = (kind: AgentKind): boolean => (current?.kind === 'cli' || current?.kind === 'install') && current.cli === kind;
|
|
68
|
+
|
|
67
69
|
const picksAccount = (id: string): boolean => current?.kind === 'account' && current.id === id;
|
|
68
70
|
|
|
69
71
|
const row = ({ provider, entries, note }: ProviderRow) => {
|
|
70
72
|
// One account has no row of its own, so picking it lights up its provider.
|
|
71
73
|
const several = entries.length > 1;
|
|
72
74
|
const selected = picksCli(provider.kind) || (!several && entries[0] !== undefined && picksAccount(entries[0].id));
|
|
75
|
+
|
|
73
76
|
return (
|
|
74
77
|
<div key={provider.kind} className="flex min-w-0 shrink-0 flex-col gap-0.5">
|
|
75
78
|
<ListRow
|
|
@@ -49,11 +49,14 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
49
49
|
|
|
50
50
|
const groups = groupProviders(providers, accounts, setupStatusOf);
|
|
51
51
|
const installed = [...groups.ready, ...groups.setup].map((row) => row.provider);
|
|
52
|
+
|
|
52
53
|
const entriesOf = (kind: AgentKind): AccountEntry[] => accountsOfKind(accounts, kind);
|
|
54
|
+
|
|
53
55
|
const loginOf = (kind: AgentKind) => accountLoginOf(accounts, kind);
|
|
54
56
|
|
|
55
57
|
// What was picked may be gone since (an account removed elsewhere); the first CLI stands in for it.
|
|
56
58
|
const pickedEntry = picked?.kind === 'account' ? (Object.hasOwn(accounts?.accounts ?? {}, picked.id) ? picked.id : null) : null;
|
|
59
|
+
|
|
57
60
|
// A CLI taken off the host since it was picked makes way too, so the detail never stays empty.
|
|
58
61
|
const keeps = (entry: Picked): boolean => {
|
|
59
62
|
switch (entry.kind) {
|
|
@@ -67,17 +70,22 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
67
70
|
return true;
|
|
68
71
|
}
|
|
69
72
|
};
|
|
73
|
+
|
|
70
74
|
const current: Picked | null = picked !== null && keeps(picked) ? picked : installed[0] ? { kind: 'cli', cli: installed[0].kind } : null;
|
|
71
75
|
const currentAccount = current?.kind === 'account' ? accounts?.accounts[current.id] : undefined;
|
|
76
|
+
|
|
72
77
|
const currentCli =
|
|
73
78
|
current === null || current.kind === 'catalog' ? null : current.kind === 'account' ? (currentAccount?.kind as AgentKind | undefined) : current.cli;
|
|
79
|
+
|
|
74
80
|
const provider = (current?.kind === 'install' ? providers : installed).find((entry) => entry.kind === currentCli) ?? null;
|
|
75
81
|
|
|
76
82
|
// A search result lands on a row of a CLI's detail, so a picked account makes way for its CLI.
|
|
77
83
|
const [seenTarget, setSeenTarget] = useState(target);
|
|
84
|
+
|
|
78
85
|
if (target !== seenTarget) {
|
|
79
86
|
setSeenTarget(target);
|
|
80
87
|
const opened = pickOfTarget(target, providers);
|
|
88
|
+
|
|
81
89
|
if (opened !== null) {
|
|
82
90
|
setPicked(opened);
|
|
83
91
|
} else if (target?.startsWith('providers.') && current?.kind !== 'cli' && provider !== null) {
|
|
@@ -87,6 +95,7 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
87
95
|
|
|
88
96
|
const added = (id: string, name: string, made: boolean): void => {
|
|
89
97
|
setPicked({ kind: 'account', id });
|
|
98
|
+
|
|
90
99
|
if (made && provider !== null && loginOf(provider.kind) === 'terminal' && openLogin !== null && loginBlocked === null) {
|
|
91
100
|
void openLogin(scopeId, provider.kind, id, name);
|
|
92
101
|
}
|
|
@@ -111,22 +120,28 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
111
120
|
if (current?.kind === 'catalog') {
|
|
112
121
|
return addPage?.((kind) => setPicked(pickOfCli(kind, providers))) ?? null;
|
|
113
122
|
}
|
|
123
|
+
|
|
114
124
|
if (current === null || provider === null) {
|
|
115
125
|
return null;
|
|
116
126
|
}
|
|
127
|
+
|
|
117
128
|
if (current.kind === 'install') {
|
|
118
129
|
const extra = installStepOf?.(provider) ?? null;
|
|
119
130
|
const statuses = entriesOf(provider.kind).map((entry) => entry.status?.state);
|
|
120
131
|
// Without accounts to read, nothing says the CLI is signed out, so being there is all it takes.
|
|
121
132
|
const signedIn = statuses.length === 0 || statuses.includes('ready');
|
|
133
|
+
|
|
122
134
|
if (!provider.installed || !signedIn || (extra !== null && !extra.done)) {
|
|
123
135
|
return <InstallPage key={provider.kind} provider={provider} signedIn={signedIn} extra={extra} />;
|
|
124
136
|
}
|
|
125
137
|
}
|
|
138
|
+
|
|
126
139
|
const own = current.kind === 'cli' || current.kind === 'install' ? (detailOf?.(provider) ?? null) : null;
|
|
140
|
+
|
|
127
141
|
if (own !== null) {
|
|
128
142
|
return own;
|
|
129
143
|
}
|
|
144
|
+
|
|
130
145
|
if (current.kind === 'add') {
|
|
131
146
|
return (
|
|
132
147
|
<AddAccountForm
|
|
@@ -139,8 +154,10 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
139
154
|
/>
|
|
140
155
|
);
|
|
141
156
|
}
|
|
157
|
+
|
|
142
158
|
if (current.kind === 'account') {
|
|
143
159
|
const entry = entriesOf(provider.kind).find((candidate) => candidate.id === current.id);
|
|
160
|
+
|
|
144
161
|
return (
|
|
145
162
|
entry && (
|
|
146
163
|
<AccountDetail
|
|
@@ -156,6 +173,7 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
156
173
|
)
|
|
157
174
|
);
|
|
158
175
|
}
|
|
176
|
+
|
|
159
177
|
return (
|
|
160
178
|
<>
|
|
161
179
|
<CliDetail
|
|
@@ -4,20 +4,17 @@ import { accountFor, readChatPreferences, rememberChatAccount } from '../chat/pr
|
|
|
4
4
|
import type { ChatHost } from '../host';
|
|
5
5
|
import type { ChatScope } from '../scope';
|
|
6
6
|
import { providerAccountsOf, useProviderAccountsStore } from '../state/provider-accounts';
|
|
7
|
-
import type
|
|
7
|
+
import { errorMessage, type ChatTransport } from '../transport';
|
|
8
8
|
|
|
9
9
|
function words(key: string, values?: Record<string, string>): string {
|
|
10
10
|
return i18next.t(`agent-providers:${key}`, values);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function reason(e: unknown): string {
|
|
14
|
-
return e instanceof Error ? e.message : String(e);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
13
|
function linkTo(scope: ChatScope): ChatTransport {
|
|
18
14
|
if (scope.transport.status !== 'open') {
|
|
19
15
|
throw new Error(words('notAnswering'));
|
|
20
16
|
}
|
|
17
|
+
|
|
21
18
|
return scope.transport;
|
|
22
19
|
}
|
|
23
20
|
|
|
@@ -25,9 +22,11 @@ function linkTo(scope: ChatScope): ChatTransport {
|
|
|
25
22
|
export async function saveAccounts(scope: ChatScope, host: Pick<ChatHost, 'notify'>, accounts: ProviderAccountMap): Promise<boolean> {
|
|
26
23
|
try {
|
|
27
24
|
useProviderAccountsStore.getState().set(scope.id, await linkTo(scope).request('accounts.save', { accounts }));
|
|
25
|
+
|
|
28
26
|
return true;
|
|
29
27
|
} catch (e) {
|
|
30
|
-
host.notify({ id: `providers-save-${scope.id}`, kind: 'error', title: words('account.saveFailed'), description:
|
|
28
|
+
host.notify({ id: `providers-save-${scope.id}`, kind: 'error', title: words('account.saveFailed'), description: errorMessage(e) });
|
|
29
|
+
|
|
31
30
|
return false;
|
|
32
31
|
}
|
|
33
32
|
}
|
|
@@ -35,6 +34,7 @@ export async function saveAccounts(scope: ChatScope, host: Pick<ChatHost, 'notif
|
|
|
35
34
|
/* One account changed and every other one as the host last said. */
|
|
36
35
|
export function saveAccount(scope: ChatScope, host: Pick<ChatHost, 'notify'>, id: string, account: ProviderAccount): Promise<boolean> {
|
|
37
36
|
const current = providerAccountsOf(scope.id).accounts?.accounts ?? {};
|
|
37
|
+
|
|
38
38
|
return saveAccounts(scope, host, { ...current, [id]: account });
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -44,9 +44,11 @@ export function saveAccount(scope: ChatScope, host: Pick<ChatHost, 'notify'>, id
|
|
|
44
44
|
*/
|
|
45
45
|
export async function removeAccount(scope: ChatScope, host: Pick<ChatHost, 'notify'>, id: string, kind: AgentKind): Promise<void> {
|
|
46
46
|
const { [id]: _gone, ...rest } = providerAccountsOf(scope.id).accounts?.accounts ?? {};
|
|
47
|
+
|
|
47
48
|
if (!(await saveAccounts(scope, host, rest))) {
|
|
48
49
|
throw new Error(words('account.saveFailed'));
|
|
49
50
|
}
|
|
51
|
+
|
|
50
52
|
if (accountFor(readChatPreferences(), scope.id, kind) === id) {
|
|
51
53
|
rememberChatAccount(scope.id, kind, null);
|
|
52
54
|
}
|
|
@@ -54,9 +56,9 @@ export async function removeAccount(scope: ChatScope, host: Pick<ChatHost, 'noti
|
|
|
54
56
|
|
|
55
57
|
/* An account in a folder the host makes for it; answers its id. Throws what the host said, for the form to show. */
|
|
56
58
|
export async function createAccount(scope: ChatScope, kind: AgentKind, label: string, color: string): Promise<string> {
|
|
57
|
-
const
|
|
58
|
-
const { id, ...accounts } = created;
|
|
59
|
+
const { id, ...accounts } = await linkTo(scope).request('accounts.create', { kind, label, color });
|
|
59
60
|
useProviderAccountsStore.getState().set(scope.id, accounts);
|
|
61
|
+
|
|
60
62
|
return id;
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -17,6 +17,7 @@ const PLATFORMS: readonly ProviderPlatform[] = ['darwin', 'linux', 'win32'];
|
|
|
17
17
|
/* The first step not done is the current one. */
|
|
18
18
|
export function installStepStates(done: readonly boolean[]): InstallStepState[] {
|
|
19
19
|
const first = done.indexOf(false);
|
|
20
|
+
|
|
20
21
|
return done.map((value, index) => (value ? 'done' : index === first ? 'current' : 'later'));
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -25,11 +26,13 @@ export function pagePlatform(): ProviderPlatform {
|
|
|
25
26
|
if (isApplePlatform()) {
|
|
26
27
|
return 'darwin';
|
|
27
28
|
}
|
|
29
|
+
|
|
28
30
|
return typeof navigator !== 'undefined' && /windows/i.test(navigator.userAgent) ? 'win32' : 'linux';
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
/* The systems a provider has a command for, and the one the page opens on: the machine's when it has one there. */
|
|
32
34
|
export function installPlatforms(provider: ProviderInfo, machine: ProviderPlatform): { offered: ProviderPlatform[]; initial: ProviderPlatform | null } {
|
|
33
35
|
const offered = PLATFORMS.filter((platform) => Boolean(provider.install?.commands[platform]));
|
|
36
|
+
|
|
34
37
|
return { offered, initial: offered.includes(machine) ? machine : (offered[0] ?? null) };
|
|
35
38
|
}
|
|
@@ -16,12 +16,15 @@ export function pickOfTarget(target: string | null, providers: ProviderInfo[]):
|
|
|
16
16
|
if (target === 'providers.apple') {
|
|
17
17
|
return { kind: 'cli', cli: 'apple' };
|
|
18
18
|
}
|
|
19
|
+
|
|
19
20
|
if (target === ADD_TARGET) {
|
|
20
21
|
return { kind: 'catalog' };
|
|
21
22
|
}
|
|
23
|
+
|
|
22
24
|
if (!target?.startsWith(INSTALL_TARGET) || target.length === INSTALL_TARGET.length) {
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
27
|
+
|
|
25
28
|
return pickOfCli(target.slice(INSTALL_TARGET.length) as AgentKind, providers);
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -32,8 +35,10 @@ export function pickOfTarget(target: string | null, providers: ProviderInfo[]):
|
|
|
32
35
|
*/
|
|
33
36
|
export function pickOfCli(cli: AgentKind, providers: ProviderInfo[]): Picked {
|
|
34
37
|
const provider = providers.find((entry) => entry.kind === cli);
|
|
38
|
+
|
|
35
39
|
if (provider !== undefined && (provider.installed || !provider.capabilities.terminal)) {
|
|
36
40
|
return { kind: 'cli', cli };
|
|
37
41
|
}
|
|
42
|
+
|
|
38
43
|
return { kind: 'install', cli };
|
|
39
44
|
}
|
|
@@ -5,6 +5,7 @@ import type { ProviderCapabilities, ProviderInfo } from '@adecore/agent-contract
|
|
|
5
5
|
export function providerAbilities(provider: ProviderInfo): string {
|
|
6
6
|
const where = provider.capabilities.chat ? i18next.t('agent-providers:abilities.chatAndTerminal') : i18next.t('agent-providers:abilities.terminalOnly');
|
|
7
7
|
const status = provider.capabilities.hooks ? i18next.t('agent-providers:abilities.reportsStatus') : i18next.t('agent-providers:abilities.noStatus');
|
|
8
|
+
|
|
8
9
|
return `${where} ${status}`;
|
|
9
10
|
}
|
|
10
11
|
|
|
@@ -24,6 +24,7 @@ export interface ProviderGroups {
|
|
|
24
24
|
/* What an account says beside its name: its plan while it is ready, a short word when it is not, nothing while it is checked. */
|
|
25
25
|
export function accountNote(status: ProviderAccountStatus | null): ProviderSetupStatus | null {
|
|
26
26
|
const words = (key: string): string => i18next.t(`agent-providers:${key}`);
|
|
27
|
+
|
|
27
28
|
switch (status?.state ?? 'checking') {
|
|
28
29
|
case 'checking':
|
|
29
30
|
return null;
|
|
@@ -57,14 +58,18 @@ export function groupProviders(
|
|
|
57
58
|
setupStatusOf?: (provider: ProviderInfo) => ProviderSetupStatus | null
|
|
58
59
|
): ProviderGroups {
|
|
59
60
|
const groups: ProviderGroups = { ready: [], setup: [], missing: [] };
|
|
61
|
+
|
|
60
62
|
for (const provider of providers) {
|
|
61
63
|
// A provider that never runs in a terminal is no CLI to install: it is turned on in its own detail.
|
|
62
64
|
if (!provider.installed && provider.capabilities.terminal) {
|
|
63
65
|
groups.missing.push(provider);
|
|
66
|
+
|
|
64
67
|
continue;
|
|
65
68
|
}
|
|
69
|
+
|
|
66
70
|
const entries = provider.installed ? accountsOfKind(accounts, provider.kind) : [];
|
|
67
71
|
const hostStatus = setupStatusOf?.(provider) ?? null;
|
|
72
|
+
|
|
68
73
|
if (hostStatus !== null) {
|
|
69
74
|
groups.setup.push({ provider, entries, note: hostStatus });
|
|
70
75
|
} else if (entries.length === 0 || entries.some(usable)) {
|
|
@@ -73,5 +78,6 @@ export function groupProviders(
|
|
|
73
78
|
groups.setup.push({ provider, entries, note: accountNote(entries[0]!.status) });
|
|
74
79
|
}
|
|
75
80
|
}
|
|
81
|
+
|
|
76
82
|
return groups;
|
|
77
83
|
}
|
|
@@ -15,8 +15,10 @@ export interface VariableDraft {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
let drafted = 0;
|
|
18
|
+
|
|
18
19
|
function nextKey(): string {
|
|
19
20
|
drafted += 1;
|
|
21
|
+
|
|
20
22
|
return `variable-${drafted}`;
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -45,23 +47,31 @@ function keepsValue(draft: VariableDraft): boolean {
|
|
|
45
47
|
/* The first thing that keeps these from being saved, in a sentence; null when they can be. */
|
|
46
48
|
export function variablesProblem(drafts: readonly VariableDraft[]): string | null {
|
|
47
49
|
const words = (key: string, name: string): string => i18next.t(`agent-providers:account.variables.problem.${key}`, { name });
|
|
50
|
+
|
|
48
51
|
const seen = new Set<string>();
|
|
52
|
+
|
|
49
53
|
for (const draft of drafts) {
|
|
50
54
|
const name = draft.name.trim();
|
|
55
|
+
|
|
51
56
|
if (name === '') {
|
|
52
57
|
return words('noName', '');
|
|
53
58
|
}
|
|
59
|
+
|
|
54
60
|
if (!NAME.test(name)) {
|
|
55
61
|
return words('invalidName', name);
|
|
56
62
|
}
|
|
63
|
+
|
|
57
64
|
if (seen.has(name)) {
|
|
58
65
|
return words('duplicate', name);
|
|
59
66
|
}
|
|
67
|
+
|
|
60
68
|
seen.add(name);
|
|
69
|
+
|
|
61
70
|
if (draft.value === '' && !keepsValue({ ...draft, name })) {
|
|
62
71
|
return words('noValue', name);
|
|
63
72
|
}
|
|
64
73
|
}
|
|
74
|
+
|
|
65
75
|
return null;
|
|
66
76
|
}
|
|
67
77
|
|
|
@@ -69,9 +79,11 @@ export function variablesProblem(drafts: readonly VariableDraft[]): string | nul
|
|
|
69
79
|
export function variablesOf(drafts: readonly VariableDraft[]): ProviderAccountVariable[] {
|
|
70
80
|
return drafts.map((draft) => {
|
|
71
81
|
const name = draft.name.trim();
|
|
82
|
+
|
|
72
83
|
if (keepsValue({ ...draft, name })) {
|
|
73
84
|
return { name, value: '', sensitive: true, valueRedacted: true };
|
|
74
85
|
}
|
|
86
|
+
|
|
75
87
|
return { name, value: draft.value, sensitive: draft.sensitive };
|
|
76
88
|
});
|
|
77
89
|
}
|
package/src/scope.ts
CHANGED
|
@@ -23,8 +23,10 @@ export const ChatScopeContext = createContext<ChatScope | null>(null);
|
|
|
23
23
|
/* Throws outside a scope on purpose: a component that reads a chat has to know which host it runs on. */
|
|
24
24
|
export function useChatScope(): ChatScope {
|
|
25
25
|
const scope = useContext(ChatScopeContext);
|
|
26
|
+
|
|
26
27
|
if (scope === null) {
|
|
27
28
|
throw new Error('This component reads a chat, so it has to be rendered inside a ChatScopeContext');
|
|
28
29
|
}
|
|
30
|
+
|
|
29
31
|
return scope;
|
|
30
32
|
}
|