Automation editor with graphical schedule and assistant; movable chat list groups

Automations
- Job files hold only the instructions; name, schedule, mode, model, approval
  mode and time limit are settings in the database (jobs.settings). Existing
  files are adopted on start-up (frontmatter into the database and removed from
  the file); plain Markdown files registered later get default settings and stay
  switched off until scheduled.
- New automation: name, project and a starting point (blank example structure or
  a template) create .codecraft/jobs/<name>.md and open the editor: settings with
  a graphical cron builder (next runs in server time via /jobs/schedule), the
  instructions in the Markdown editor and an assistant chat
  (POST /jobs/{id}/assistant) whose model edits the file; the editor reloads it
  after each turn and warns about conflicts with unsaved edits.
- The schedule tool writes prompt-only files with settings.

Chat list
- Folders and projects keep a user-defined order and can be pinned (drag and
  drop, or the group's menu), stored per user via /account/sidebar. A new
  message moves the chat to the top of its group, no longer the project itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-10 10:05:15 +01:00
1 parent 872ebb94dd
commit 05c215f685
19 files changed
+1661 -356

No files matched your search

+53 -10
View File
@@ -344,7 +344,7 @@ export const de: Messages = {
"agents.refineShort": "Review ×{n}",
"agents.deleteFile": "Agenten-Datei {path} löschen?",
"nav.jobs": "Automationen",
"jobs.intro": "Agenten, die nach Zeitplan starten. Jede Automation ist eine Markdown-Datei (Auftrag + Zeitplan im Frontmatter) – lass sie dir in einem Chat von einem Agenten anlegen (Tool „schedule“) oder registriere unten eine Datei. Jeder Lauf erscheint als normaler Chat; braucht er eine Freigabe, bekommst du eine Push-Benachrichtigung.",
"jobs.intro": "Agenten, die nach Zeitplan starten. Die Anweisungen jeder Automatisierung stehen in einer Markdown-Datei; Name, Zeitplan und Einstellungen legst du hier fest. Mit „Neue Automatisierung“ anlegen und die Anweisungen mit dem Assistenten erarbeiten – oder einen Agenten in einem Chat darum bitten (Tool „schedule“). Jeder Lauf erscheint als normaler Chat.",
"jobs.none": "Noch keine Automationen.",
"jobs.schedule": "Zeitplan",
"jobs.next": "Nächster Lauf",
@@ -355,13 +355,12 @@ export const de: Messages = {
"jobs.enable": "Aktivieren",
"jobs.disable": "Deaktivieren",
"jobs.runNow": "Jetzt starten",
"jobs.editFile": "Datei bearbeiten",
"jobs.remove": "Entfernen",
"jobs.deleteConfirm": "Automation „{name}“ entfernen? Die Job-Datei bleibt erhalten.",
"jobs.openRun": "Lauf öffnen",
"jobs.prompt": "Auftrag",
"jobs.register": "Job-Datei registrieren",
"jobs.registerHint": "Pfad zu einer Markdown-Datei mit Zeitplan im Frontmatter:",
"jobs.register": "Vorhandene Datei registrieren",
"jobs.registerHint": "Pfad zu einer Markdown-Datei mit Anweisungen (ältere Dateien mit Zeitplan im Frontmatter werden übernommen):",
"jobs.registerBtn": "Registrieren",
"jobs.status.running": "läuft",
"jobs.status.done": "fertig",
@@ -509,6 +508,11 @@ export const de: Messages = {
"sidebar.unpin": "Nicht mehr anpinnen",
"sidebar.openBeside": "Daneben öffnen",
"chat.closePane": "Spalte schließen",
"sidebar.groupMenu": "Ordner-Optionen",
"sidebar.groupPin": "Oben fixieren",
"sidebar.groupUnpin": "Nicht mehr fixieren",
"sidebar.groupUp": "Nach oben",
"sidebar.groupDown": "Nach unten",
"sidebar.moveTo": "In Ordner verschieben…",
"sidebar.removeFromFolder": "Aus Ordner entfernen",
"sidebar.archiveOne": "Archivieren",
@@ -545,14 +549,9 @@ export const de: Messages = {
"backup.s3Keep": "Im Bucket behalten (0 = alle)",
"backup.last": "Letztes Backup",
"backup.s3Ok": "hochgeladen",
"jobs.fromTemplate": "Neue Automation aus Vorlage",
"jobs.tplName": "Name",
"jobs.tplProject": "Projektordner",
"jobs.tplSchedule": "Wann",
"jobs.tplCronHint": "Cron: Minute Stunde Tag Monat Wochentag (Zeitzone des Servers).",
"jobs.tplMode": "Modus",
"jobs.tplPrompt": "Aufgabe für den Agenten",
"jobs.tplCreate": "Automation anlegen",
"new.title": "Neue Session",
"new.directory": "Projektverzeichnis",
"new.up": "Hoch",
@@ -595,8 +594,52 @@ export const de: Messages = {
"chat.compactingDetail": "{tokens} von {limit} Tokens ({pct}) – danach arbeitet der Agent mit einer Zusammenfassung weiter",
"chat.telegram": "Fragen an Telegram senden",
"chat.telegramHint": "Freigaben und Rückfragen dieses Chats auch per Telegram schicken (der gerade in Telegram geöffnete Chat meldet sich immer)",
"cron.label": "Zeitplan",
"cron.mode.minutes": "Alle paar Minuten",
"cron.mode.hourly": "Stündlich",
"cron.mode.daily": "Täglich",
"cron.mode.weekly": "An Wochentagen",
"cron.mode.monthly": "Monatlich",
"cron.mode.custom": "Cron-Ausdruck",
"cron.every": "Alle",
"cron.minutes": "Minuten",
"cron.atMinute": "Zur Minute",
"cron.days": "Wochentage",
"cron.workdays": "Mo–Fr",
"cron.onDay": "Am",
"cron.at": "um",
"cron.customHint": "Minute Stunde Tag Monat Wochentag, z. B. „30 6 * * 1-5“ = Mo–Fr 06:30.",
"cron.nextRuns": "Nächste Läufe:",
"cron.shortMonths": "Monate ohne diesen Tag werden übersprungen.",
"cron.serverTz": "Uhrzeiten in Serverzeit ({tz})",
"jobEditor.saved": "Gespeichert",
"jobEditor.conflict": "Die Anweisungen wurden inzwischen geändert (z. B. vom Assistenten). Mit deiner Fassung überschreiben?",
"jobEditor.overwrite": "Überschreiben",
"jobEditor.runUnsaved": "Es gibt ungespeicherte Änderungen – der Lauf verwendet die gespeicherte Fassung. Trotzdem starten?",
"jobEditor.discard": "Ungespeicherte Änderungen verwerfen?",
"jobEditor.back": "Zurück zu den Automatisierungen",
"jobEditor.tab.prompt": "Anweisungen",
"jobEditor.tab.settings": "Zeitplan",
"jobEditor.tab.assistant": "Assistent",
"jobEditor.timeout": "Zeitlimit (Min.)",
"jobEditor.bypassHint": "Läuft nachts: Mit „Alles erlauben“ wartet der Lauf nie auf eine Freigabe.",
"jobEditor.instructions": "Anweisungen",
"jobEditor.instructionsHint": "Der Agent sieht nur diesen Text – keinen Chat, niemanden zum Nachfragen.",
"jobEditor.changedOnDisk": "Der Assistent hat die Datei geändert, während du bearbeitet hast.",
"jobEditor.reload": "Seine Fassung laden",
"jobEditor.assistantIntro": "Erarbeite die Anweisungen zusammen mit einem Modell: Beschreib, was die Automatisierung tun soll – es fragt nach und schreibt die Datei nebenan mit.",
"jobEditor.assistantStart": "Assistent starten",
"jobEditor.defaultModel": "Server-Standard",
"jobs.new": "Neue Automatisierung",
"jobs.namePlaceholder": "z. B. Nächtlicher Abhängigkeits-Check",
"jobs.fileHint": "Die Anweisungen landen in .codecraft/jobs/<name>.md in diesem Ordner.",
"jobs.startWith": "Beginnen mit",
"jobs.blank": "Leer",
"jobs.blankDesc": "Beispielgliederung zum Ausfüllen mit dem Assistenten",
"jobs.createAndEdit": "Anlegen und bearbeiten",
"jobs.edit": "Bearbeiten",
"jobs.permissionMode": "Freigabemodus",
"jobs.permissionModeHint": "Gilt ab dem nächsten Lauf (wird in die Datei geschrieben). „Alles erlauben“: der Lauf fragt nie nach und wartet nicht auf Freigaben.",
"jobs.permissionModeHint": "Gilt ab dem nächsten Lauf. „Alles erlauben“: der Lauf fragt nie nach und wartet nicht auf Freigaben.",
"instructions.title": "Anweisungen für diesen Chat",
"instructions.hint": "Gelten für jede Nachricht in diesem Chat, zusätzlich zum Modus – z. B. Sprache, Ton, Regeln oder der Teil des Projekts, um den es geht.",
"instructions.placeholder": "z. B. Antworte immer auf Englisch. Ändere nur Dateien unter api/. Frag, bevor du Abhängigkeiten hinzufügst.",
+53 -10
View File
@@ -343,7 +343,7 @@ export const en = {
"agents.refineShort": "Review ×{n}",
"agents.deleteFile": "Delete agent file {path}?",
"nav.jobs": "Automations",
"jobs.intro": "Agents that start on a schedule. Each automation is a Markdown file (prompt + schedule in the frontmatter) – ask an agent in any chat to create one (tool “schedule”) or register a file below. Every run appears as a normal chat; if it needs permission you get a push notification.",
"jobs.intro": "Agents that start on a schedule. Each automation has its instructions in a Markdown file; name, schedule and settings are set here. Create one with “New automation” and work out the instructions with the assistant – or ask an agent in any chat (tool “schedule”). Every run appears as a normal chat.",
"jobs.none": "No automations yet.",
"jobs.schedule": "Schedule",
"jobs.next": "Next run",
@@ -354,13 +354,12 @@ export const en = {
"jobs.enable": "Enable",
"jobs.disable": "Disable",
"jobs.runNow": "Run now",
"jobs.editFile": "Edit file",
"jobs.remove": "Remove",
"jobs.deleteConfirm": "Remove the automation “{name}”? The job file stays.",
"jobs.openRun": "Open run",
"jobs.prompt": "Instructions",
"jobs.register": "Register a job file",
"jobs.registerHint": "Path to a Markdown file with a schedule in its frontmatter:",
"jobs.register": "Register an existing file",
"jobs.registerHint": "Path to a Markdown file with instructions (older files with a schedule in the frontmatter are taken over):",
"jobs.registerBtn": "Register",
"jobs.status.running": "running",
"jobs.status.done": "done",
@@ -508,6 +507,11 @@ export const en = {
"sidebar.unpin": "Unpin",
"sidebar.openBeside": "Open beside",
"chat.closePane": "Close this column",
"sidebar.groupMenu": "Folder options",
"sidebar.groupPin": "Pin to the top",
"sidebar.groupUnpin": "Unpin",
"sidebar.groupUp": "Move up",
"sidebar.groupDown": "Move down",
"sidebar.moveTo": "Move to folder…",
"sidebar.removeFromFolder": "Remove from folder",
"sidebar.archiveOne": "Archive",
@@ -544,14 +548,9 @@ export const en = {
"backup.s3Keep": "Keep in bucket (0 = all)",
"backup.last": "Last backup",
"backup.s3Ok": "uploaded",
"jobs.fromTemplate": "New automation from a template",
"jobs.tplName": "Name",
"jobs.tplProject": "Project folder",
"jobs.tplSchedule": "When",
"jobs.tplCronHint": "Cron: minute hour day month weekday (server time zone).",
"jobs.tplMode": "Mode",
"jobs.tplPrompt": "Task for the agent",
"jobs.tplCreate": "Create automation",
"new.title": "New session",
"new.directory": "Project directory",
"new.up": "Up",
@@ -594,8 +593,52 @@ export const en = {
"chat.compactingDetail": "{tokens} of {limit} tokens ({pct}) – the agent continues with a summary afterwards",
"chat.telegram": "Send questions to Telegram",
"chat.telegramHint": "Also send approvals and questions of this chat via Telegram (the chat currently open in Telegram always reports)",
"cron.label": "Schedule",
"cron.mode.minutes": "Every few minutes",
"cron.mode.hourly": "Hourly",
"cron.mode.daily": "Daily",
"cron.mode.weekly": "On weekdays",
"cron.mode.monthly": "Monthly",
"cron.mode.custom": "Cron expression",
"cron.every": "Every",
"cron.minutes": "minutes",
"cron.atMinute": "At minute",
"cron.days": "Days of the week",
"cron.workdays": "Mon–Fri",
"cron.onDay": "On day",
"cron.at": "at",
"cron.customHint": "Minute hour day month weekday, e.g. “30 6 * * 1-5” = Mon–Fri 06:30.",
"cron.nextRuns": "Next runs:",
"cron.shortMonths": "Months without this day are skipped.",
"cron.serverTz": "Times in server time ({tz})",
"jobEditor.saved": "Saved",
"jobEditor.conflict": "The instructions were changed on disk meanwhile (e.g. by the assistant). Overwrite them with your version?",
"jobEditor.overwrite": "Overwrite",
"jobEditor.runUnsaved": "There are unsaved changes – the run uses the saved version. Start anyway?",
"jobEditor.discard": "Discard the unsaved changes?",
"jobEditor.back": "Back to automations",
"jobEditor.tab.prompt": "Instructions",
"jobEditor.tab.settings": "Schedule",
"jobEditor.tab.assistant": "Assistant",
"jobEditor.timeout": "Time limit (min)",
"jobEditor.bypassHint": "Runs at night: with “Allow everything” the run never waits for approval.",
"jobEditor.instructions": "Instructions",
"jobEditor.instructionsHint": "The agent sees only this text – no chat, nobody to ask.",
"jobEditor.changedOnDisk": "The assistant changed the file while you were editing.",
"jobEditor.reload": "Load its version",
"jobEditor.assistantIntro": "Work out the instructions together with a model: describe what the automation should do – it asks back and writes the file next to you.",
"jobEditor.assistantStart": "Start assistant",
"jobEditor.defaultModel": "Server default",
"jobs.new": "New automation",
"jobs.namePlaceholder": "e.g. Nightly dependency check",
"jobs.fileHint": "The instructions go to .codecraft/jobs/<name>.md in this folder.",
"jobs.startWith": "Start with",
"jobs.blank": "Blank",
"jobs.blankDesc": "Example structure to fill in with the assistant",
"jobs.createAndEdit": "Create and edit",
"jobs.edit": "Edit",
"jobs.permissionMode": "Approval mode",
"jobs.permissionModeHint": "Applies from the next run (written to the file). “Allow everything”: the run never asks and never waits for approval.",
"jobs.permissionModeHint": "Applies from the next run. “Allow everything”: the run never asks and never waits for approval.",
"instructions.title": "Instructions for this chat",
"instructions.hint": "Apply to every message in this chat, in addition to the mode – e.g. language, tone, rules, the part of the project to work on.",
"instructions.placeholder": "e.g. Always answer in English. Only change files under api/. Ask before adding dependencies.",