Files
DemonGatanjieuandClaude Opus 5.5 342946141e Make the AI's questions and the waiting page say what to press
The user took an option for something to select and then pressed "skip"
to confirm; boxes shown open read as fields to fill.

- Questions (stage panels, the strip over the message box): options are
  buttons with an arrow under "One press sends it to the AI" and show the
  pressed one at once; "Let the AI decide" moves to the question's top
  right (the panel title for ask_user); a line of one's own is folded as
  "None of these, I'll say it…". The Gates card folds its reason the same.
- A waiting task is one page: the sentence for the AI leads and sticks
  under the task header while the page scrolls (the workbench measures the
  header); "Say what to do" and the gallery are optional folds that say
  how many pictures are in. The sentence has the AI do what the task says,
  asking only when it says nothing. The Get started / Put ready tabs and
  their words are gone.
- Gates window texts fixed (canvas covers building, lines are over the
  message box, "Ask me" named as on the button); run_workflow waits up to
  55 s by default, so a quick run comes back with its pictures.
- The UI map counts words the backend names (label_key) as used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 03:54:20 +08:00

32 lines
2.0 KiB
JavaScript

/**
* The lines the user can paste into the AI's chat for a task (ui_ai_call.js draws them over the
* message box). Anomalous cannot wake an AI app, so when the AI has stopped the user tells it in a
* word, picked by what waits: a run it was not told has ended (`call_ai`, api/ai_task_runs.py),
* something the user gave it that it has not got yet, or nothing (go on). The last line picks the
* task up in a new chat. A task that ended has lines only while a reply of the user's waits (writing
* to it opens it again, api/ai_panels.py); one still waiting for its first AI has none
* (ui_ai_ready.js, the waiting page, has the line that starts it).
*/
const REPLIES = new Set(['user_message', 'user_marks', 'user_pictures', 'user_toolbox']);
export const NEW_CHAT = 'aiCallNewChat';
/** Whether the user gave the AI something it has not got: words, marks, pictures, materials, an answer, a late gate decision. */
export function unseenReply(task) {
return (task?.steps || []).some(step => (step.kind === 'user' && REPLIES.has(step.tool) && !step.delivered)
|| (step.gate?.timed_out && step.gate.decision && !step.gate.delivered)
|| Object.values(step.answers || {}).some(given => !given.delivered));
}
/** {lead, lines} as locale keys for `task` (the first line is the one to send), or null. */
export function callLines(task) {
const steps = task?.steps || [];
if (!task || (task.waiting && steps.every(step => step.kind === 'user'))) return null;
if (task.ended) return unseenReply(task) ? { lead: 'aiCallRepliedLead', lines: ['aiCallReplied', NEW_CHAT] } : null;
const run = steps.findLast(step => step.tool === 'run_workflow' && step.call_ai);
if (run?.state === 'done') return { lead: 'aiCallDoneLead', lines: ['aiCallDone', 'aiCallAgain', NEW_CHAT] };
if (run?.state === 'error') return { lead: 'aiCallFailedLead', lines: ['aiCallFailed', NEW_CHAT] };
if (unseenReply(task)) return { lead: 'aiCallRepliedLead', lines: ['aiCallReplied', NEW_CHAT] };
return { lead: 'aiCallLead', lines: ['aiCallGoOn', NEW_CHAT] };
}