diff --git a/README.md b/README.md index 151d272..509e303 100644 --- a/README.md +++ b/README.md @@ -240,7 +240,7 @@ redémarrages (volume `/data`). Variables d'environnement du conteneur : | `LOKI_MCP` | `rust` : les serveurs MCP — configuration, catalogue, état, pool de sessions stdio et HTTP — sont tenus par la façade Rust ; le Go lui demande les outils MCP de l'agent et leurs appels ; les tours de la façade appellent son pool directement (expérimental, migration en cours) | Go | | `LOKI_BACKENDS` | `rust` : les backends llama.cpp — statut, vérification git, binaires précompilés, bascule fast/opt, backends custom, GPU vus par un moteur — et le job des moteurs sont tenus par la façade Rust ; les jobs du Go (compilation, moteur de l'image, Strata) lui rapportent leurs étapes (expérimental, migration en cours) | Go | | `LOKI_STRATA` | `rust` (avec `LOKI_BACKENDS=rust`) : l'écran de Strata — machine, ce qui y tient, recommandation, modèles installés —, ses réglages et son installation sont tenus par la façade Rust ; le lancement reste au Go (expérimental, migration en cours) | Go | -| `LOKI_TASKS` | `rust` : les tâches planifiées — liste, enregistrement, bascule, interrupteur maître, lancement, arrêt —, le planificateur et les tâches « script seul » sont tenus par la façade Rust ; une tâche IA reste exécutée par le Go, à la demande de la façade (expérimental, migration en cours) | Go | +| `LOKI_TASKS` | `rust` : les tâches planifiées — liste, enregistrement, bascule, interrupteur maître, lancement, arrêt —, le planificateur et les tâches « script seul » sont tenus par la façade Rust ; les outils task_* de l'agent aussi, dans les tours de la façade ; une tâche IA reste exécutée par le Go, à la demande de la façade (expérimental, migration en cours) | Go | | `LOKI_BENCH` | `rust` : le banc d'essai — lancement, progression, annulation, dernière mesure, mode rapide et mode complet en profondeur — est tenu par la façade Rust ; le verrou de génération reste celui du Go, pris par le bail du moteur (expérimental, migration en cours) | Go | | `LOKI_TUNE` | `rust` : l'optimiseur — lancement, essais, progression, annulation, application dans une copie ou dans le preset, dernier résultat — est tenu par la façade Rust, sous Unix ; le verrou reste le fichier `tune.lock` lu par le Go, les essais des « loki serve » du Go (expérimental, migration en cours) | Go | | `LOKI_ENGINE_IMAGE` | `rust` (avec `LOKI_BACKENDS=rust`) : le panneau « moteur de l'image » — version qui tourne, dernier build publié, version recommandée, mise à jour depuis le registre officiel avec essai à blanc, bascules, retour à la version précédente, vérification du rendu du gabarit — est tenu par la façade Rust (expérimental, migration en cours) | Go | diff --git a/docs/superpowers/specs/2026-10-16-rust-migration-lot37-outils-taches-design.md b/docs/superpowers/specs/2026-10-16-rust-migration-lot37-outils-taches-design.md new file mode 100644 index 0000000..8a207c2 --- /dev/null +++ b/docs/superpowers/specs/2026-10-16-rust-migration-lot37-outils-taches-design.md @@ -0,0 +1,82 @@ +# Lot 37 — Outils task_* de l'agent en Rust + +## Contexte + +Depuis le lot 26, la façade tient les tâches planifiées (`LOKI_TASKS=rust`) : + +- les routes ; +- le planificateur ; +- les tâches « script seul ». + +Les quatre outils par lesquels le modèle gère lui-même ses tâches +(`tasks_tools.go`) restaient au Go, appelés par `/internal/v1/tool/exec` : + +- `task_list` ; +- `task_create` ; +- `task_update` ; +- `task_delete`. + +## Le lot + +`src/tasks/tools.rs` porte les quatre outils, mêmes messages au caractère +près : + +- **`task_list`** : + - liste du projet actif, aperçu d'une ligne par tâche ; + - compte-rendu coupé à 300 octets, un caractère coupé valant U+FFFD par + octet comme à l'encodage JSON du Go ; + - avec un id, la tâche seule et son compte-rendu complet ; + - une tâche d'un autre projet est « introuvable » ; +- **`task_create`** : + - tâche unique « dans N minutes » (durée tronquée comme + `time.Duration(v)`) ou « à HH:MM » (le lendemain si l'heure est passée, + à la même heure murale) ou « à AAAA-MM-JJ HH:MM » ; + - fréquence validée ; + - script vérifié dans le dossier protégé ; + - tâche rattachée au projet actif ; + - fuseau : celui du navigateur, sinon celui de la première tâche qui en a + un ; +- **`task_update`** : modification partielle ; la prochaine exécution est + recalculée sur une nouvelle fréquence, ou à la reprise d'une tâche qui + n'en a pas ; +- **`task_delete`**. + +Un projet disparu vaut le projet par défaut (`taskProjectOf`). + +`GoTurnHost::exec_tool` les exécute quand la façade tient les tâches +(`ChatShared.tasks`, la même base que celle des routes). Sinon l'appel part +au Go comme avant. + +Côté Go, les outils prennent l'heure des tâches (`tasksNow`) au lieu de +`time.Now`. Rien ne change en service ; le journal de parité peut ainsi la +fixer. + +## Parité + +`internal/loki/parity_tasks_tools_test.go` tire du Go un journal de 44 +appels (`tests/parity_tasks/tools.json`). Chaque étape porte : + +- l'heure, le fuseau, le projet actif, les projets connus ; +- les scripts présents ; +- une tâche posée telle quelle en base ; +- les arguments tels que le modèle les envoie ; +- le résultat tel qu'il le reçoit ; +- les tâches en base après coup. + +Le journal couvre : + +- l'heure du trou du changement d'heure ; +- une date passée ou impossible ; +- des arguments d'un autre type ; +- un script absent, hostile ou dossier ; +- le compte-rendu coupé au milieu d'un caractère ; +- le fuseau d'une tâche existante. + +`tests/tasks.rs` (`parite_des_outils`) le rejoue contre le port Rust. + +`tests/lot6.rs` (`outil_task_par_la_facade`) fait tourner un tour de la +façade qui crée une tâche. Il vérifie : + +- rien ne passe par le Go ; +- la tâche est rangée au fuseau de l'utilisateur, dans le projet actif ; +- le résultat est celui que le modèle reçoit. diff --git a/internal/loki/parity_tasks_tools_test.go b/internal/loki/parity_tasks_tools_test.go new file mode 100644 index 0000000..edbc52f --- /dev/null +++ b/internal/loki/parity_tasks_tools_test.go @@ -0,0 +1,244 @@ +package loki + +import ( + "bytes" + "context" + "encoding/json" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" +) + +// parity_tasks_tools_test.go — journal de référence des outils task_* de +// l'agent (lot 37 de la migration Rust) : chaque appel (arguments tels que le +// modèle les envoie) et son résultat, avec les tâches en base après coup. +// L'heure des tâches est fixée pas à pas ; le fuseau de l'utilisateur, le +// projet actif, les projets connus et les scripts du dossier protégé sont +// posés avant l'appel. Rangé dans +// rust/loki-rs/tests/parity_tasks/tools.json ; tests/tasks.rs le rejoue par +// le port Rust. +// +// LOKI_PARITY_UPDATE=1 go test ./internal/loki -run TestPariteOutilsTaches + +const parityTaskToolsFile = "../../rust/loki-rs/tests/parity_tasks/tools.json" + +type parityTaskToolStep struct { + Name string `json:"name"` + Now string `json:"now,omitempty"` // RFC 3339 : l'heure des tâches + State map[string]string `json:"state,omitempty"` + Files map[string]string `json:"files,omitempty"` + PutTask string `json:"put_task,omitempty"` // une tâche écrite telle quelle en base + Tool string `json:"tool"` + Args json.RawMessage `json:"args"` + Out string `json:"out"` + Tasks any `json:"tasks"` +} + +func TestPariteOutilsTaches(t *testing.T) { + home := testHome(t) + oldNow := tasksNow + var now time.Time + tasksNow = func() time.Time { return now } + t.Cleanup(func() { tasksNow = oldNow }) + activeProjMu.Lock() + activeProjCache = "" + activeProjMu.Unlock() + t.Cleanup(func() { + activeProjMu.Lock() + activeProjCache = "" + activeProjMu.Unlock() + }) + + // Les identifiants tirés au hasard deviennent {{ID1}}, {{ID2}}… dans + // l'ordre où ils apparaissent. + ids := map[string]string{} + var order []string + mask := func(s string) string { + return parityTaskIDRe.ReplaceAllStringFunc(s, func(id string) string { + if _, ok := ids[id]; !ok { + order = append(order, id) + ids[id] = "{{ID" + strconv.Itoa(len(order)) + "}}" + } + return ids[id] + }) + } + unmask := func(s string) string { + for id, m := range ids { + s = strings.ReplaceAll(s, m, id) + } + return s + } + snapshot := func() any { + b, _ := json.Marshal(listTasks()) + var v any + _ = json.Unmarshal([]byte(mask(string(b))), &v) + return v + } + + var steps []parityTaskToolStep + run := func(st parityTaskToolStep) { + if st.Now != "" { + n, err := time.Parse(time.RFC3339, st.Now) + if err != nil { + t.Fatal(err) + } + now = n + } + parityApplyFiles(t, home, st.Files) + for k, v := range st.State { + if err := putStr(bkState, k, v); err != nil { + t.Fatal(err) + } + if k == stActiveProjectKey { + activeProjMu.Lock() + activeProjCache = v + activeProjMu.Unlock() + } + } + if st.PutTask != "" { + raw := unmask(st.PutTask) + var tk Task + if err := json.Unmarshal([]byte(raw), &tk); err != nil { + t.Fatal(err) + } + if err := putBytes(bkTasks, tk.ID, []byte(raw)); err != nil { + t.Fatal(err) + } + mask(raw) + } + var args map[string]any + dec := json.NewDecoder(bytes.NewReader([]byte(unmask(string(st.Args))))) + if err := dec.Decode(&args); err != nil { + t.Fatalf("%s : arguments illisibles : %v", st.Name, err) + } + if args == nil { + args = map[string]any{} + } + res := execTool(context.Background(), st.Tool, args, toolCallLabel(st.Tool, args), Caps{Agent: true}) + // Le résultat tel que le modèle le reçoit : encodé en JSON (octets + // orphelins d'une coupe → U+FFFD). + b, _ := json.Marshal(res.Result) + var out string + _ = json.Unmarshal(b, &out) + st.Out = mask(out) + st.Tasks = snapshot() + steps = append(steps, st) + } + args := func(s string) json.RawMessage { return json.RawMessage(s) } + // Un compte-rendu dont la coupe à 300 octets tombe au milieu d'un « é ». + longReport := strings.Repeat("a", 299) + "é et la suite\n sur plusieurs lignes" + + run(parityTaskToolStep{Name: "liste vide", Now: "2026-03-28T12:00:00Z", + State: map[string]string{stUserTZKey: "Europe/Paris"}, + Tool: "task_list", Args: args(`{}`)}) + run(parityTaskToolStep{Name: "dans 30 minutes", Tool: "task_create", + Args: args(`{"name":"Rappel","prompt":"Bois de l'eau","in_minutes":30}`)}) + run(parityTaskToolStep{Name: "dans 1,9 minute : une seule", Tool: "task_create", + Args: args(`{"name":"Bref","prompt":"x","in_minutes":1.9}`)}) + run(parityTaskToolStep{Name: "à une heure passée : demain", Tool: "task_create", + Args: args(`{"name":"Matin","prompt":"Café","at":"08:15"}`)}) + run(parityTaskToolStep{Name: "à une heure à venir : aujourd'hui", Tool: "task_create", + Args: args(`{"name":"Soir","prompt":"Bilan","at":" 21:05 "}`)}) + run(parityTaskToolStep{Name: "à une date, dans le trou du changement d'heure", Tool: "task_create", + Args: args(`{"name":"Nuit","prompt":"x","at":"2026-03-29 02:30"}`)}) + run(parityTaskToolStep{Name: "à une date passée", Tool: "task_create", + Args: args(`{"name":"Hier","prompt":"x","at":"2026-03-27 10:00"}`)}) + run(parityTaskToolStep{Name: "at illisible", Tool: "task_create", + Args: args(`{"name":"X","prompt":"x","at":"25:00"}`)}) + run(parityTaskToolStep{Name: "at : date impossible", Tool: "task_create", + Args: args(`{"name":"X","prompt":"x","at":"2026-02-30 10:00"}`)}) + run(parityTaskToolStep{Name: "intervalle", Tool: "task_create", + Args: args(`{"name":"Veille","prompt":"Regarde les nouvelles","schedule":"@every 2h"}`)}) + run(parityTaskToolStep{Name: "cron, désactivée", Tool: "task_create", + Args: args(`{"name":"Semaine","prompt":"Point","schedule":"0 9 * * 1-5","enabled":false}`)}) + run(parityTaskToolStep{Name: "quotidienne ancrée", Tool: "task_create", + Args: args(`{"name":"Journal","prompt":"Écris","schedule":"@every 1d@09:00","in_minutes":5}`)}) + run(parityTaskToolStep{Name: "fréquence invalide", Tool: "task_create", + Args: args(`{"name":"X","prompt":"x","schedule":"@every 30s"}`)}) + run(parityTaskToolStep{Name: "sans nom", Tool: "task_create", + Args: args(`{"prompt":"x","in_minutes":5}`)}) + run(parityTaskToolStep{Name: "nom d'un autre type", Tool: "task_create", + Args: args(`{"name":42,"prompt":"x","in_minutes":5}`)}) + run(parityTaskToolStep{Name: "moins d'une minute : pas de fréquence", Tool: "task_create", + Args: args(`{"name":"X","prompt":"x","in_minutes":0.5}`)}) + run(parityTaskToolStep{Name: "ni prompt ni script", Tool: "task_create", + Args: args(`{"name":"X","in_minutes":5}`)}) + run(parityTaskToolStep{Name: "script absent", Tool: "task_create", + Args: args(`{"name":"Ménage","script":"menage.sh","schedule":"@every 1d"}`)}) + run(parityTaskToolStep{Name: "script hostile", Tool: "task_create", + Args: args(`{"name":"Ménage","script":"a;b.sh","schedule":"@every 1d"}`)}) + run(parityTaskToolStep{Name: "script dossier", Files: map[string]string{"scripts/outils/x": "#!/bin/sh\n"}, + Tool: "task_create", Args: args(`{"name":"Ménage","script":"outils","schedule":"@every 1d"}`)}) + run(parityTaskToolStep{Name: "script présent", Files: map[string]string{"scripts/menage.sh": "#!/bin/sh\necho ok\n"}, + Tool: "task_create", Args: args(`{"name":"Ménage","script":" menage.sh ","prompt":"ignoré ?","schedule":"@every 1d","enabled":"false"}`)}) + + // Les projets : une tâche d'un autre projet est invisible ; un projet + // disparu vaut le projet par défaut. + projects := `[{"slug":"generale","name":"Générale","created_at":1},{"slug":"autre","name":"Autre","created_at":2}]` + run(parityTaskToolStep{Name: "tâche d'un autre projet", State: map[string]string{stProjectsKey: projects}, + PutTask: `{"id":"aaaaaaaaaaaa","name":"Autre","prompt":"x","schedule":"@every 1h","tz":"Europe/Paris","preset":"","project":"autre","no_mem":false,"no_web":false,"enabled":true,"last_run":0,"next_run":1774699200000,"last_dur_ms":0,"last_ok":false,"last_error":"","last_report":""}`, + Tool: "task_list", Args: args(`{"id":"aaaaaaaaaaaa"}`)}) + run(parityTaskToolStep{Name: "tâche d'un projet disparu", + PutTask: `{"id":"bbbbbbbbbbbb","name":"Antique (fantôme)","prompt":"x","schedule":"@every 1h","tz":"America/New_York","preset":"","project":"fantome","no_mem":false,"no_web":false,"enabled":true,"last_run":1774692000000,"next_run":1774699200000,"last_dur_ms":1200,"last_ok":false,"last_error":"moteur occupé","last_report":""}`, + Tool: "task_list", Args: args(`{"id":"bbbbbbbbbbbb"}`)}) + rb, _ := json.Marshal(longReport) + report := string(rb) + run(parityTaskToolStep{Name: "compte-rendu long", + PutTask: `{"id":"cccccccccccc","name":"Rapport","prompt":"x","schedule":"@every 1d","tz":"Europe/Paris","preset":"","no_mem":false,"no_web":false,"enabled":false,"last_run":1774692000000,"next_run":1774699200000,"last_dur_ms":5000,"last_ok":true,"last_error":"","last_report":` + report + `}`, + Tool: "task_list", Args: args(`{}`)}) + run(parityTaskToolStep{Name: "compte-rendu complet", Tool: "task_list", Args: args(`{"id":" cccccccccccc "}`)}) + run(parityTaskToolStep{Name: "liste d'un autre projet", State: map[string]string{stActiveProjectKey: "autre"}, + Tool: "task_list", Args: args(`{}`)}) + run(parityTaskToolStep{Name: "création dans le projet actif", Tool: "task_create", + Args: args(`{"name":"Ici","prompt":"x","schedule":"@every 3h"}`)}) + run(parityTaskToolStep{Name: "retour au projet par défaut", State: map[string]string{stActiveProjectKey: "generale"}, + Tool: "task_update", Args: args(`{"id":"aaaaaaaaaaaa","name":"Volée"}`)}) + + // Les modifications. + run(parityTaskToolStep{Name: "modifier sans id", Now: "2026-03-28T15:00:00Z", Tool: "task_update", Args: args(`{"name":"x"}`)}) + run(parityTaskToolStep{Name: "modifier un id inconnu", Tool: "task_update", Args: args(`{"id":"ffffffffffff"}`)}) + run(parityTaskToolStep{Name: "renommer, nouvelle fréquence", Tool: "task_update", + Args: args(`{"id":"{{ID1}}","name":" Eau ","prompt":" ","schedule":" @every 45m "}`)}) + run(parityTaskToolStep{Name: "mettre en pause", Tool: "task_update", Args: args(`{"id":"{{ID1}}","enabled":false}`)}) + run(parityTaskToolStep{Name: "fréquence refusée", Tool: "task_update", Args: args(`{"id":"{{ID1}}","schedule":"jamais"}`)}) + run(parityTaskToolStep{Name: "reprendre une tâche sans prochaine exécution", + PutTask: `{"id":"dddddddddddd","name":"Dormante","prompt":"x","schedule":"0 8 * * *","tz":"Europe/Paris","preset":"","no_mem":false,"no_web":false,"enabled":false,"last_run":0,"next_run":0,"last_dur_ms":0,"last_ok":false,"last_error":"","last_report":""}`, + Tool: "task_update", Args: args(`{"id":"dddddddddddd","enabled":true,"prompt":"Réveil"}`)}) + run(parityTaskToolStep{Name: "liste après modifications", Tool: "task_list", Args: args(`{}`)}) + + // Les suppressions. + run(parityTaskToolStep{Name: "supprimer sans id", Tool: "task_delete", Args: args(`{"id":" "}`)}) + run(parityTaskToolStep{Name: "supprimer d'un autre projet", Tool: "task_delete", Args: args(`{"id":"aaaaaaaaaaaa"}`)}) + run(parityTaskToolStep{Name: "supprimer", Tool: "task_delete", Args: args(`{"id":"{{ID1}}"}`)}) + run(parityTaskToolStep{Name: "supprimer deux fois", Tool: "task_delete", Args: args(`{"id":"{{ID1}}"}`)}) + + // Sans fuseau du navigateur : celui de la première tâche qui en a un. + run(parityTaskToolStep{Name: "fuseau d'une tâche existante", State: map[string]string{stUserTZKey: ""}, + Tool: "task_create", Args: args(`{"name":"Ailleurs","prompt":"x","at":"23:30"}`)}) + + got, err := json.MarshalIndent(steps, "", " ") + if err != nil { + t.Fatal(err) + } + got = append(got, '\n') + if os.Getenv("LOKI_PARITY_UPDATE") == "1" { + if err := os.MkdirAll(filepath.Dir(parityTaskToolsFile), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(parityTaskToolsFile, got, 0o644); err != nil { + t.Fatal(err) + } + return + } + want, err := os.ReadFile(parityTaskToolsFile) + if err != nil { + t.Fatalf("journal de référence absent (%v) : LOKI_PARITY_UPDATE=1 pour le créer", err) + } + if !bytes.Equal(got, want) { + t.Errorf("les outils task_* ne produisent plus le journal rangé dans %s.\n"+ + "LOKI_PARITY_UPDATE=1 pour le régénérer si le changement est voulu.", parityTaskToolsFile) + } +} diff --git a/internal/loki/tasks_tools.go b/internal/loki/tasks_tools.go index f6e98e0..35e6fa0 100644 --- a/internal/loki/tasks_tools.go +++ b/internal/loki/tasks_tools.go @@ -7,6 +7,11 @@ package loki // saveTask), donc une tâche créée par l'IA apparaît et se pilote comme les // autres dans le panneau Tâches. // +// Port Rust (lot 37) : rust/loki-rs/src/tasks/tools.rs, employé par les tours +// de la façade quand elle tient les tâches (LOKI_TASKS=rust) ; journal de +// parité dans parity_tasks_tools_test.go. L'heure est celle des tâches +// (tasksNow), fixée par ce journal. +// // Gate : réservés au mode agent (EnabledTools). Une tâche n'a de sens que si // l'IA peut agir en arrière-plan ; sans agent elle n'aurait aucun outil pour // livrer son résultat. @@ -215,7 +220,7 @@ func toolTaskCreate(args map[string]any) string { // fuseau de l'utilisateur (AJEAN 0.17.5). Le modèle n'a plus à jongler avec // les fuseaux ni le cron pour un simple rappel. if schedule == "" { - now := time.Now().In(loc(tz)) + now := tasksNow().In(loc(tz)) if v, ok := args["in_minutes"].(float64); ok && v >= 1 { schedule = "@once " + now.Add(time.Duration(v)*time.Minute).Format("2006-01-02 15:04") } else if at := strings.TrimSpace(taskStrArg(args["at"])); at != "" { @@ -259,7 +264,7 @@ func toolTaskCreate(args map[string]any) string { // comme elle n'y voit et n'y pilote que ses propres tâches. Project: activeProjectSlug(), } - t.NextRun = computeNextRun(schedule, tz, time.Now()) + t.NextRun = computeNextRun(schedule, tz, tasksNow()) if err := saveTask(t); err != nil { return "[erreur] " + err.Error() } @@ -292,12 +297,12 @@ func toolTaskUpdate(args map[string]any) string { return "[erreur] fréquence invalide : " + err.Error() } t.Schedule = sched - t.NextRun = computeNextRun(sched, t.TZ, time.Now()) + t.NextRun = computeNextRun(sched, t.TZ, tasksNow()) } if v, ok := args["enabled"].(bool); ok { t.Enabled = v if v && t.NextRun == 0 { - t.NextRun = computeNextRun(t.Schedule, t.TZ, time.Now()) + t.NextRun = computeNextRun(t.Schedule, t.TZ, tasksNow()) } } if err := saveTask(t); err != nil { diff --git a/rust/loki-rs/src/chat/generate.rs b/rust/loki-rs/src/chat/generate.rs index d449e9e..3a2cda6 100644 --- a/rust/loki-rs/src/chat/generate.rs +++ b/rust/loki-rs/src/chat/generate.rs @@ -1304,6 +1304,7 @@ impl ChatShared { tpl: std::sync::Arc::new(super::tplprobe::TplProbe::new()), prewarm: Default::default(), mcp: None, + tasks: None, go_version: Default::default(), } } diff --git a/rust/loki-rs/src/chat/host.rs b/rust/loki-rs/src/chat/host.rs index 5b082a1..4cd1fb0 100644 --- a/rust/loki-rs/src/chat/host.rs +++ b/rust/loki-rs/src/chat/host.rs @@ -4,7 +4,8 @@ //! classées et formulées comme `friendlyLLMError` ; //! - outils fichiers et shell exécutés ici ([`crate::tools`], état partagé //! tenu par le Go), outils MCP par le pool de la façade quand elle le tient -//! (lot 36) ; les autres par le Go (`/internal/v1/tool/exec`), avec +//! (lot 36), outils task_* quand elle tient les tâches (lot 37) ; les autres +//! par le Go (`/internal/v1/tool/exec`), avec //! ce qu'il tire du résultat (capture de la bulle, aperçu du navigateur, //! image relayée) ; //! - résultats complets (« voir plus ») confiés à l'écrivain des discussions ; @@ -334,6 +335,9 @@ pub struct ChatShared { /// Le pool MCP, quand la façade le tient (LOKI_MCP=rust) : les appels /// `mcp__*` du tour y vont directement (lot 36). pub mcp: Option>, + /// Les tâches, quand la façade les tient (LOKI_TASKS=rust) : les outils + /// `task_*` du tour s'exécutent ici (lot 37). + pub tasks: Option>, /// La version du Go, annoncée aux serveurs MCP à une reconnexion ; lue /// une fois. pub go_version: tokio::sync::OnceCell, @@ -645,6 +649,23 @@ impl TurnHost for GoTurnHost { // Outils MCP, quand la façade tient le pool : ce que ferait le Go // (`mcpCall` → /internal/facade/v1/mcp/call), sans ses deux // allers-retours. Le Go n'en tire rien d'autre que le texte. + // Outils task_*, quand la façade tient les tâches (lot 37). + if crate::tasks::tools::is_tool(name) + && let Some(tasks) = &self.shared.tasks + { + let dir = tasks.scripts_dir(); + let env = crate::tasks::tools::ToolEnv { + store: &self.shared.store, + scripts_dir: &dir, + now_ns: tasks.now(), + }; + if let Some(result) = crate::tasks::tools::exec(&env, name, args).await { + return ToolOutcome { + result, + ..Default::default() + }; + } + } if crate::mcp::config::is_mcp_tool(name) && let Some(mcp) = &self.shared.mcp { diff --git a/rust/loki-rs/src/main.rs b/rust/loki-rs/src/main.rs index a9bbe2f..049cac5 100644 --- a/rust/loki-rs/src/main.rs +++ b/rust/loki-rs/src/main.rs @@ -262,11 +262,15 @@ fn serve() -> ExitCode { return ExitCode::FAILURE; } }; - // Un seul pool MCP : celui des routes, et celui des tours de la façade. + // Un seul pool MCP, une seule base de tâches : ceux des routes, et ceux + // des tours de la façade (outils mcp__* et task_*). let mcp = mcp_rust .then(|| std::sync::Arc::new(loki_rs::mcp::Mcp::new(engine_paths.home.clone()))); + let tasks = tasks_rust + .then(|| std::sync::Arc::new(loki_rs::tasks::Tasks::new(engine_paths.home.clone()))); let chat = if chat_rust { - match start_chat(backend, &token, &engine_paths.home, mcp.clone()).await { + let held = (mcp.clone(), tasks.clone()); + match start_chat(backend, &token, &engine_paths.home, held).await { Ok(c) => Some(c), Err(e) => { eprintln!("[loki-rs] conversation : {e}"); @@ -368,8 +372,6 @@ fn serve() -> ExitCode { loki_rs::backends::probe::Probe::system(), )) }); - let tasks = tasks_rust - .then(|| std::sync::Arc::new(loki_rs::tasks::Tasks::new(engine_paths.home.clone()))); let bench = bench_rust .then(|| std::sync::Arc::new(loki_rs::bench::job::Bench::new(engine_paths.clone()))); let tune = tune_rust.then(|| { @@ -512,7 +514,10 @@ async fn start_chat( backend: SocketAddr, token: &str, home: &std::path::Path, - mcp: Option>, + (mcp, tasks): ( + Option>, + Option>, + ), ) -> Result, String> { use loki_rs::chat::{conv::Conversation, generate::ChatService, host::ChatShared, sessions}; let store = loki_rs::store::Store::new(backend, token.to_string()); @@ -525,6 +530,7 @@ async fn start_chat( let mut shared = ChatShared::for_sessions(&s, store.clone(), home.join("chatimg")); shared.patterns = loki_rs::chat::generate::retry_patterns(&store).await; shared.mcp = mcp; + shared.tasks = tasks; eprintln!("[loki-rs] conversation tenue par la façade (LOKI_CHAT=go pour la rendre au Go)"); Ok(ChatService::new( std::sync::Arc::new(s), diff --git a/rust/loki-rs/src/tasks/cron.rs b/rust/loki-rs/src/tasks/cron.rs index c315fa8..41795f2 100644 --- a/rust/loki-rs/src/tasks/cron.rs +++ b/rust/loki-rs/src/tasks/cron.rs @@ -86,7 +86,7 @@ pub fn next_after(schedule: &str, tz: &str, from: i64) -> Result { /// `time.ParseInLocation("2006-01-02 15:04", s, l)` : l'instant (ns), ou /// rien si la chaîne ne suit pas la forme. -fn parse_ymd_hm(s: &str, l: &Location) -> Option { +pub fn parse_ymd_hm(s: &str, l: &Location) -> Option { let b = s.as_bytes(); let digits = |r: &[u8]| r.iter().all(u8::is_ascii_digit); // 2006 : 4 chiffres ; -01 et -02 : 2 chiffres ; 15 : 1 ou 2 ; :04 : 2. @@ -176,7 +176,7 @@ fn next_every(spec: &str, tz: &str, from: i128) -> Result { } /// `parseHHMM`. -fn parse_hhmm(s: &str) -> Result<(i64, i64), String> { +pub fn parse_hhmm(s: &str) -> Result<(i64, i64), String> { let Some((hs, ms)) = s.trim().split_once(':') else { return Err(format!("heure invalide (attendu HH:MM) : {}", quote(s))); }; diff --git a/rust/loki-rs/src/tasks/mod.rs b/rust/loki-rs/src/tasks/mod.rs index 95bd017..3632e19 100644 --- a/rust/loki-rs/src/tasks/mod.rs +++ b/rust/loki-rs/src/tasks/mod.rs @@ -13,6 +13,7 @@ //! planificateur. pub mod cron; +pub mod tools; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; diff --git a/rust/loki-rs/src/tasks/tools.rs b/rust/loki-rs/src/tasks/tools.rs new file mode 100644 index 0000000..01d7ca1 --- /dev/null +++ b/rust/loki-rs/src/tasks/tools.rs @@ -0,0 +1,337 @@ +//! Les outils `task_*` de l'agent (lot 37) — port de `tasks_tools.go` : +//! le modèle gère lui-même ses tâches planifiées (rappel, veille, ménage +//! périodique), les liste, les ajuste, les supprime. Mêmes règles que le +//! panneau Tâches : fréquence validée, prochaine exécution calculée dans le +//! fuseau de l'utilisateur, tâche rattachée au projet actif — l'IA ne voit +//! et ne pilote que celles de son projet. +//! +//! La façade les exécute quand elle tient les tâches (`LOKI_TASKS=rust`) ; +//! sinon l'appel part au Go. + +use std::path::Path; + +use serde_json::{Map, Value}; + +use super::cron::{compute_next_run, loc, next_after, parse_hhmm, parse_ymd_hm}; +use super::{BK_TASKS, Task, get_task, list_tasks, new_task_id, save_task, script_exists}; +use crate::paths::DEFAULT_PROJECT_SLUG; +use crate::store::{BK_STATE, Store}; +use crate::tz::Location; + +const NS: i64 = 1_000_000_000; +const MINUTE: i64 = 60 * NS; + +/// `stUserTZKey` : fuseau IANA du navigateur de l'utilisateur. +pub const ST_USER_TZ: &str = "user_tz"; + +/// Les outils portés ici. +pub fn is_tool(name: &str) -> bool { + matches!( + name, + "task_list" | "task_create" | "task_update" | "task_delete" + ) +} + +/// Ce qu'il faut pour exécuter un outil : la base, le dossier protégé des +/// scripts et l'heure des tâches (ns Unix). +pub struct ToolEnv<'a> { + pub store: &'a Store, + pub scripts_dir: &'a Path, + pub now_ns: i64, +} + +/// Un appel d'outil `task_*` ; `None` pour un autre outil. +pub async fn exec(env: &ToolEnv<'_>, name: &str, args: &Map) -> Option { + Some(match name { + "task_list" => task_list(env, args).await, + "task_create" => task_create(env, args).await, + "task_update" => task_update(env, args).await, + "task_delete" => task_delete(env, args).await, + _ => return None, + }) +} + +/// `strings.TrimSpace`. +fn go_trim(s: &str) -> &str { + s.trim_matches(char::is_whitespace) +} + +/// `taskStrArg` : une chaîne, `""` si absente ou d'un autre type. +fn str_arg<'a>(args: &'a Map, k: &str) -> &'a str { + args.get(k).and_then(Value::as_str).unwrap_or("") +} + +/// `Format("2006-01-02 15:04")` d'un instant en ms Unix, dans `l`. +fn fmt_ms(ms: i64, l: &Location) -> String { + l.civil(ms.div_euclid(1000)).ymd_hm() +} + +/// `activeProjectSlug` et `taskProjectOf`, lus une fois par appel. +struct Projects { + active: String, + known: Vec, +} + +impl Projects { + async fn load(store: &Store) -> Self { + Projects { + active: crate::memory::active_project(store).await, + known: crate::memory::list_projects(store) + .await + .into_iter() + .map(|p| p.slug) + .collect(), + } + } + + /// `taskProjectOf` : le projet d'une tâche, absent ou inconnu → le + /// projet par défaut. + fn of(&self, t: &Task) -> String { + let s = go_trim(&t.project); + if !s.is_empty() && self.known.iter().any(|k| k == s) { + return s.to_string(); + } + DEFAULT_PROJECT_SLUG.to_string() + } +} + +/// `defaultTaskTZ` : le fuseau du navigateur s'il est connu, sinon celui +/// d'une tâche existante, sinon vide (heure locale du serveur). +async fn default_task_tz(store: &Store) -> String { + let tz = store.get_str(BK_STATE, ST_USER_TZ).await; + if !tz.is_empty() { + return tz; + } + list_tasks(store) + .await + .into_iter() + .find(|t| !go_trim(&t.tz).is_empty()) + .map(|t| t.tz) + .unwrap_or_default() +} + +/// `tzLabel`. +fn tz_label(tz: &str) -> &str { + if tz.is_empty() { + "heure du serveur" + } else { + tz + } +} + +/// `toolTaskList` : avec un id, cette tâche seule et son compte-rendu +/// complet ; sinon la liste du projet, un aperçu court par tâche. +async fn task_list(env: &ToolEnv<'_>, args: &Map) -> String { + let projects = Projects::load(env.store).await; + let id = go_trim(str_arg(args, "id")); + if !id.is_empty() { + return match get_task(env.store, id).await { + Some(t) if projects.of(&t) == projects.active => format_task(&t, true), + _ => format!("[erreur] tâche introuvable : {id}"), + }; + } + let tasks: Vec = list_tasks(env.store) + .await + .into_iter() + .filter(|t| projects.of(t) == projects.active) + .collect(); + if tasks.is_empty() { + return "[aucune tâche planifiée dans ce projet]".into(); + } + let mut b = String::new(); + for t in &tasks { + b.push_str(&format_task(t, false)); + b.push('\n'); + } + b.trim_end_matches('\n').to_string() +} + +/// `formatTask` : `full`, le compte-rendu entier ; sinon un aperçu d'une +/// ligne. +pub fn format_task(t: &Task, full: bool) -> String { + let state = if t.enabled { "on" } else { "off" }; + let mut b = format!("- {} [{state}] « {} » — {}", t.id, t.name, t.schedule); + let l = loc(&t.tz); + if t.next_run > 0 && t.enabled { + b.push_str(&format!(" (prochaine : {})", fmt_ms(t.next_run, &l))); + } + if t.last_run > 0 { + let when = fmt_ms(t.last_run, &l); + if t.last_ok { + b.push_str(&format!(" ✓ dernier run {when}")); + } else { + b.push_str(&format!(" ✗ dernier run {when} : {}", t.last_error)); + } + let r = go_trim(&t.last_report); + if !r.is_empty() { + if full { + b.push_str("\n compte-rendu complet :\n"); + b.push_str(r); + } else { + b.push_str("\n compte-rendu : "); + b.push_str(&preview_report(r)); + } + } + } + b +} + +/// `previewReport` : aplati, coupé à 300 octets (un caractère coupé devient +/// U+FFFD par octet, comme à l'encodage JSON du Go). +pub fn preview_report(s: &str) -> String { + let s = s.split_whitespace().collect::>().join(" "); + const MAX: usize = 300; + if s.len() > MAX { + return format!( + "{} […] (id pour le compte-rendu complet)", + crate::system::go_lossy(&s.as_bytes()[..MAX]) + ); + } + s +} + +/// `toolTaskCreate`. +async fn task_create(env: &ToolEnv<'_>, args: &Map) -> String { + let name = go_trim(str_arg(args, "name")); + let prompt = go_trim(str_arg(args, "prompt")); + let script = go_trim(str_arg(args, "script")); + let mut schedule = go_trim(str_arg(args, "schedule")).to_string(); + let tz = default_task_tz(env.store).await; + // Tâche unique : « dans N minutes » ou « à HH:MM », calculés ici dans le + // fuseau de l'utilisateur. + if schedule.is_empty() { + let l = loc(&tz); + let at = go_trim(str_arg(args, "at")); + if let Some(v) = args + .get("in_minutes") + .and_then(Value::as_f64) + .filter(|v| *v >= 1.0) + { + // time.Duration(v) * time.Minute : tronqué vers zéro. + let t = env + .now_ns + .wrapping_add((v as i64).wrapping_mul(MINUTE)) + .div_euclid(NS); + schedule = format!("@once {}", l.civil(t).ymd_hm()); + } else if !at.is_empty() { + if let Some(t) = parse_ymd_hm(at, &l) { + let sec = t.div_euclid(i128::from(NS)) as i64; + schedule = format!("@once {}", l.civil(sec).ymd_hm()); + } else if let Ok((hh, mm)) = parse_hhmm(at) { + let now = l.civil(env.now_ns.div_euclid(NS)); + let mut t = l.date(now.year, now.month, now.day, hh, mm, 0); + if i128::from(t) * i128::from(NS) <= i128::from(env.now_ns) { + // AddDate(0, 0, 1) : le lendemain, à la même heure murale. + let c = l.civil(t); + t = l.date(c.year, c.month, c.day + 1, c.hour, c.minute, c.second); + } + schedule = format!("@once {}", l.civil(t).ymd_hm()); + } else { + return "[erreur] 'at' invalide : « HH:MM » ou « AAAA-MM-JJ HH:MM »".into(); + } + } + } + if name.is_empty() || schedule.is_empty() { + return "[erreur] name obligatoire, et schedule (tâche répétée) ou in_minutes / at (tâche unique)".into(); + } + let mut kind = ""; + if !script.is_empty() { + // Tâche script : le script doit exister dans le dossier protégé. + kind = "script"; + if let Err(e) = script_exists(env.scripts_dir, script) { + return format!("[erreur] {e}"); + } + } else if prompt.is_empty() { + return "[erreur] fournis soit 'prompt' (tâche IA) soit 'script' (tâche script)".into(); + } + if let Err(e) = next_after(&schedule, &tz, env.now_ns) { + return format!("[erreur] fréquence invalide : {e}"); + } + let enabled = args.get("enabled").and_then(Value::as_bool).unwrap_or(true); + let mut t = Task { + id: new_task_id(), + name: name.to_string(), + prompt: prompt.to_string(), + schedule: schedule.clone(), + tz: tz.clone(), + enabled, + kind: kind.to_string(), + script: script.to_string(), + // L'IA ne crée que DANS son projet. + project: crate::memory::active_project(env.store).await, + ..Default::default() + }; + t.next_run = compute_next_run(&schedule, &tz, env.now_ns); + if let Err(e) = save_task(env.store, &t).await { + return format!("[erreur] {e}"); + } + let when = if t.next_run > 0 && enabled { + format!( + ", prochaine exécution {} ({})", + fmt_ms(t.next_run, &loc(&tz)), + tz_label(&tz) + ) + } else { + String::new() + }; + format!("[ok] tâche '{name}' créée (id {}){when}", t.id) +} + +/// `toolTaskUpdate` : modification partielle. +async fn task_update(env: &ToolEnv<'_>, args: &Map) -> String { + let id = go_trim(str_arg(args, "id")); + if id.is_empty() { + return "[erreur] id manquant".into(); + } + let projects = Projects::load(env.store).await; + let mut t = match get_task(env.store, id).await { + Some(t) if projects.of(&t) == projects.active => t, + _ => return format!("[erreur] tâche introuvable : {id}"), + }; + let text = |k: &str| { + args.get(k) + .and_then(Value::as_str) + .map(go_trim) + .filter(|v| !v.is_empty()) + }; + if let Some(v) = text("name") { + t.name = v.to_string(); + } + if let Some(v) = text("prompt") { + t.prompt = v.to_string(); + } + if let Some(sched) = text("schedule") { + if let Err(e) = next_after(sched, &t.tz, env.now_ns) { + return format!("[erreur] fréquence invalide : {e}"); + } + t.schedule = sched.to_string(); + t.next_run = compute_next_run(sched, &t.tz, env.now_ns); + } + if let Some(v) = args.get("enabled").and_then(Value::as_bool) { + t.enabled = v; + if v && t.next_run == 0 { + t.next_run = compute_next_run(&t.schedule, &t.tz, env.now_ns); + } + } + if let Err(e) = save_task(env.store, &t).await { + return format!("[erreur] {e}"); + } + format!("[ok] tâche '{}' (id {}) mise à jour", t.name, t.id) +} + +/// `toolTaskDelete`. +async fn task_delete(env: &ToolEnv<'_>, args: &Map) -> String { + let id = go_trim(str_arg(args, "id")); + if id.is_empty() { + return "[erreur] id manquant".into(); + } + let projects = Projects::load(env.store).await; + let t = match get_task(env.store, id).await { + Some(t) if projects.of(&t) == projects.active => t, + _ => return format!("[erreur] tâche introuvable : {id}"), + }; + if let Err(e) = env.store.del(BK_TASKS, id).await { + return format!("[erreur] {e}"); + } + format!("[ok] tâche '{}' (id {id}) supprimée", t.name) +} diff --git a/rust/loki-rs/tests/common/fakego.rs b/rust/loki-rs/tests/common/fakego.rs index 7cacc4d..9dbcf60 100644 --- a/rust/loki-rs/tests/common/fakego.rs +++ b/rust/loki-rs/tests/common/fakego.rs @@ -1007,6 +1007,7 @@ pub async fn start_with( let mut shared = ChatShared::for_sessions(&s, store.clone(), home.join("chatimg")); shared.patterns = loki_rs::chat::generate::retry_patterns(&store).await; shared.mcp = opts.mcp.clone(); + shared.tasks = opts.tasks.clone(); Some(ChatService::new(Arc::new(s), Arc::new(shared))) } else { None diff --git a/rust/loki-rs/tests/lot6.rs b/rust/loki-rs/tests/lot6.rs index 4414264..c5a008f 100644 --- a/rust/loki-rs/tests/lot6.rs +++ b/rust/loki-rs/tests/lot6.rs @@ -668,6 +668,7 @@ async fn tour_complet_par_le_go() { tpl: Arc::new(loki_rs::chat::tplprobe::TplProbe::new()), prewarm: Default::default(), mcp: None, + tasks: None, go_version: Default::default(), }); let cfg = std::collections::HashMap::new(); @@ -851,13 +852,13 @@ async fn service( tokio::sync::oneshot::Sender<()>, tempfile::TempDir, ) { - service_with(engine_url, None).await + service_with(engine_url, |_| {}).await } -/// [`service`], avec le pool MCP de la façade. +/// [`service`], l'état partagé réglé par `f` (pool MCP, tâches…). async fn service_with( engine_url: Option<&str>, - mcp: Option>, + f: impl FnOnce(&mut ChatShared), ) -> ( Arc, Arc, @@ -874,7 +875,7 @@ async fn service_with( let sessions = Sessions::new(st.clone(), Conversation::new(), GoSessionHooks(st.clone())); sessions.load().await.unwrap(); let mut shared = ChatShared::for_sessions(&sessions, st, t.path().join("chatimg")); - shared.mcp = mcp; + f(&mut shared); ( ChatService::new(Arc::new(sessions), Arc::new(shared)), go, @@ -2443,7 +2444,7 @@ done std::fs::set_permissions(&bin, std::fs::Permissions::from_mode(0o755)).unwrap(); let trace = dir.path().join("trace"); let pool = Arc::new(loki_rs::mcp::Mcp::new(dir.path().to_path_buf())); - let (svc, go, _stop, _t) = service_with(Some(&url), Some(pool.clone())).await; + let (svc, go, _stop, _t) = service_with(Some(&url), |s| s.mcp = Some(pool.clone())).await; let mut servers = loki_rs::mcp::config::Servers::new(); servers.insert( "sh".into(), @@ -2493,3 +2494,60 @@ done assert!(inits[1].contains(r#""version":"0.15.0""#), "{inits:?}"); pool.close_all().await; } + +/// Lot 37 : un outil task_* appelé par un tour de la façade s'exécute ici +/// quand elle tient les tâches — la tâche rangée dans le projet actif, au +/// fuseau de l'utilisateur, sans passer par le Go. +#[tokio::test] +async fn outil_task_par_la_facade() { + let call = sse(&[ + serde_json::json!({"choices":[{"delta":{"tool_calls":[{"index":0,"id":"t1","type":"function","function":{"name":"task_create","arguments":"{\"name\":\"Rappel\",\"prompt\":\"Bois\",\"schedule\":\"@every 2h\"}"}}]}}]}), + serde_json::json!({"choices":[{"delta":{},"finish_reason":"tool_calls"}]}), + ]); + let (url, seen) = fake_engine(vec![call, answer("c'est noté")]).await; + let dir = tempfile::tempdir().unwrap(); + // 2026-03-28 12:00:00 UTC. + fn clock() -> i64 { + 1_774_699_200 * 1_000_000_000 + } + let tasks = Arc::new(loki_rs::tasks::Tasks::with( + dir.path().to_path_buf(), + std::time::Duration::from_secs(3600), + clock, + )); + let (svc, go, _stop, _t) = service_with(Some(&url), |s| s.tasks = Some(tasks.clone())).await; + go.set("state", "user_tz", "Europe/Paris"); + go.set("state", "active_project", "generale"); + svc.send(serde_json::json!({"message": "rappelle-moi de boire", "cid": "t"})) + .await + .unwrap(); + until_done(&svc, 1).await; + assert!(go.tool_log.lock().unwrap().is_empty(), "{:?}", go.tool_log); + let list = loki_rs::tasks::list_tasks(&svc.shared.store).await; + assert_eq!(list.len(), 1, "{list:?}"); + let t = &list[0]; + assert_eq!( + ( + t.name.as_str(), + t.schedule.as_str(), + t.tz.as_str(), + t.project.as_str() + ), + ("Rappel", "@every 2h", "Europe/Paris", "generale") + ); + let seen = seen.lock().unwrap().clone(); + let tool = seen[1].1["messages"] + .as_array() + .unwrap() + .iter() + .rfind(|m| m["role"] == "tool") + .unwrap()["content"] + .clone(); + assert_eq!( + tool, + serde_json::json!(format!( + "[ok] tâche 'Rappel' créée (id {}), prochaine exécution 2026-03-28 15:00 (Europe/Paris)", + t.id + )) + ); +} diff --git a/rust/loki-rs/tests/parity_tasks/tools.json b/rust/loki-rs/tests/parity_tasks/tools.json new file mode 100644 index 0000000..77e8d6f --- /dev/null +++ b/rust/loki-rs/tests/parity_tasks/tools.json @@ -0,0 +1,7114 @@ +[ + { + "name": "liste vide", + "now": "2026-03-28T12:00:00Z", + "state": { + "user_tz": "Europe/Paris" + }, + "tool": "task_list", + "args": {}, + "out": "[aucune tâche planifiée dans ce projet]", + "tasks": null + }, + { + "name": "dans 30 minutes", + "tool": "task_create", + "args": { + "name": "Rappel", + "prompt": "Bois de l'eau", + "in_minutes": 30 + }, + "out": "[ok] tâche 'Rappel' créée (id {{ID1}}), prochaine exécution 2026-03-28 13:30 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "dans 1,9 minute : une seule", + "tool": "task_create", + "args": { + "name": "Bref", + "prompt": "x", + "in_minutes": 1.9 + }, + "out": "[ok] tâche 'Bref' créée (id {{ID2}}), prochaine exécution 2026-03-28 13:01 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "à une heure passée : demain", + "tool": "task_create", + "args": { + "name": "Matin", + "prompt": "Café", + "at": "08:15" + }, + "out": "[ok] tâche 'Matin' créée (id {{ID3}}), prochaine exécution 2026-03-29 08:15 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "à une heure à venir : aujourd'hui", + "tool": "task_create", + "args": { + "name": "Soir", + "prompt": "Bilan", + "at": " 21:05 " + }, + "out": "[ok] tâche 'Soir' créée (id {{ID4}}), prochaine exécution 2026-03-28 21:05 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "à une date, dans le trou du changement d'heure", + "tool": "task_create", + "args": { + "name": "Nuit", + "prompt": "x", + "at": "2026-03-29 02:30" + }, + "out": "[ok] tâche 'Nuit' créée (id {{ID5}}), prochaine exécution 2026-03-29 03:30 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "à une date passée", + "tool": "task_create", + "args": { + "name": "Hier", + "prompt": "x", + "at": "2026-03-27 10:00" + }, + "out": "[erreur] fréquence invalide : 2026-03-27 10:00 est déjà passé (il est 2026-03-28 13:00)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "at illisible", + "tool": "task_create", + "args": { + "name": "X", + "prompt": "x", + "at": "25:00" + }, + "out": "[erreur] 'at' invalide : « HH:MM » ou « AAAA-MM-JJ HH:MM »", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "at : date impossible", + "tool": "task_create", + "args": { + "name": "X", + "prompt": "x", + "at": "2026-02-30 10:00" + }, + "out": "[erreur] 'at' invalide : « HH:MM » ou « AAAA-MM-JJ HH:MM »", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "intervalle", + "tool": "task_create", + "args": { + "name": "Veille", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h" + }, + "out": "[ok] tâche 'Veille' créée (id {{ID6}}), prochaine exécution 2026-03-28 15:00 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "cron, désactivée", + "tool": "task_create", + "args": { + "name": "Semaine", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "enabled": false + }, + "out": "[ok] tâche 'Semaine' créée (id {{ID7}})", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "quotidienne ancrée", + "tool": "task_create", + "args": { + "name": "Journal", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "in_minutes": 5 + }, + "out": "[ok] tâche 'Journal' créée (id {{ID8}}), prochaine exécution 2026-03-29 09:00 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "fréquence invalide", + "tool": "task_create", + "args": { + "name": "X", + "prompt": "x", + "schedule": "@every 30s" + }, + "out": "[erreur] fréquence invalide : intervalle minimum : 1 minute", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "sans nom", + "tool": "task_create", + "args": { + "prompt": "x", + "in_minutes": 5 + }, + "out": "[erreur] name obligatoire, et schedule (tâche répétée) ou in_minutes / at (tâche unique)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "nom d'un autre type", + "tool": "task_create", + "args": { + "name": 42, + "prompt": "x", + "in_minutes": 5 + }, + "out": "[erreur] name obligatoire, et schedule (tâche répétée) ou in_minutes / at (tâche unique)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "moins d'une minute : pas de fréquence", + "tool": "task_create", + "args": { + "name": "X", + "prompt": "x", + "in_minutes": 0.5 + }, + "out": "[erreur] name obligatoire, et schedule (tâche répétée) ou in_minutes / at (tâche unique)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "ni prompt ni script", + "tool": "task_create", + "args": { + "name": "X", + "in_minutes": 5 + }, + "out": "[erreur] fournis soit 'prompt' (tâche IA) soit 'script' (tâche script)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "script absent", + "tool": "task_create", + "args": { + "name": "Ménage", + "script": "menage.sh", + "schedule": "@every 1d" + }, + "out": "[erreur] script introuvable : menage.sh", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "script hostile", + "tool": "task_create", + "args": { + "name": "Ménage", + "script": "a;b.sh", + "schedule": "@every 1d" + }, + "out": "[erreur] nom de script invalide (caractère interdit \";\") : a;b.sh", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "script dossier", + "files": { + "scripts/outils/x": "#!/bin/sh\n" + }, + "tool": "task_create", + "args": { + "name": "Ménage", + "script": "outils", + "schedule": "@every 1d" + }, + "out": "[erreur] outils est un dossier, pas un script", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "script présent", + "files": { + "scripts/menage.sh": "#!/bin/sh\necho ok\n" + }, + "tool": "task_create", + "args": { + "name": "Ménage", + "script": " menage.sh ", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "enabled": "false" + }, + "out": "[ok] tâche 'Ménage' créée (id {{ID9}}), prochaine exécution 2026-03-29 14:00 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "tâche d'un autre projet", + "state": { + "projects": "[{\"slug\":\"generale\",\"name\":\"Générale\",\"created_at\":1},{\"slug\":\"autre\",\"name\":\"Autre\",\"created_at\":2}]" + }, + "put_task": "{\"id\":\"aaaaaaaaaaaa\",\"name\":\"Autre\",\"prompt\":\"x\",\"schedule\":\"@every 1h\",\"tz\":\"Europe/Paris\",\"preset\":\"\",\"project\":\"autre\",\"no_mem\":false,\"no_web\":false,\"enabled\":true,\"last_run\":0,\"next_run\":1774699200000,\"last_dur_ms\":0,\"last_ok\":false,\"last_error\":\"\",\"last_report\":\"\"}", + "tool": "task_list", + "args": { + "id": "aaaaaaaaaaaa" + }, + "out": "[erreur] tâche introuvable : {{ID10}}", + "tasks": [ + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "tâche d'un projet disparu", + "put_task": "{\"id\":\"bbbbbbbbbbbb\",\"name\":\"Antique (fantôme)\",\"prompt\":\"x\",\"schedule\":\"@every 1h\",\"tz\":\"America/New_York\",\"preset\":\"\",\"project\":\"fantome\",\"no_mem\":false,\"no_web\":false,\"enabled\":true,\"last_run\":1774692000000,\"next_run\":1774699200000,\"last_dur_ms\":1200,\"last_ok\":false,\"last_error\":\"moteur occupé\",\"last_report\":\"\"}", + "tool": "task_list", + "args": { + "id": "bbbbbbbbbbbb" + }, + "out": "- {{ID11}} [on] « Antique (fantôme) » — @every 1h (prochaine : 2026-03-28 08:00) ✗ dernier run 2026-03-28 06:00 : moteur occupé", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "compte-rendu long", + "put_task": "{\"id\":\"cccccccccccc\",\"name\":\"Rapport\",\"prompt\":\"x\",\"schedule\":\"@every 1d\",\"tz\":\"Europe/Paris\",\"preset\":\"\",\"no_mem\":false,\"no_web\":false,\"enabled\":false,\"last_run\":1774692000000,\"next_run\":1774699200000,\"last_dur_ms\":5000,\"last_ok\":true,\"last_error\":\"\",\"last_report\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\\n sur plusieurs lignes\"}", + "tool": "task_list", + "args": {}, + "out": "- {{ID11}} [on] « Antique (fantôme) » — @every 1h (prochaine : 2026-03-28 08:00) ✗ dernier run 2026-03-28 06:00 : moteur occupé\n- {{ID2}} [on] « Bref » — @once 2026-03-28 13:01 (prochaine : 2026-03-28 13:01)\n- {{ID8}} [on] « Journal » — @every 1d@09:00 (prochaine : 2026-03-29 09:00)\n- {{ID3}} [on] « Matin » — @once 2026-03-29 08:15 (prochaine : 2026-03-29 08:15)\n- {{ID9}} [on] « Ménage » — @every 1d (prochaine : 2026-03-29 14:00)\n- {{ID5}} [on] « Nuit » — @once 2026-03-29 03:30 (prochaine : 2026-03-29 03:30)\n- {{ID1}} [on] « Rappel » — @once 2026-03-28 13:30 (prochaine : 2026-03-28 13:30)\n- {{ID12}} [off] « Rapport » — @every 1d ✓ dernier run 2026-03-28 11:00\n compte-rendu : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa� […] (id pour le compte-rendu complet)\n- {{ID7}} [off] « Semaine » — 0 9 * * 1-5\n- {{ID4}} [on] « Soir » — @once 2026-03-28 21:05 (prochaine : 2026-03-28 21:05)\n- {{ID6}} [on] « Veille » — @every 2h (prochaine : 2026-03-28 15:00)", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "compte-rendu complet", + "tool": "task_list", + "args": { + "id": " cccccccccccc " + }, + "out": "- {{ID12}} [off] « Rapport » — @every 1d ✓ dernier run 2026-03-28 11:00\n compte-rendu complet :\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "liste d'un autre projet", + "state": { + "active_project": "autre" + }, + "tool": "task_list", + "args": {}, + "out": "- {{ID10}} [on] « Autre » — @every 1h (prochaine : 2026-03-28 13:00)", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "création dans le projet actif", + "tool": "task_create", + "args": { + "name": "Ici", + "prompt": "x", + "schedule": "@every 3h" + }, + "out": "[ok] tâche 'Ici' créée (id {{ID13}}), prochaine exécution 2026-03-28 16:00 (Europe/Paris)", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "retour au projet par défaut", + "state": { + "active_project": "generale" + }, + "tool": "task_update", + "args": { + "id": "aaaaaaaaaaaa", + "name": "Volée" + }, + "out": "[erreur] tâche introuvable : {{ID10}}", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "modifier sans id", + "now": "2026-03-28T15:00:00Z", + "tool": "task_update", + "args": { + "name": "x" + }, + "out": "[erreur] id manquant", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "modifier un id inconnu", + "tool": "task_update", + "args": { + "id": "ffffffffffff" + }, + "out": "[erreur] tâche introuvable : {{ID14}}", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Rappel", + "next_run": 1774701000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@once 2026-03-28 13:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "renommer, nouvelle fréquence", + "tool": "task_update", + "args": { + "id": "{{ID1}}", + "name": " Eau ", + "prompt": " ", + "schedule": " @every 45m " + }, + "out": "[ok] tâche 'Eau' (id {{ID1}}) mise à jour", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "mettre en pause", + "tool": "task_update", + "args": { + "id": "{{ID1}}", + "enabled": false + }, + "out": "[ok] tâche 'Eau' (id {{ID1}}) mise à jour", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "fréquence refusée", + "tool": "task_update", + "args": { + "id": "{{ID1}}", + "schedule": "jamais" + }, + "out": "[erreur] fréquence invalide : cron : 5 champs attendus « min heure jour mois jour-semaine », reçu 1", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "reprendre une tâche sans prochaine exécution", + "put_task": "{\"id\":\"dddddddddddd\",\"name\":\"Dormante\",\"prompt\":\"x\",\"schedule\":\"0 8 * * *\",\"tz\":\"Europe/Paris\",\"preset\":\"\",\"no_mem\":false,\"no_web\":false,\"enabled\":false,\"last_run\":0,\"next_run\":0,\"last_dur_ms\":0,\"last_ok\":false,\"last_error\":\"\",\"last_report\":\"\"}", + "tool": "task_update", + "args": { + "id": "dddddddddddd", + "enabled": true, + "prompt": "Réveil" + }, + "out": "[ok] tâche 'Dormante' (id {{ID15}}) mise à jour", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "liste après modifications", + "tool": "task_list", + "args": {}, + "out": "- {{ID11}} [on] « Antique (fantôme) » — @every 1h (prochaine : 2026-03-28 08:00) ✗ dernier run 2026-03-28 06:00 : moteur occupé\n- {{ID2}} [on] « Bref » — @once 2026-03-28 13:01 (prochaine : 2026-03-28 13:01)\n- {{ID15}} [on] « Dormante » — 0 8 * * * (prochaine : 2026-03-29 08:00)\n- {{ID1}} [off] « Eau » — @every 45m\n- {{ID8}} [on] « Journal » — @every 1d@09:00 (prochaine : 2026-03-29 09:00)\n- {{ID3}} [on] « Matin » — @once 2026-03-29 08:15 (prochaine : 2026-03-29 08:15)\n- {{ID9}} [on] « Ménage » — @every 1d (prochaine : 2026-03-29 14:00)\n- {{ID5}} [on] « Nuit » — @once 2026-03-29 03:30 (prochaine : 2026-03-29 03:30)\n- {{ID12}} [off] « Rapport » — @every 1d ✓ dernier run 2026-03-28 11:00\n compte-rendu : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa� […] (id pour le compte-rendu complet)\n- {{ID7}} [off] « Semaine » — 0 9 * * 1-5\n- {{ID4}} [on] « Soir » — @once 2026-03-28 21:05 (prochaine : 2026-03-28 21:05)\n- {{ID6}} [on] « Veille » — @every 2h (prochaine : 2026-03-28 15:00)", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "supprimer sans id", + "tool": "task_delete", + "args": { + "id": " " + }, + "out": "[erreur] id manquant", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "supprimer d'un autre projet", + "tool": "task_delete", + "args": { + "id": "aaaaaaaaaaaa" + }, + "out": "[erreur] tâche introuvable : {{ID10}}", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID1}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Eau", + "next_run": 1774712700000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bois de l'eau", + "schedule": "@every 45m", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "supprimer", + "tool": "task_delete", + "args": { + "id": "{{ID1}}" + }, + "out": "[ok] tâche 'Eau' (id {{ID1}}) supprimée", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "supprimer deux fois", + "tool": "task_delete", + "args": { + "id": "{{ID1}}" + }, + "out": "[erreur] tâche introuvable : {{ID1}}", + "tasks": [ + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + }, + { + "name": "fuseau d'une tâche existante", + "state": { + "user_tz": "" + }, + "tool": "task_create", + "args": { + "name": "Ailleurs", + "prompt": "x", + "at": "23:30" + }, + "out": "[ok] tâche 'Ailleurs' créée (id {{ID16}}), prochaine exécution 2026-03-28 23:30 (America/New_York)", + "tasks": [ + { + "enabled": true, + "id": "{{ID16}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ailleurs", + "next_run": 1774755000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 23:30", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID11}}", + "last_dur_ms": 1200, + "last_error": "moteur occupé", + "last_ok": false, + "last_report": "", + "last_run": 1774692000000, + "name": "Antique (fantôme)", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "fantome", + "prompt": "x", + "schedule": "@every 1h", + "tz": "America/New_York" + }, + { + "enabled": true, + "id": "{{ID10}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Autre", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 1h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID2}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Bref", + "next_run": 1774699260000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-28 13:01", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID15}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Dormante", + "next_run": 1774764000000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "Réveil", + "schedule": "0 8 * * *", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID13}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ici", + "next_run": 1774710000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "autre", + "prompt": "x", + "schedule": "@every 3h", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID8}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Journal", + "next_run": 1774767600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Écris", + "schedule": "@every 1d@09:00", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID3}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Matin", + "next_run": 1774764900000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Café", + "schedule": "@once 2026-03-29 08:15", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID9}}", + "kind": "script", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Ménage", + "next_run": 1774785600000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "ignoré ?", + "schedule": "@every 1d", + "script": "menage.sh", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID5}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Nuit", + "next_run": 1774747800000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "x", + "schedule": "@once 2026-03-29 03:30", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID12}}", + "last_dur_ms": 5000, + "last_error": "", + "last_ok": true, + "last_report": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaé et la suite\n sur plusieurs lignes", + "last_run": 1774692000000, + "name": "Rapport", + "next_run": 1774699200000, + "no_mem": false, + "no_web": false, + "preset": "", + "prompt": "x", + "schedule": "@every 1d", + "tz": "Europe/Paris" + }, + { + "enabled": false, + "id": "{{ID7}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Semaine", + "next_run": 1774854000000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Point", + "schedule": "0 9 * * 1-5", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID4}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Soir", + "next_run": 1774728300000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Bilan", + "schedule": "@once 2026-03-28 21:05", + "tz": "Europe/Paris" + }, + { + "enabled": true, + "id": "{{ID6}}", + "last_dur_ms": 0, + "last_error": "", + "last_ok": false, + "last_report": "", + "last_run": 0, + "name": "Veille", + "next_run": 1774706400000, + "no_mem": false, + "no_web": false, + "preset": "", + "project": "generale", + "prompt": "Regarde les nouvelles", + "schedule": "@every 2h", + "tz": "Europe/Paris" + } + ] + } +] diff --git a/rust/loki-rs/tests/tasks.rs b/rust/loki-rs/tests/tasks.rs index ee2e54e..594c8d2 100644 --- a/rust/loki-rs/tests/tasks.rs +++ b/rust/loki-rs/tests/tasks.rs @@ -495,3 +495,61 @@ async fn amorce_au_demarrage() { assert_eq!(next("eteinte"), 0); assert_eq!(next("posee"), 42); } + +fn zero_clock() -> i64 { + 0 +} + +/// Lot 37 : les outils task_* de l'agent, rejoués contre le journal du Go +/// (`internal/loki/parity_tasks_tools_test.go` → `parity_tasks/tools.json`) : +/// chaque appel, son résultat tel que le modèle le reçoit, les tâches en base +/// après coup. +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn parite_des_outils() { + use loki_rs::tasks::tools::{ToolEnv, exec, is_tool}; + let fx: Value = serde_json::from_str(include_str!("parity_tasks/tools.json")).expect("journal"); + let mut bn = bench(zero_clock).await; + let scripts = bn.home.join("scripts"); + let mut now = 0; + for st in fx.as_array().unwrap() { + let name = s(&st["name"]); + if let Some(n) = st["now"].as_str() { + now = rfc3339_ns(n); + } + let files: serde_json::Map = st["files"] + .as_object() + .into_iter() + .flatten() + .map(|(k, v)| (k.clone(), Value::String(bn.unmask(s(v))))) + .collect(); + apply_files(&bn.home, &Value::Object(files)); + for (k, v) in st["state"].as_object().into_iter().flatten() { + bn.go.set("state", k, s(v)); + } + if let Some(t) = st["put_task"].as_str() { + let raw = bn.unmask(t); + let v: Value = serde_json::from_str(&raw).unwrap(); + bn.go.set("tasks", s(&v["id"]), &raw); + bn.mask(&raw); + } + let tool = s(&st["tool"]); + assert!(is_tool(tool), "{name}"); + let args: serde_json::Map = + serde_json::from_str(&bn.unmask(&st["args"].to_string())).unwrap(); + let env = ToolEnv { + store: &bn.store, + scripts_dir: &scripts, + now_ns: now, + }; + let out = exec(&env, tool, &args).await.expect("outil task_*"); + assert_eq!(bn.mask(&out), s(&st["out"]), "{name}"); + assert_eq!(bn.snapshot().await, st["tasks"], "{name}"); + } + let env = ToolEnv { + store: &bn.store, + scripts_dir: &scripts, + now_ns: now, + }; + assert_eq!(exec(&env, "bash", &serde_json::Map::new()).await, None); + assert!(!is_tool("task_run")); +}