Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions apps/client/__tests__/config-schema-form.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,85 @@ describe('config schema form', () => {
expect(html).not.toContain('config.detail.inheritedReadonly')
})

it('opens a runtime adapter account when its config schema is unavailable', () => {
const onChange = vi.fn()
const uiSection: ConfigUiSection = {
key: 'adapters',
kind: 'recordMap',
recordMap: {
mode: 'keyed',
keyPlaceholder: 'Adapter key',
schemas: {},
unknownSchema: {
fields: []
},
unknownEditor: 'json'
}
}

const html = renderToStaticMarkup(
<SectionForm
sectionKey='adapters'
uiSection={uiSection}
value={{}}
onChange={onChange}
mergedModelServices={{}}
mergedAdapters={{}}
detailRoute={{
kind: 'detailCollectionItem',
fieldPath: [],
itemKey: 'codex',
nestedPath: ['accounts', 'work']
}}
t={t}
/>
)

expect(html).toContain('adapter-account-manager__state')
expect(html).not.toContain('config-view__complex-editor')
expect(onChange).not.toHaveBeenCalled()
})

it('keeps the JSON fallback for an unknown adapter without an account route', () => {
const uiSection: ConfigUiSection = {
key: 'adapters',
kind: 'recordMap',
recordMap: {
mode: 'keyed',
keyPlaceholder: 'Adapter key',
schemas: {},
unknownSchema: {
fields: []
},
unknownEditor: 'json'
}
}

const html = renderToStaticMarkup(
<SectionForm
sectionKey='adapters'
uiSection={uiSection}
value={{
custom: {
enabled: true
}
}}
onChange={() => undefined}
mergedModelServices={{}}
mergedAdapters={{}}
detailRoute={{
kind: 'detailCollectionItem',
fieldPath: [],
itemKey: 'custom'
}}
t={t}
/>
)

expect(html).toContain('config-view__complex-editor')
expect(html).not.toContain('adapter-account-manager__')
})

it('renders a schema-driven adapter detail route as a second-level config page', () => {
const uiSection: ConfigUiSection = {
key: 'adapters',
Expand Down
57 changes: 30 additions & 27 deletions apps/client/src/components/config/ConfigSectionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1733,6 +1733,36 @@ export const SectionForm = ({
})
const shouldRenderJsonFallback = !isKnownEntry && uiSection.recordMap.unknownEditor === 'json'
const discriminatorField = uiSection.recordMap.discriminatorField ?? 'type'
const accountItemSchema = sectionKey === 'adapters'
? itemSchema?.recordFields?.accounts?.itemSchema
: undefined
const isAdapterAccountsNestedRoute = sectionKey === 'adapters' &&
detailRoute?.nestedPath?.[0] === 'accounts'

if (isAdapterAccountsNestedRoute) {
return (
<div className='config-view__detail-panel'>
{detailNotice}
<AdapterAccountsManager
adapterKey={detailMeta.itemKey}
value={detailMeta.item}
accountsData={adapterAccountsData}
accountItemSchema={accountItemSchema}
onChange={writeDetailItem}
nestedPath={detailRoute.nestedPath}
onOpenNestedPath={(nextPath) => {
onOpenDetailRoute?.({
kind: detailRoute.kind,
fieldPath: detailMeta.field.path,
itemKey: detailMeta.itemKey,
nestedPath: nextPath
})
}}
t={t}
/>
</div>
)
}

if (shouldRenderJsonFallback) {
return (
Expand All @@ -1749,8 +1779,6 @@ export const SectionForm = ({

if (itemSchema != null) {
if (sectionKey === 'adapters') {
const accountItemSchema = itemSchema.recordFields?.accounts?.itemSchema
const isAccountsNestedRoute = detailRoute?.nestedPath?.[0] === 'accounts'
const hiddenFieldPaths = [
...(isKnownEntry && uiSection.recordMap.mode === 'discriminated' ? [[discriminatorField]] : []),
['accounts']
Expand Down Expand Up @@ -1854,31 +1882,6 @@ export const SectionForm = ({
}
]

if (isAccountsNestedRoute) {
return (
<div className='config-view__detail-panel'>
{detailNotice}
<AdapterAccountsManager
adapterKey={detailMeta.itemKey}
value={detailMeta.item}
accountsData={adapterAccountsData}
accountItemSchema={accountItemSchema}
onChange={writeDetailItem}
nestedPath={detailRoute?.nestedPath}
onOpenNestedPath={(nextPath) => {
onOpenDetailRoute?.({
kind: detailRoute?.kind ?? 'detailCollectionItem',
fieldPath: detailMeta.field.path,
itemKey: detailMeta.itemKey,
nestedPath: nextPath
})
}}
t={t}
/>
</div>
)
}

return (
<div className='config-view__detail-panel'>
{detailNotice}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions changelog/0.1.0-beta.10/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
- Polish Launcher settings with a full-bleed, content-sized tab strip and consistent 10px spacing, fix empty shortcut input rendering, and support `Command+,` on macOS or `Ctrl+,` on Windows and Linux to open settings directly.
- Refine Launcher menu surfaces with opaque theme-owned root and language submenus, keep icon-label spacing consistent at 6px, and show the platform settings shortcut alongside the settings command.
- Keep sender status-bar menus anchored and clickable when the account popup opens, including correct stacking above the composer input.
- Show runtime adapter account details even when the workspace has no adapter configuration schema, instead of falling back to an empty JSON editor.
- Remove the duplicate plugin configuration entry from the settings sidebar now that plugin management lives in the plugin marketplace, and safely redirect obsolete plugin settings links to General.
- Keep the new-session environment menu coherent when only the built-in default is available, and preserve a visible, keyboard-accessible control for restoring a collapsed status bar.
- Normalize new-session composer edge spacing to the shared 10px inset across compact and medium desktop windows while keeping the wide 800px layout centered.

![New-session composer with consistent edge spacing](./compact-composer-padding.jpg)

![Runtime adapter account detail with personal identifiers redacted](./adapter-account-detail-redacted.png)
Loading