Require two materials for content schedules and scope readiness copy
The engine plans each production piece from a pair of documents, so a summary, quiz or similar schedule with one material can never plan. Approving such a plan is now blocked with a note to choose or upload another material, and the engine's refusal on an existing schedule is explained in plain language. Video and research schedules still work with one material. The engine now checks only a schedule's own material before a run, so the run error and Upload texts no longer say the whole Library or Brain is checked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
||||
} from '../express/parse'
|
||||
import { ask, chatLangOf, editRule, EMPTY, nextQuestion, removeRule, respond, type AgentState } from '../express/agent'
|
||||
import { inLang, t, useLang, type Key, type Lang } from '../i18n'
|
||||
import { budgetFor, canSchedule, createSchedule, VIDEO, videoQuote } from '../express/schedules'
|
||||
import { budgetFor, canSchedule, createSchedule, MIN_PRODUCTION_SOURCES, needsTwoSources, VIDEO, videoQuote } from '../express/schedules'
|
||||
|
||||
const EXAMPLES: Key[] = ['ins.ex1', 'ins.ex2', 'ins.ex3', 'ins.ex4', 'ins.ex5']
|
||||
const THINKING: Key[] = ['agent.think1', 'agent.think2', 'agent.think3']
|
||||
@@ -59,6 +59,9 @@ export function InstructionPage() {
|
||||
const view: AgentState = { ...agent, sources }
|
||||
const question = nextQuestion(view)
|
||||
const ready = agent.items.filter(i => canSchedule(i.rule))
|
||||
// Without a choice the whole Brain is attached, so every ready document counts.
|
||||
const sourceCount = chosen.length || choosable(docs.data).length
|
||||
const tooFewSources = sourceCount < MIN_PRODUCTION_SOURCES && ready.some(i => needsTwoSources(i.rule))
|
||||
const hasContent = agent.items.some(i => i.rule.type === 'content')
|
||||
// The agent's current turn: its question, or what it is waiting for. It stays live, so an edit in the plan updates it.
|
||||
const live = inLang(lang, () => saving
|
||||
@@ -108,7 +111,7 @@ export function InstructionPage() {
|
||||
|
||||
async function approve(state = agent, replyLang = lang) {
|
||||
const items = state.items.filter(i => canSchedule(i.rule))
|
||||
if (!items.length) return
|
||||
if (!items.length || tooFewSources) return
|
||||
setSaving(true)
|
||||
const done: Outcome[] = []
|
||||
const created = new Set<number>()
|
||||
@@ -201,8 +204,9 @@ export function InstructionPage() {
|
||||
<small>
|
||||
<b className="rule-sources"><Icon name="brain" />{chosen.length ? t('ins.sourcesChosen', { n: chosen.length }) : t('ins.sourcesAll')}</b>
|
||||
{t('ins.approveNote')}
|
||||
{tooFewSources && <span className="error">{t(chosen.length ? 'ins.tooFewChosen' : 'ins.tooFewInBrain', { n: MIN_PRODUCTION_SOURCES })}</span>}
|
||||
</small>
|
||||
<button className="btn primary" disabled={saving || !idle} onClick={() => approve()}>
|
||||
<button className="btn primary" disabled={saving || !idle || tooFewSources} onClick={() => approve()}>
|
||||
<Icon name="check" />{saving ? t('ins.approving') : t('ins.approve', { n: ready.length })}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user