agnets done
This commit is contained in:
@@ -44,7 +44,19 @@ const PER_SKILL = 3;
|
||||
const TOTAL = 4;
|
||||
|
||||
/**
|
||||
* The chips a page's skills offer.
|
||||
* The chips a page's skills *declare*.
|
||||
*
|
||||
* NOT what the panel renders, and no longer on the production path. Which
|
||||
* suggestions Owliver offers is decided by `GET /api/v1/owliver/suggestions` —
|
||||
* the backend filters against the caller's role and ranks against the rows in
|
||||
* PostgreSQL, and `lib/skills/serverSuggestions.js` turns the reply into chips.
|
||||
* Nothing in `src/` ranks a suggestion any more.
|
||||
*
|
||||
* What is left here is the reading of a *definition*: given a skill file, what
|
||||
* did its author write under `owliver.suggestions`, and which of those name a
|
||||
* capability the skill actually offers. That is a question about the Markdown
|
||||
* rather than about the workspace, and it is what the editor's preview and the
|
||||
* definition checks in `scripts/skill-check.mjs` ask.
|
||||
*
|
||||
* Capped deliberately. A workspace with six skills attached would otherwise
|
||||
* bury the page's own suggestions under twenty of them, and a suggestion nobody
|
||||
@@ -365,52 +377,3 @@ export function presentable(data) {
|
||||
export const CAPABILITY_SUMMARIES = OWLIVER_CAPABILITIES.map(
|
||||
({ id, label, summary }) => ({ id, label, summary })
|
||||
);
|
||||
|
||||
/* ── Suggestions for a record that has just appeared ────────────────────── */
|
||||
|
||||
/**
|
||||
* What can now be asked about a record the conversation just produced.
|
||||
*
|
||||
* Creating a position is the moment "who could do this?" becomes worth asking,
|
||||
* and the panel is the only thing that knows a position now exists. Rather than
|
||||
* naming a skill to offer — which would put a candidate-matching feature inside
|
||||
* the position-creation flow — this asks the registry the general question: of
|
||||
* the skills attached to this page, which declare a capability whose reading is
|
||||
* *about one position*? Those are exactly the ones that can say something about
|
||||
* the record just made.
|
||||
*
|
||||
* The record's own title is appended to each prompt, so the answer resolves
|
||||
* against it directly and the reader is never asked to pick from a list that
|
||||
* includes the position they are looking at. Nothing is named here: a skill
|
||||
* added tomorrow that reads a position is offered on the same terms.
|
||||
*/
|
||||
export function suggestionsForPosition(contextId, disabled = [], customSources = [], position) {
|
||||
if (!position?.title) return [];
|
||||
|
||||
const chips = [];
|
||||
|
||||
for (const skill of owliverSkillsForContext(contextId, disabled, customSources)) {
|
||||
/* Only capabilities that read one position — a workspace-wide reading has
|
||||
nothing to do with the record that was just created. */
|
||||
const scoped = skill.owliver.capabilities.filter(
|
||||
(capability) => skill.owliver.responses[capability]?.context === 'positionId'
|
||||
);
|
||||
if (!scoped.length) continue;
|
||||
|
||||
const offered = skill.owliver.suggestions
|
||||
.filter((s) => !s.capability || scoped.includes(s.capability))
|
||||
.slice(0, 1)
|
||||
.map((s) => ({
|
||||
label: s.label,
|
||||
/* Named, so the reading resolves against this position rather than
|
||||
asking which one. */
|
||||
prompt: `${s.prompt} for ${position.title}`,
|
||||
skillId: skill.id,
|
||||
skillCapability: s.capability || null,
|
||||
}));
|
||||
|
||||
chips.push(...offered);
|
||||
}
|
||||
|
||||
return chips.slice(0, 2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user