import * as React from 'react';
import { LayoutTemplate, Minus, Pencil, Plus, SearchX } from 'lucide-react';
import { Link } from 'react-router-dom';
import { cn } from '@/lib/utils';
import { Alert, Button, SearchInput, Switch } from '@/components/ds';
/**
* Board skills, under the agent that stands beside them.
*
* The second half of one Skills section — the same heading, a tab away from the
* Owliver catalog — so nobody has to decide between two top-level destinations
* ever again.
*
* **Two controls, because there are two different questions.** This card used to
* offer only the workspace switch, and said so at length: a Board skill was not
* carried by an agent, because `SkillSurface` read the page and the account's
* `disabledSkills` and never looked at `agent.skills`. That was true, and it is
* not any more — `useSkillSections` now asks `agentPermitsSkill`, so an id
* written into `agent.skills` is honoured on the page.
*
* So both questions are asked here, and neither is dressed up as the other:
*
* - **Active** is the workspace switch. Off means off for everyone, on every
* page, for every agent. It is the account's `disabledSkills`.
* - **Add to agent** is ownership. It writes this skill's id into
* `agent.skills`, through the same handler the Owliver catalog uses.
*
* Ownership is opt-in and that is what makes the two safe together: a skill no
* agent claims still draws wherever its `pages:` say, exactly as before. The
* first agent to claim it is what narrows it — which is why attaching is worth
* saying out loud on the card rather than leaving as a silent side effect.
*/
/** One Board skill: what it draws, where, and whether it is switched on. */
function BoardCard({ entry, enabled, onToggle, onSurfaces, busy, attached = false, onAttach = null }) {
const switchId = `board-${entry.id}`;
return (
{/* Soft Background Highlight on Hover */}
Board Skill
{enabled ? 'Active' : 'Disabled'}
onToggle(entry.id, next)}
aria-label={`${entry.name} — ${enabled ? 'on' : 'off'} for this workspace`}
/>
{entry.name}
{entry.description && (
{entry.description}
)}
{/* What it actually draws. */}
{entry.sections.length > 0 && (
{/* Ownership, separate from the workspace switch above it. The button
writes `agent.skills` through the same handler the Owliver catalog
uses — there is no second assignment path and nothing new stored. */}
{onAttach && (
{attached
? 'Owned by this agent'
: 'Not owned by any agent on this page'}
)}
{entry.surfaces.some((s) => onSurfaces.has(s.id))
? 'Active on this agent\'s pages'
: 'Draws across workspace'}
Edit
);
}
export function BoardSkillList({
entries, agentPages = [], disabledIds, onToggle, busy = false, query, onQueryChange, total,
attachedIds = null, onAttach = null,
}: any) {
const searchId = React.useId();
const onSurfaces = React.useMemo(() => new Set(agentPages), [agentPages]);
/* The ones that meet this agent first */
const ordered = React.useMemo(() => {
const here = [];
const elsewhere = [];
for (const e of entries) {
(e.surfaces.some((s) => onSurfaces.has(s.id)) ? here : elsewhere).push(e);
}
return [...here, ...elsewhere];
}, [entries, onSurfaces]);
return (
Active is workspace-wide: off means off on every page, for every
agent. Add to agent is ownership — once any agent owns a board
skill, it draws only where an owning agent is answering. A skill no agent owns
keeps drawing wherever its pages say, as before.
{total > 0 && (