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
30 changes: 15 additions & 15 deletions client/src/pages/CapabilityMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ export default function CapabilityMap() {
Enable at least one runnable AI provider. Networking and other integrations are optional; you can configure them whenever they are useful.
</p>

<section className="space-y-3 rounded-xl border border-port-border bg-port-card p-4 sm:p-5">
<div>
<h3 className="font-semibold text-white">AI provider</h3>
<p className="mt-1 text-xs text-gray-500">
Enable one option you intend to use: an authenticated subscription CLI, a paid API key, or a local runtime with a downloaded model. PortOS never enables a paid provider or starts model work without your action.
</p>
</div>
{providerCapability && <CapabilityRow cap={providerCapability} />}
<div className="grid gap-2 text-xs text-gray-400 sm:grid-cols-3">
<div className="rounded-lg border border-port-border bg-port-bg/40 p-3"><strong className="text-gray-200">Subscription CLI</strong><br />Claude Code, Codex, or Antigravity after local sign-in.</div>
<div className="rounded-lg border border-port-border bg-port-bg/40 p-3"><strong className="text-gray-200">API provider</strong><br />Add a key only for the paid service you chose.</div>
<div className="rounded-lg border border-port-border bg-port-bg/40 p-3"><strong className="text-gray-200">Local/private</strong><br />Ollama or LM Studio with a runnable model.</div>
</div>
</section>

<section className="space-y-3 rounded-xl border border-port-border bg-port-card p-4 sm:p-5">
<div>
<h3 className="font-semibold text-white">Optional networking</h3>
Expand All @@ -133,21 +148,6 @@ export default function CapabilityMap() {
{preference === 'none' && <p className="text-sm text-gray-400">Networking marked as not desired. You can change this preference at any time.</p>}
</section>

<section className="space-y-3 rounded-xl border border-port-border bg-port-card p-4 sm:p-5">
<div>
<h3 className="font-semibold text-white">AI provider</h3>
<p className="mt-1 text-xs text-gray-500">
Enable one option you intend to use: an authenticated subscription CLI, a paid API key, or a local runtime with a downloaded model. PortOS never enables a paid provider or starts model work without your action.
</p>
</div>
{providerCapability && <CapabilityRow cap={providerCapability} />}
<div className="grid gap-2 text-xs text-gray-400 sm:grid-cols-3">
<div className="rounded-lg border border-port-border bg-port-bg/40 p-3"><strong className="text-gray-200">Subscription CLI</strong><br />Claude Code, Codex, or Antigravity after local sign-in.</div>
<div className="rounded-lg border border-port-border bg-port-bg/40 p-3"><strong className="text-gray-200">API provider</strong><br />Add a key only for the paid service you chose.</div>
<div className="rounded-lg border border-port-border bg-port-bg/40 p-3"><strong className="text-gray-200">Local/private</strong><br />Ollama or LM Studio with a runnable model.</div>
</div>
</section>

<section className="space-y-3">
<div className="flex flex-wrap items-center justify-between gap-3">
<div>
Expand Down
5 changes: 4 additions & 1 deletion client/src/pages/CapabilityMap.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import * as api from '../services/api';
import CapabilityMap from './CapabilityMap';

describe('CapabilityMap setup walkthrough', () => {
it('keeps essential network/provider setup above optional capabilities', () => {
it('keeps the essential provider setup above optional networking and capabilities', () => {
render(<MemoryRouter><CapabilityMap /></MemoryRouter>);

expect(screen.getByRole('heading', { name: 'Setup & Capabilities' })).toBeInTheDocument();
Expand All @@ -57,6 +57,9 @@ describe('CapabilityMap setup walkthrough', () => {
'https://login.tailscale.com/admin/dns',
);
expect(screen.getByRole('heading', { name: 'AI provider' })).toBeInTheDocument();
expect(screen.getByRole('heading', { name: 'AI provider' }).compareDocumentPosition(
screen.getByRole('heading', { name: 'Optional networking' }),
) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
expect(screen.getByText('Subscription CLI')).toBeInTheDocument();
expect(screen.getByRole('heading', { name: 'Optional capabilities' })).toBeInTheDocument();
expect(screen.getByText('Calendar')).toBeInTheDocument();
Expand Down