update owliver skill

This commit is contained in:
2026-08-14 17:33:16 +05:30
parent cccada9bd2
commit 4fdfb90326
58 changed files with 8015 additions and 1339 deletions

View File

@@ -6,6 +6,10 @@ import {
import { cn } from '@/lib/utils';
import { Badge } from '@/components/ui/badge';
import { ProgressBar, toneForScore } from '@/components/ds/Progress';
import { SECTION_COMPONENTS } from '@/components/skills/SkillSections';
import { useSkillDataContext } from '@/components/skills/SkillSurface';
import { resolveSkillData } from '@/lib/skills/dataResolver';
import { usePageAction } from './PageContext';
/**
* Renderers for response blocks.
@@ -441,8 +445,55 @@ const NoteBlock = React.memo(({ block }) => (
));
NoteBlock.displayName = 'NoteBlock';
/**
* A section a skill declared, drawn by the component the page uses for it.
*
* There is no chat-specific renderer for a skill's shapes, and there must not
* be: `SECTION_COMPONENTS` is the single table from a declared type to a
* component, and this block goes through it exactly as `SkillSurface` does. A
* definition that gains a new shape gains it in both places at once, and a
* shape the table does not carry renders nothing rather than something
* improvised.
*/
const SkillSectionBlock = React.memo(({ block }) => {
const section = block.section;
const Component = SECTION_COMPONENTS[section?.shape || section?.type];
/**
* A settable answer is re-read, never replayed.
*
* An ordinary answer is a record of what was true when it was given, and the
* stored blocks are exactly right for that. A section offering *controls* is
* different: it is a live view of a value the reader can still change, from
* here or on the page behind the panel. Replaying the stored copy would show
* a weight of 25% next to a form that now says 30%, and the control would
* write the stale figure back.
*
* So an editable section resolves from the current context on every render,
* through the same resolver the page's own card uses. There is one value and
* one place it lives; this is a second window onto it, not a second copy.
*/
const live = Boolean(section?.editable);
const context = useSkillDataContext(null);
const data = React.useMemo(
() => (live && section ? resolveSkillData(section, context) : block.data),
[live, section, context, block.data]
);
const apply = usePageAction(live ? section?.source : null);
if (!Component) return null;
return (
<div className="rounded-xl border border-border bg-surface-subtle/60 p-3">
<Component data={data} section={section} onApply={apply} compact />
</div>
);
});
SkillSectionBlock.displayName = 'SkillSectionBlock';
const RENDERERS = {
text: TextBlock,
skillSection: SkillSectionBlock,
heading: HeadingBlock,
kpis: KpisBlock,
status: StatusBlock,