Privacy mode left the AI blind twice over: the whole prompt was a token, so it could not help with light, lens or style, and model and LoRA file names still went out as written. - The prompt box has a first field, the gist: the picture in words the user writes for the AI to read. seal_answer hands it on as written beside the tokens of the private prompts; either alone can be handed in. - ai_sealed_models.py: while the Gates window's "Model names in a private task" is on (the default), each model of the library is one token ([M1], sealed as its model_id) however an answer writes it: model_id, loader name, file name in a text, card name. A model's own entry drops name, file, folder, links and hash and keeps type, base model, the author's settings and the user's note. expand writes a model token back as the model_id, as the loader's name among a node's values, as the card's name inside the AI's words. The task's menu lists what each token stands for. - The model editor has "Note for the AI" (ai_note, note_for_ai in the tools, searched by search_models): what a model is for, in words the AI may read. - A combo's name is sealed too: unless renamed it is made of its model's name and the start of its prompt. - The privacy skill says how to write around a gist and how to pick and pass on model tokens. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
57 lines
2.8 KiB
JavaScript
57 lines
2.8 KiB
JavaScript
/**
|
|
* The ⋯ of a task, in its head and on its row in the list: what is done to a task now and then (rename
|
|
* it, say what it goes on from, keep its pictures from the AI, remove it), out of the way of the tools
|
|
* used while it runs.
|
|
*/
|
|
|
|
import { translate as t } from './locales.js';
|
|
import { forgetTask } from './ai_task_cache.js';
|
|
import { anomalousAlert, anomalousConfirm, anomalousPrompt } from './ui_dialog.js';
|
|
import { modelTokens, setPrivacy } from './ui_ai_privacy.js';
|
|
import { pickTaskLink } from './ui_ai_task_links.js';
|
|
import { openPopupMenu } from './ui_popup_menu.js';
|
|
|
|
/**
|
|
* What the menu of `task` does. `tasks`: the list's summaries; `post(id, body)` writes to the task,
|
|
* `refresh()` draws the page again, `removed()` lets go of a removed task, before that.
|
|
*/
|
|
export function menuActions(task, { tasks, post, refresh, removed }) {
|
|
return { tasks, changed: () => void refresh(), rename: async () => {
|
|
const named = await anomalousPrompt(t('aiRenamePrompt'), task.title || '', t('aiRename'));
|
|
if (named === null || named === undefined) return;
|
|
await post(task.id, { title: named }).catch(error => anomalousAlert(error.message));
|
|
await refresh();
|
|
}, remove: async () => {
|
|
if (!await anomalousConfirm(t('aiRemoveConfirm'), t('aiRemove'))) return;
|
|
await post(task.id, { remove: true }).catch(error => anomalousAlert(error.message));
|
|
forgetTask(task.id);
|
|
removed();
|
|
await refresh();
|
|
} };
|
|
}
|
|
|
|
/** The menu of `task` (its full record) under `anchor`; the rest from menuActions. */
|
|
export function openTaskMenu(anchor, task, { tasks, rename, remove, changed }) {
|
|
const place = anchor.getBoundingClientRect(); // the head is drawn anew every few seconds: the button may be another by the time a row is chosen
|
|
openPopupMenu(anchor, [
|
|
{ label: t('aiRename'), run: rename },
|
|
...(task.links?.from ? [] : [{ label: t('aiTaskLink'), title: t('aiTaskLinkHint'), run: () => pickTaskLink(place, task, tasks, changed) }]),
|
|
{ label: t(task.private ? 'aiPrivacyTurnOff' : 'aiPrivacyTurnOn'), title: t(task.private ? 'aiPrivacyHint_on' : 'aiPrivacyHint_off'),
|
|
run: () => void setPrivacy(task, !task.private, changed) },
|
|
...(modelTokens(task) ? [{ label: t('aiModelTokens'), title: t('aiModelTokensHint'),
|
|
run: () => void anomalousAlert(modelTokens(task), t('aiModelTokens')) }] : []),
|
|
{ label: t('aiRemove'), danger: true, run: remove },
|
|
]);
|
|
}
|
|
|
|
/** The button in the head of `task`. */
|
|
export function taskMenu(task, actions) {
|
|
const more = document.createElement('button');
|
|
more.type = 'button';
|
|
more.className = 'anomalous-ai-tool is-icon';
|
|
more.textContent = '⋯';
|
|
more.title = t('notebookMore');
|
|
more.onclick = () => openTaskMenu(more, task, actions);
|
|
return more;
|
|
}
|