update agents skill design
This commit is contained in:
@@ -178,6 +178,33 @@ export function outOfScopeAnswer(context) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The reply when the selected agent does not cover this page.
|
||||
*
|
||||
* Says three things, because leaving any of them out invites the reader to
|
||||
* assume something untrue: which agent is active, that the *page* is what
|
||||
* bounds the answer rather than the agent being broken, and which agent is the
|
||||
* one for here.
|
||||
*
|
||||
* It deliberately does not answer from the requested agent's own pages. An
|
||||
* agent is a lens on the page you are standing on, never a way to reach another
|
||||
* one — reaching would make selecting an agent a way around the page boundary,
|
||||
* which is the one thing the design does not permit.
|
||||
*/
|
||||
export function constrainedAgentAnswer(agent, context, suggestion) {
|
||||
const covered = (agent?.pages || []).join(', ');
|
||||
return doc(
|
||||
text(`**${agent?.name || 'That agent'}** is selected, but it does not cover **${context?.page || 'this page'}**.`),
|
||||
note(covered
|
||||
? `It works on: ${covered}.`
|
||||
: 'It covers no pages yet.'),
|
||||
text(suggestion
|
||||
? `On this page, **${suggestion.name}** is the one that answers. Switch to it, or open a page ${agent?.name || 'this agent'} covers.`
|
||||
: 'Open a page it covers, or ask something this page can answer.'),
|
||||
note('An agent narrows what can be asked here. It never widens it, so the records this page holds are the records any agent can read from it.')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a question to an action, ahead of the page responder.
|
||||
*
|
||||
@@ -185,6 +212,7 @@ export function outOfScopeAnswer(context) {
|
||||
* { kind: 'answer' } — let this page respond
|
||||
* { kind: 'navigate', destination, doc } — other page; go there
|
||||
* { kind: 'outOfScope', doc } — nothing here can answer it
|
||||
* { kind: 'constrained', doc } — the agent does not cover this page
|
||||
*/
|
||||
/* ── Workforce ──────────────────────────────────────────────────────────── */
|
||||
|
||||
@@ -820,6 +848,16 @@ function resolveDraftAction(question, workforce, positionId = null) {
|
||||
export function resolveIntent({
|
||||
question, contextId, disabledSkills = [], customSkills = [], roles = [], skillCategories = [],
|
||||
courses = [], workforce = null, skillContext = null,
|
||||
/**
|
||||
* The active agent, and where the reader is.
|
||||
*
|
||||
* Both optional and both inert when absent, so a caller that knows nothing
|
||||
* about agents resolves exactly as it always did. `agent` does not gate the
|
||||
* skills considered here — that has already happened, in `disabledSkills`,
|
||||
* which arrives carrying the agent's scoping. What it decides is whether this
|
||||
* agent should be answering on this page at all.
|
||||
*/
|
||||
agent = null, agentCoversPage = true, agentSuggestion = null, owliverContext = null,
|
||||
/* The record the control that raised this question was built from, when there
|
||||
was one. Only the draft flow reads it; a typed question carries none and
|
||||
resolves exactly as it always did. */
|
||||
@@ -827,6 +865,18 @@ export function resolveIntent({
|
||||
}) {
|
||||
const context = ASSISTANT_CONTEXTS[contextId] ?? null;
|
||||
|
||||
/**
|
||||
* 0. The selected agent does not belong here.
|
||||
*
|
||||
* Ahead of everything, because every matcher below would otherwise answer
|
||||
* from this page while the header names an agent that does not cover it — an
|
||||
* answer attributed to the wrong lens. The page still decides what is
|
||||
* readable; this only declines to pretend the agent chose it.
|
||||
*/
|
||||
if (agent && !agentCoversPage) {
|
||||
return { kind: 'constrained', agent, doc: constrainedAgentAnswer(agent, context, agentSuggestion) };
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Finishing a draft, wherever the reader is standing.
|
||||
*
|
||||
@@ -846,7 +896,10 @@ export function resolveIntent({
|
||||
/* 2. Current page skills — specific triggers, ahead of the general reader. */
|
||||
const skill = resolveSkill({
|
||||
question, contextId, disabledSkills, customSkills, roles, skillCategories, courses,
|
||||
skillContext,
|
||||
/* The envelope travels beside the collections rather than replacing them:
|
||||
a resolver reads records, and the envelope says where the reader is. A
|
||||
source that needs a position still finds it exactly where it always was. */
|
||||
skillContext: owliverContext ? { ...skillContext, owliver: owliverContext } : skillContext,
|
||||
});
|
||||
if (skill) return skill;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user