@adecore/agents-react 0.31.5 → 0.31.6
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/chat/ui/rows/WorkRows.js +1 -1
- package/dist/providers/ProvidersPane.js +5 -3
- package/dist/providers/pane-target.d.ts +15 -0
- package/dist/providers/pane-target.js +17 -0
- package/package.json +8 -8
- package/src/chat/ui/rows/WorkRows.tsx +22 -19
- package/src/providers/ProvidersPane.tsx +6 -7
- package/src/providers/pane-target.ts +23 -0
|
@@ -76,7 +76,7 @@ export function ToggleLine({ icon, label, brand, detail, command, look, path, op
|
|
|
76
76
|
const classes = clsx(
|
|
77
77
|
// Fix the width so long commands reach the truncation inside the negative margins.
|
|
78
78
|
'group/line -mx-1 mb-0.5 flex h-7 w-[calc(100%+8px)] items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted', onToggle !== undefined && 'hover:bg-surface-hover', failed && 'text-status-error', className);
|
|
79
|
-
const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: clsx(ROW_GUTTER, live && 'text-accent'), children: icon }), _jsxs("span", { className: clsx('shrink-0', live && 'chat-live-text'), children: [brand !== undefined && _jsx("span", { className: BRAND, children: brand }), brand !== undefined && label !== '' && ' ', label] }), look !== undefined ? (_jsxs(_Fragment, { children: [look.run.detail !== '' && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-code text-text-faint", children: _jsx(LookDetail, { run: look.run, chatId: look.chatId }) })), _jsx(LookTags, { run: look.run })] })) : (detail && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-code text-text-faint", children: command ? _jsx(ShellCommand, { command: detail }) : path ? _jsx(MiddleTruncate, { text: detail }) : detail }))), _jsx("span", { className: "grow" }), trailing, time !== undefined && _jsx(RowTime, { at: time }), failed && _jsx(Icon, { icon: X, size: 12, className: "shrink-0" }), onToggle !== undefined && (_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') }))] }));
|
|
79
|
+
const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: clsx(ROW_GUTTER, live && 'text-accent'), children: icon }), _jsxs("span", { className: "flex min-w-0 items-baseline gap-2", children: [_jsxs("span", { className: clsx('shrink-0', live && 'chat-live-text'), children: [brand !== undefined && _jsx("span", { className: BRAND, children: brand }), brand !== undefined && label !== '' && ' ', label] }), look !== undefined ? (_jsxs(_Fragment, { children: [look.run.detail !== '' && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-code text-text-faint", children: _jsx(LookDetail, { run: look.run, chatId: look.chatId }) })), _jsx(LookTags, { run: look.run })] })) : (detail && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-code text-text-faint", children: command ? _jsx(ShellCommand, { command: detail }) : path ? _jsx(MiddleTruncate, { text: detail }) : detail })))] }), _jsx("span", { className: "grow" }), trailing, time !== undefined && _jsx(RowTime, { at: time }), failed && _jsx(Icon, { icon: X, size: 12, className: "shrink-0" }), onToggle !== undefined && (_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') }))] }));
|
|
80
80
|
if (onToggle === undefined) {
|
|
81
81
|
return _jsx("div", { className: classes, children: content });
|
|
82
82
|
}
|
|
@@ -13,6 +13,7 @@ import { AccountDetail } from './AccountDetail.js';
|
|
|
13
13
|
import { AddAccountForm } from './AddAccountForm.js';
|
|
14
14
|
import { CliDetail } from './CliDetail.js';
|
|
15
15
|
import { InstallPage } from './InstallPage.js';
|
|
16
|
+
import { pickOfTarget } from './pane-target.js';
|
|
16
17
|
import { CliMark } from './parts.js';
|
|
17
18
|
import { useProviderAccounts } from '../state/provider-accounts.js';
|
|
18
19
|
import { useProviders } from '../state/providers.js';
|
|
@@ -30,7 +31,7 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
30
31
|
const host = useChatHost();
|
|
31
32
|
const { openLogin } = host;
|
|
32
33
|
const loginBlocked = host.useLoginBlocked(scopeId);
|
|
33
|
-
const [picked, setPicked] = useState(() => (target
|
|
34
|
+
const [picked, setPicked] = useState(() => pickOfTarget(target, providers));
|
|
34
35
|
// A provider that never runs in a terminal is no CLI to install: it is turned on in its own detail, so it is always listed.
|
|
35
36
|
const installed = useMemo(() => providers.filter((provider) => provider.installed || !provider.capabilities.terminal), [providers]);
|
|
36
37
|
const missing = useMemo(() => providers.filter((provider) => !provider.installed && provider.capabilities.terminal), [providers]);
|
|
@@ -47,8 +48,9 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
47
48
|
const [seenTarget, setSeenTarget] = useState(target);
|
|
48
49
|
if (target !== seenTarget) {
|
|
49
50
|
setSeenTarget(target);
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
const opened = pickOfTarget(target, providers);
|
|
52
|
+
if (opened !== null) {
|
|
53
|
+
setPicked(opened);
|
|
52
54
|
}
|
|
53
55
|
else if (target?.startsWith('providers.') && current?.kind !== 'cli' && provider !== null) {
|
|
54
56
|
setPicked({ kind: 'cli', cli: provider.kind });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AgentKind, ProviderInfo } from '@adecore/agent-contracts';
|
|
2
|
+
export type Picked = {
|
|
3
|
+
kind: 'cli';
|
|
4
|
+
cli: AgentKind;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'install';
|
|
7
|
+
cli: AgentKind;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'account';
|
|
10
|
+
id: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'add';
|
|
13
|
+
cli: AgentKind;
|
|
14
|
+
};
|
|
15
|
+
export declare function pickOfTarget(target: string | null, providers: ProviderInfo[]): Picked | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const INSTALL_TARGET = 'providers.install.';
|
|
2
|
+
/* What a target opens on its own, before any CLI is picked; null for a target that only lands on a row of the CLI already shown. */
|
|
3
|
+
export function pickOfTarget(target, providers) {
|
|
4
|
+
if (target === 'providers.apple') {
|
|
5
|
+
return { kind: 'cli', cli: 'apple' };
|
|
6
|
+
}
|
|
7
|
+
if (!target?.startsWith(INSTALL_TARGET) || target.length === INSTALL_TARGET.length) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const cli = target.slice(INSTALL_TARGET.length);
|
|
11
|
+
const provider = providers.find((entry) => entry.kind === cli);
|
|
12
|
+
// A CLI the host has not reported yet is taken as missing; once it is installed and signed in, its install page gives way to its detail.
|
|
13
|
+
if (provider !== undefined && (provider.installed || !provider.capabilities.terminal)) {
|
|
14
|
+
return { kind: 'cli', cli };
|
|
15
|
+
}
|
|
16
|
+
return { kind: 'install', cli };
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents-react",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.6",
|
|
4
4
|
"description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@adecore/agent-contracts": "0.31.
|
|
71
|
-
"@adecore/editor": "0.31.
|
|
72
|
-
"@adecore/editor-react": "0.31.
|
|
73
|
-
"@adecore/intelligent-ui": "0.31.
|
|
74
|
-
"@adecore/merge": "0.31.
|
|
70
|
+
"@adecore/agent-contracts": "0.31.6",
|
|
71
|
+
"@adecore/editor": "0.31.6",
|
|
72
|
+
"@adecore/editor-react": "0.31.6",
|
|
73
|
+
"@adecore/intelligent-ui": "0.31.6",
|
|
74
|
+
"@adecore/merge": "0.31.6",
|
|
75
75
|
"@codemirror/commands": "^6.11.1",
|
|
76
76
|
"@codemirror/language": "^6.12.4",
|
|
77
77
|
"@codemirror/state": "^6.7.6",
|
|
@@ -94,14 +94,14 @@
|
|
|
94
94
|
"zustand": "^5.0.15"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|
|
97
|
-
"@adecore/ui": "^0.31.
|
|
97
|
+
"@adecore/ui": "^0.31.6",
|
|
98
98
|
"i18next": "^26.4.2",
|
|
99
99
|
"react": "^19.3.0",
|
|
100
100
|
"react-dom": "^19.3.0",
|
|
101
101
|
"react-i18next": "^17.0.15"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@adecore/ui": "0.31.
|
|
104
|
+
"@adecore/ui": "0.31.6",
|
|
105
105
|
"@types/bun": "^1.4.2",
|
|
106
106
|
"@types/react": "^19.3.0",
|
|
107
107
|
"@types/react-dom": "^19.3.0",
|
|
@@ -154,27 +154,30 @@ export function ToggleLine({
|
|
|
154
154
|
const content = (
|
|
155
155
|
<>
|
|
156
156
|
<span className={clsx(ROW_GUTTER, live && 'text-accent')}>{icon}</span>
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
{
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
157
|
+
{/* The label is sans and the detail mono, so only a shared baseline puts them on one line. */}
|
|
158
|
+
<span className="flex min-w-0 items-baseline gap-2">
|
|
159
|
+
<span className={clsx('shrink-0', live && 'chat-live-text')}>
|
|
160
|
+
{brand !== undefined && <span className={BRAND}>{brand}</span>}
|
|
161
|
+
{brand !== undefined && label !== '' && ' '}
|
|
162
|
+
{label}
|
|
163
|
+
</span>
|
|
164
|
+
{look !== undefined ? (
|
|
165
|
+
<>
|
|
166
|
+
{look.run.detail !== '' && (
|
|
167
|
+
<span data-find-field="summary" className="min-w-0 truncate font-mono text-code text-text-faint">
|
|
168
|
+
<LookDetail run={look.run} chatId={look.chatId} />
|
|
169
|
+
</span>
|
|
170
|
+
)}
|
|
171
|
+
<LookTags run={look.run} />
|
|
172
|
+
</>
|
|
173
|
+
) : (
|
|
174
|
+
detail && (
|
|
165
175
|
<span data-find-field="summary" className="min-w-0 truncate font-mono text-code text-text-faint">
|
|
166
|
-
<
|
|
176
|
+
{command ? <ShellCommand command={detail} /> : path ? <MiddleTruncate text={detail} /> : detail}
|
|
167
177
|
</span>
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
) : (
|
|
172
|
-
detail && (
|
|
173
|
-
<span data-find-field="summary" className="min-w-0 truncate font-mono text-code text-text-faint">
|
|
174
|
-
{command ? <ShellCommand command={detail} /> : path ? <MiddleTruncate text={detail} /> : detail}
|
|
175
|
-
</span>
|
|
176
|
-
)
|
|
177
|
-
)}
|
|
178
|
+
)
|
|
179
|
+
)}
|
|
180
|
+
</span>
|
|
178
181
|
<span className="grow" />
|
|
179
182
|
{trailing}
|
|
180
183
|
{time !== undefined && <RowTime at={time} />}
|
|
@@ -14,13 +14,11 @@ import { AddAccountForm } from './AddAccountForm';
|
|
|
14
14
|
import { CliDetail } from './CliDetail';
|
|
15
15
|
import { InstallPage } from './InstallPage';
|
|
16
16
|
import type { ProviderInstallStep } from './install-steps';
|
|
17
|
+
import { pickOfTarget, type Picked } from './pane-target';
|
|
17
18
|
import { CliMark } from './parts';
|
|
18
19
|
import { useProviderAccounts } from '../state/provider-accounts';
|
|
19
20
|
import { useProviders } from '../state/providers';
|
|
20
21
|
|
|
21
|
-
// `install` is a CLI picked while it was missing: its install page stays until it is installed and signed in.
|
|
22
|
-
type Picked = { kind: 'cli'; cli: AgentKind } | { kind: 'install'; cli: AgentKind } | { kind: 'account'; id: string } | { kind: 'add'; cli: AgentKind };
|
|
23
|
-
|
|
24
22
|
/* A row of the list with a control of its own beside the part that picks it, so the two never nest. */
|
|
25
23
|
function ListRow({
|
|
26
24
|
selected,
|
|
@@ -51,7 +49,7 @@ function ListRow({
|
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
interface ProvidersPaneProps {
|
|
54
|
-
/* The row a search result leads to, by its `searchId`; the pane opens on the CLI it belongs to. */
|
|
52
|
+
/* The row a search result leads to, by its `searchId`; the pane opens on the CLI it belongs to. `providers.install.<kind>` opens on that CLI's install page, or on its detail once it is installed. */
|
|
55
53
|
target?: string | null;
|
|
56
54
|
/* The detail of a provider the app draws itself, such as a model the host runs on its own; null draws the CLI's own. */
|
|
57
55
|
detailOf?(provider: ProviderInfo): ReactNode | null;
|
|
@@ -71,7 +69,7 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
71
69
|
const host = useChatHost();
|
|
72
70
|
const { openLogin } = host;
|
|
73
71
|
const loginBlocked = host.useLoginBlocked(scopeId);
|
|
74
|
-
const [picked, setPicked] = useState<Picked | null>(() => (target
|
|
72
|
+
const [picked, setPicked] = useState<Picked | null>(() => pickOfTarget(target, providers));
|
|
75
73
|
|
|
76
74
|
// A provider that never runs in a terminal is no CLI to install: it is turned on in its own detail, so it is always listed.
|
|
77
75
|
const installed = useMemo(() => providers.filter((provider) => provider.installed || !provider.capabilities.terminal), [providers]);
|
|
@@ -92,8 +90,9 @@ export function ProvidersPane({ target = null, detailOf, defaults = true, instal
|
|
|
92
90
|
const [seenTarget, setSeenTarget] = useState(target);
|
|
93
91
|
if (target !== seenTarget) {
|
|
94
92
|
setSeenTarget(target);
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
const opened = pickOfTarget(target, providers);
|
|
94
|
+
if (opened !== null) {
|
|
95
|
+
setPicked(opened);
|
|
97
96
|
} else if (target?.startsWith('providers.') && current?.kind !== 'cli' && provider !== null) {
|
|
98
97
|
setPicked({ kind: 'cli', cli: provider.kind });
|
|
99
98
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AgentKind, ProviderInfo } from '@adecore/agent-contracts';
|
|
2
|
+
|
|
3
|
+
// `install` is a CLI picked while it was missing: its install page stays until it is installed and signed in.
|
|
4
|
+
export type Picked = { kind: 'cli'; cli: AgentKind } | { kind: 'install'; cli: AgentKind } | { kind: 'account'; id: string } | { kind: 'add'; cli: AgentKind };
|
|
5
|
+
|
|
6
|
+
const INSTALL_TARGET = 'providers.install.';
|
|
7
|
+
|
|
8
|
+
/* What a target opens on its own, before any CLI is picked; null for a target that only lands on a row of the CLI already shown. */
|
|
9
|
+
export function pickOfTarget(target: string | null, providers: ProviderInfo[]): Picked | null {
|
|
10
|
+
if (target === 'providers.apple') {
|
|
11
|
+
return { kind: 'cli', cli: 'apple' };
|
|
12
|
+
}
|
|
13
|
+
if (!target?.startsWith(INSTALL_TARGET) || target.length === INSTALL_TARGET.length) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const cli = target.slice(INSTALL_TARGET.length) as AgentKind;
|
|
17
|
+
const provider = providers.find((entry) => entry.kind === cli);
|
|
18
|
+
// A CLI the host has not reported yet is taken as missing; once it is installed and signed in, its install page gives way to its detail.
|
|
19
|
+
if (provider !== undefined && (provider.installed || !provider.capabilities.terminal)) {
|
|
20
|
+
return { kind: 'cli', cli };
|
|
21
|
+
}
|
|
22
|
+
return { kind: 'install', cli };
|
|
23
|
+
}
|