update draft issue
This commit is contained in:
@@ -7,6 +7,10 @@ import {
|
||||
matchOwliverSkill, owliverSkillsForContext, presentable, resolveOwliverResponse,
|
||||
responseTitle, summaryLines,
|
||||
} from '@/lib/skills/owliverResolver';
|
||||
import {
|
||||
draftActions, draftContinuedReply, explainWeightsReply, matchDraftIntent, noDraftReply,
|
||||
resolveDraft, weightsFromQuestion, weightsReply, weightsUnchangedReply, whichDraftReply,
|
||||
} from '@/lib/skills/draftFlow';
|
||||
import {
|
||||
appliedToday, askWhichPosition, assignmentPreview, assignmentToExecute, availability,
|
||||
candidateDetail, candidateMatches, candidateRoute, interviewReady, matchWorkforceIntent,
|
||||
@@ -707,12 +711,121 @@ function resolveSkill({
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A draft question, resolved against the position records the panel holds.
|
||||
*
|
||||
* Returns an intent the panel executes. The two that write — generating a
|
||||
* description and setting weights, plus publishing — carry a `perform` block
|
||||
* rather than performing anything here: this module stays pure, and the write
|
||||
* goes through the mutation the Create Position form already uses.
|
||||
*/
|
||||
function resolveDraftAction(question, workforce, positionId = null) {
|
||||
const action = matchDraftIntent(question);
|
||||
if (!action) return null;
|
||||
|
||||
const positions = workforce.positions || [];
|
||||
/* `positionId` is the record a control was built from — the Continue button on
|
||||
a card, or a chip this flow wrote. It settles the question before any
|
||||
guessing from the wording starts. */
|
||||
const { position, ambiguous } = resolveDraft(
|
||||
question, positions, workforce.currentPositionId, positionId
|
||||
);
|
||||
|
||||
if (ambiguous) return { kind: 'draft', ...whichDraftReply(ambiguous) };
|
||||
|
||||
/**
|
||||
* Nothing resolved. Only a question explicitly about drafts is answered with
|
||||
* "there are none" — everything else is handed back.
|
||||
*
|
||||
* "Summarize these vetting weights" on the Create Position form is a question
|
||||
* about the form, and the page has answered it since long before drafts could
|
||||
* be continued here. Claiming it because it contains the word "weights" and
|
||||
* then reporting that no draft exists would be this flow taking a question it
|
||||
* cannot answer.
|
||||
*/
|
||||
if (!position) {
|
||||
return action === 'continue' || action === 'list'
|
||||
? { kind: 'draft', doc: noDraftReply() }
|
||||
: null;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
/* One draft is continued; several are offered by name. Either way the
|
||||
answer is here, and neither opens a form. */
|
||||
case 'list':
|
||||
return positions.filter((p) => p.status === 'draft').length > 1
|
||||
? { kind: 'draft', ...whichDraftReply(positions.filter((p) => p.status === 'draft')) }
|
||||
: {
|
||||
kind: 'draft',
|
||||
doc: draftContinuedReply(position),
|
||||
followUp: draftActions(position),
|
||||
};
|
||||
|
||||
case 'continue':
|
||||
return {
|
||||
kind: 'draft',
|
||||
doc: draftContinuedReply(position),
|
||||
/* Never "continue" again — the reply *is* the continuation. */
|
||||
followUp: draftActions(position),
|
||||
};
|
||||
|
||||
case 'show_weights':
|
||||
return { kind: 'draft', doc: weightsReply(position), followUp: draftActions(position) };
|
||||
|
||||
case 'explain_weights':
|
||||
return { kind: 'draft', doc: explainWeightsReply(position), followUp: draftActions(position) };
|
||||
|
||||
case 'set_weights': {
|
||||
const next = weightsFromQuestion(question, position);
|
||||
if (!next) {
|
||||
return { kind: 'draft', doc: weightsUnchangedReply(position), followUp: draftActions(position) };
|
||||
}
|
||||
return { kind: 'draft', perform: { action: 'set_weights', position, weights: next } };
|
||||
}
|
||||
|
||||
case 'generate_description':
|
||||
return { kind: 'draft', perform: { action: 'generate_description', position } };
|
||||
|
||||
case 'publish':
|
||||
return position.status === 'draft'
|
||||
? { kind: 'draft', perform: { action: 'publish', position } }
|
||||
: {
|
||||
kind: 'draft',
|
||||
doc: doc(text(`**${position.title}** is already published.`)),
|
||||
followUp: draftActions(position),
|
||||
};
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveIntent({
|
||||
question, contextId, disabledSkills = [], customSkills = [], roles = [], skillCategories = [],
|
||||
courses = [], workforce = null, skillContext = 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. */
|
||||
positionId = null,
|
||||
}) {
|
||||
const context = ASSISTANT_CONTEXTS[contextId] ?? null;
|
||||
|
||||
/**
|
||||
* 1. Finishing a draft, wherever the reader is standing.
|
||||
*
|
||||
* Ahead of everything else because these questions name a record and an act
|
||||
* on it — continuing, generating, weighting, publishing — and every other
|
||||
* matcher would read them as words about positions in general. It runs only
|
||||
* where the panel actually has the positions to act on.
|
||||
*/
|
||||
/* Resolved even where the panel carries no workforce: a question about
|
||||
continuing a draft is answered in the panel or answered as "there is no
|
||||
draft", never handed to keyword routing — which is what used to send
|
||||
"Continue the Bartender draft" into the authoring form, because Create
|
||||
Position lists `position` and `role` among its topics. */
|
||||
const draftIntent = resolveDraftAction(question, workforce || { positions: [] }, positionId);
|
||||
if (draftIntent) return draftIntent;
|
||||
|
||||
/* 2. Current page skills — specific triggers, ahead of the general reader. */
|
||||
const skill = resolveSkill({
|
||||
question, contextId, disabledSkills, customSkills, roles, skillCategories, courses,
|
||||
|
||||
Reference in New Issue
Block a user