Files
DemonGatanjieuandClaude Opus 5.5 cd9751ef14 AI workbench: the flow over a task, and gates that wait for your OK
- api/ai_gates.py: changing the canvas, using the GPU, downloading and scanning online can each
  go ahead, ask first or never (downloads ask by default; anomalous/ai_gates.json). A call that
  asks waits on its step (state "asking", what it would do listed) up to 50 s for Allow or No
  (with the user's reason for the AI); unanswered, the AI is told to wait and call again, the
  later answer reaches it as a message, and the same call after an Allow goes ahead.
- ui_ai_gate.js: the card under a waiting step and the Gates window; a toast while elsewhere.
- ui_ai_flow.js + ai_task_view.flowStages: the task's stages in order, each done, running,
  waiting or failed; a stage leads to its first step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 14:48:43 +08:00

35 lines
1.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* The flow over an AI task: the stages of the work its steps went through, in the order they
* came (models, combo, prompt, canvas, run, pictures, voice, library: action_catalog.py's), each
* saying whether it is done, running, waiting for the user or failed. A stage leads to its first
* step in the timeline (`goTo(stepId)`). The stages come from ai_task_view.js flowStages.
*/
import { translate as t } from './locales.js';
import { flowStages } from './ai_task_view.js';
function el(tag, className, text) {
const node = document.createElement(tag);
if (className) node.className = className;
if (text !== undefined) node.textContent = text;
return node;
}
export function flowMap(task, goTo) {
const stages = flowStages(task);
if (!stages.length) return null;
const box = el('div', 'anomalous-ai-flow');
box.setAttribute('aria-label', t('aiFlow'));
stages.forEach((item, at) => {
if (at) box.append(el('span', 'anomalous-ai-flow-arrow', '›'));
const chip = el('button', `anomalous-ai-flow-stage is-${item.state}`);
chip.type = 'button';
chip.title = t(`aiFlowState_${item.state}`);
chip.append(el('span', 'anomalous-ai-flow-mark'), el('span', '', t(`aiStage_${item.stage}`)));
if (item.count > 1) chip.append(el('span', 'anomalous-ai-flow-count', `×${item.count}`));
chip.onclick = () => goTo(item.first);
box.append(chip);
});
return box;
}