@grinev/opencode-telegram-bot 0.11.3 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +4 -1
- package/README.md +19 -3
- package/dist/app/start-bot-app.js +2 -0
- package/dist/bot/commands/abort.js +2 -0
- package/dist/bot/commands/commands.js +5 -0
- package/dist/bot/commands/definitions.js +2 -0
- package/dist/bot/commands/start.js +2 -0
- package/dist/bot/commands/task.js +399 -0
- package/dist/bot/commands/tasklist.js +220 -0
- package/dist/bot/handlers/prompt.js +8 -0
- package/dist/bot/index.js +27 -1
- package/dist/bot/middleware/interaction-guard.js +11 -0
- package/dist/config.js +1 -0
- package/dist/i18n/de.js +38 -1
- package/dist/i18n/en.js +38 -1
- package/dist/i18n/es.js +38 -1
- package/dist/i18n/fr.js +322 -0
- package/dist/i18n/index.js +7 -0
- package/dist/i18n/ru.js +38 -1
- package/dist/i18n/zh.js +38 -1
- package/dist/interaction/cleanup.js +10 -2
- package/dist/interaction/guard.js +7 -0
- package/dist/scheduled-task/creation-manager.js +113 -0
- package/dist/scheduled-task/display.js +239 -0
- package/dist/scheduled-task/executor.js +87 -0
- package/dist/scheduled-task/foreground-state.js +32 -0
- package/dist/scheduled-task/next-run.js +207 -0
- package/dist/scheduled-task/runtime.js +362 -0
- package/dist/scheduled-task/schedule-parser.js +169 -0
- package/dist/scheduled-task/store.js +65 -0
- package/dist/scheduled-task/types.js +19 -0
- package/dist/settings/manager.js +12 -0
- package/package.json +1 -1
package/dist/i18n/fr.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
export const fr = {
|
|
2
|
+
"cmd.description.status": "Statut du serveur et de la session",
|
|
3
|
+
"cmd.description.new": "Créer une nouvelle session",
|
|
4
|
+
"cmd.description.stop": "Arrêter l'action en cours",
|
|
5
|
+
"cmd.description.sessions": "Lister les sessions",
|
|
6
|
+
"cmd.description.projects": "Lister les projets",
|
|
7
|
+
"cmd.description.task": "Créer une tâche planifiée",
|
|
8
|
+
"cmd.description.tasklist": "Afficher les tâches planifiées",
|
|
9
|
+
"cmd.description.commands": "Commandes personnalisées",
|
|
10
|
+
"cmd.description.opencode_start": "Démarrer le serveur OpenCode",
|
|
11
|
+
"cmd.description.opencode_stop": "Arrêter le serveur OpenCode",
|
|
12
|
+
"cmd.description.help": "Aide",
|
|
13
|
+
"callback.unknown_command": "Commande inconnue",
|
|
14
|
+
"callback.processing_error": "Erreur de traitement",
|
|
15
|
+
"error.load_agents": "❌ Impossible de charger la liste des modes",
|
|
16
|
+
"error.load_models": "❌ Impossible de charger la liste des modèles",
|
|
17
|
+
"error.load_variants": "❌ Impossible de charger la liste des variantes",
|
|
18
|
+
"error.context_button": "❌ Impossible de traiter le bouton de contexte",
|
|
19
|
+
"error.generic": "🔴 Une erreur s'est produite.",
|
|
20
|
+
"interaction.blocked.expired": "⚠️ Cette interaction a expiré. Veuillez la relancer.",
|
|
21
|
+
"interaction.blocked.expected_callback": "⚠️ Veuillez utiliser les boutons inline pour cette étape ou appuyer sur Annuler.",
|
|
22
|
+
"interaction.blocked.expected_text": "⚠️ Veuillez envoyer un message texte pour cette étape.",
|
|
23
|
+
"interaction.blocked.expected_command": "⚠️ Veuillez envoyer une commande pour cette étape.",
|
|
24
|
+
"interaction.blocked.command_not_allowed": "⚠️ Cette commande n'est pas disponible à l'étape actuelle.",
|
|
25
|
+
"interaction.blocked.finish_current": "⚠️ Terminez d'abord l'interaction en cours (réponse ou annulation), puis ouvrez un autre menu.",
|
|
26
|
+
"inline.blocked.expected_choice": "⚠️ Choisissez une option avec les boutons inline ou appuyez sur Annuler.",
|
|
27
|
+
"inline.blocked.command_not_allowed": "⚠️ Cette commande n'est pas disponible tant que le menu inline est actif.",
|
|
28
|
+
"question.blocked.expected_answer": "⚠️ Répondez à la question en cours avec les boutons, Réponse personnalisée ou Annuler.",
|
|
29
|
+
"question.blocked.command_not_allowed": "⚠️ Cette commande n'est pas disponible tant que le flux de question actuel n'est pas terminé.",
|
|
30
|
+
"inline.button.cancel": "❌ Annuler",
|
|
31
|
+
"inline.inactive_callback": "Ce menu est inactif",
|
|
32
|
+
"inline.cancelled_callback": "Annulé",
|
|
33
|
+
"common.unknown": "inconnu",
|
|
34
|
+
"common.unknown_error": "erreur inconnue",
|
|
35
|
+
"start.welcome": "👋 Bienvenue dans OpenCode Telegram Bot !\n\nUtilisez les commandes :\n/projects — sélectionner un projet\n/sessions — liste des sessions\n/new — nouvelle session\n/task — tâche planifiée\n/tasklist — tâches planifiées\n/status — statut\n/help — aide\n\nUtilisez les boutons du bas pour choisir le mode d'agent, le modèle et la variante.",
|
|
36
|
+
"help.keyboard_hint": "💡 Utilisez les boutons du bas pour le mode d'agent, le modèle, la variante et les actions de contexte.",
|
|
37
|
+
"help.text": "📖 **Aide**\n\n/status - Vérifier l'état du serveur\n/sessions - Liste des sessions\n/new - Créer une nouvelle session\n/help - Aide",
|
|
38
|
+
"bot.thinking": "💭 Réflexion en cours...",
|
|
39
|
+
"bot.project_not_selected": "🏗 Aucun projet n'est sélectionné.\n\nSélectionnez d'abord un projet avec /projects.",
|
|
40
|
+
"bot.creating_session": "🔄 Création d'une nouvelle session...",
|
|
41
|
+
"bot.create_session_error": "🔴 Impossible de créer la session. Essayez /new ou vérifiez l'état du serveur avec /status.",
|
|
42
|
+
"bot.session_created": "✅ Session créée : {title}",
|
|
43
|
+
"bot.session_busy": "⏳ L'agent exécute déjà une tâche. Attendez la fin ou utilisez /abort pour interrompre l'exécution en cours.",
|
|
44
|
+
"bot.session_reset_project_mismatch": "⚠️ La session active ne correspond pas au projet sélectionné, elle a donc été réinitialisée. Utilisez /sessions pour en choisir une ou /new pour créer une nouvelle session.",
|
|
45
|
+
"bot.prompt_send_error": "Impossible d'envoyer la requête à OpenCode.",
|
|
46
|
+
"bot.session_error": "🔴 OpenCode a renvoyé une erreur : {message}",
|
|
47
|
+
"bot.session_retry": "🔁 {message}\n\nLe fournisseur renvoie la même erreur à chaque nouvelle tentative. Utilisez /abort pour arrêter.",
|
|
48
|
+
"bot.unknown_command": "⚠️ Commande inconnue : {command}. Utilisez /help pour voir les commandes disponibles.",
|
|
49
|
+
"bot.photo_downloading": "⏳ Téléchargement de la photo...",
|
|
50
|
+
"bot.photo_too_large": "⚠️ La photo est trop volumineuse (max {maxSizeMb}MB)",
|
|
51
|
+
"bot.photo_model_no_image": "⚠️ Le modèle actuel ne prend pas en charge les images. Envoi du texte uniquement.",
|
|
52
|
+
"bot.photo_download_error": "🔴 Impossible de télécharger la photo",
|
|
53
|
+
"bot.photo_no_caption": "💡 Conseil : ajoutez une légende pour décrire ce que vous voulez faire avec cette photo.",
|
|
54
|
+
"bot.file_downloading": "⏳ Téléchargement du fichier...",
|
|
55
|
+
"bot.file_too_large": "⚠️ Le fichier est trop volumineux (max {maxSizeMb}MB)",
|
|
56
|
+
"bot.file_download_error": "🔴 Impossible de télécharger le fichier",
|
|
57
|
+
"bot.model_no_pdf": "⚠️ Le modèle actuel ne prend pas en charge les PDF. Envoi du texte uniquement.",
|
|
58
|
+
"bot.text_file_too_large": "⚠️ Le fichier texte est trop volumineux (max {maxSizeKb}KB)",
|
|
59
|
+
"status.header_running": "🟢 Le serveur OpenCode est en cours d'exécution",
|
|
60
|
+
"status.health.healthy": "Sain",
|
|
61
|
+
"status.health.unhealthy": "Dégradé",
|
|
62
|
+
"status.line.health": "Statut : {health}",
|
|
63
|
+
"status.line.version": "Version : {version}",
|
|
64
|
+
"status.line.managed_yes": "Démarré par le bot : Oui",
|
|
65
|
+
"status.line.managed_no": "Démarré par le bot : Non",
|
|
66
|
+
"status.line.pid": "PID : {pid}",
|
|
67
|
+
"status.line.uptime_sec": "Temps de fonctionnement : {seconds} sec",
|
|
68
|
+
"status.line.mode": "Mode : {mode}",
|
|
69
|
+
"status.line.model": "Modèle : {model}",
|
|
70
|
+
"status.agent_not_set": "non défini",
|
|
71
|
+
"status.project_selected": "Projet : {project}",
|
|
72
|
+
"status.project_not_selected": "Projet : non sélectionné",
|
|
73
|
+
"status.project_hint": "Utilisez /projects pour sélectionner un projet",
|
|
74
|
+
"status.session_selected": "Session actuelle : {title}",
|
|
75
|
+
"status.session_not_selected": "Session actuelle : non sélectionnée",
|
|
76
|
+
"status.session_hint": "Utilisez /sessions pour en sélectionner une ou /new pour en créer une",
|
|
77
|
+
"status.server_unavailable": "🔴 Le serveur OpenCode est indisponible\n\nUtilisez /opencode_start pour démarrer le serveur.",
|
|
78
|
+
"projects.empty": "📭 Aucun projet trouvé.\n\nOuvrez un répertoire dans OpenCode et créez au moins une session, il apparaîtra ensuite ici.",
|
|
79
|
+
"projects.select": "Sélectionnez un projet :",
|
|
80
|
+
"projects.select_with_current": "Sélectionnez un projet :\n\nActuel : 🏗 {project}",
|
|
81
|
+
"projects.page_indicator": "Page {current}/{total}",
|
|
82
|
+
"projects.prev_page": "⬅️ Précédent",
|
|
83
|
+
"projects.next_page": "Suivant ➡️",
|
|
84
|
+
"projects.fetch_error": "🔴 Le serveur OpenCode est indisponible ou une erreur s'est produite lors du chargement des projets.",
|
|
85
|
+
"projects.page_load_error": "Impossible de charger cette page. Veuillez réessayer.",
|
|
86
|
+
"projects.selected": "✅ Projet sélectionné : {project}\n\n📋 La session a été réinitialisée. Utilisez /sessions ou /new pour ce projet.",
|
|
87
|
+
"projects.select_error": "🔴 Impossible de sélectionner le projet.",
|
|
88
|
+
"sessions.project_not_selected": "🏗 Aucun projet n'est sélectionné.\n\nSélectionnez d'abord un projet avec /projects.",
|
|
89
|
+
"sessions.empty": "📭 Aucune session trouvée.\n\nCréez une nouvelle session avec /new.",
|
|
90
|
+
"sessions.select": "Sélectionnez une session :",
|
|
91
|
+
"sessions.select_page": "Sélectionnez une session (page {page}) :",
|
|
92
|
+
"sessions.fetch_error": "🔴 Le serveur OpenCode est indisponible ou une erreur s'est produite lors du chargement des sessions.",
|
|
93
|
+
"sessions.select_project_first": "🔴 Aucun projet n'est sélectionné. Utilisez /projects.",
|
|
94
|
+
"sessions.page_empty_callback": "Aucune session sur cette page",
|
|
95
|
+
"sessions.page_load_error_callback": "Impossible de charger cette page. Veuillez réessayer.",
|
|
96
|
+
"sessions.button.prev_page": "⬅️ Préc.",
|
|
97
|
+
"sessions.button.next_page": "Suiv. ➡️",
|
|
98
|
+
"sessions.loading_context": "⏳ Chargement du contexte et des derniers messages...",
|
|
99
|
+
"sessions.selected": "✅ Session sélectionnée : {title}",
|
|
100
|
+
"sessions.select_error": "🔴 Impossible de sélectionner la session.",
|
|
101
|
+
"sessions.preview.empty": "Aucun message récent.",
|
|
102
|
+
"sessions.preview.title": "Messages récents :",
|
|
103
|
+
"sessions.preview.you": "Vous :",
|
|
104
|
+
"sessions.preview.agent": "Agent :",
|
|
105
|
+
"new.project_not_selected": "🏗 Aucun projet n'est sélectionné.\n\nSélectionnez d'abord un projet avec /projects.",
|
|
106
|
+
"new.created": "✅ Nouvelle session créée : {title}",
|
|
107
|
+
"new.create_error": "🔴 Le serveur OpenCode est indisponible ou une erreur s'est produite lors de la création de la session.",
|
|
108
|
+
"stop.no_active_session": "🛑 L'agent n'a pas été démarré\n\nCréez une session avec /new ou sélectionnez-en une via /sessions.",
|
|
109
|
+
"stop.in_progress": "🛑 Flux d'événements arrêté, envoi du signal d'abandon...\n\nEn attente de l'arrêt de l'agent.",
|
|
110
|
+
"stop.warn_unconfirmed": "⚠️ Le flux d'événements a été arrêté, mais le serveur n'a pas confirmé l'abandon.\n\nVérifiez /status et réessayez /abort dans quelques secondes.",
|
|
111
|
+
"stop.warn_maybe_finished": "⚠️ Le flux d'événements a été arrêté, mais l'agent a peut-être déjà terminé.",
|
|
112
|
+
"stop.success": "✅ Action de l'agent interrompue. Aucun autre message de cette exécution ne sera envoyé.",
|
|
113
|
+
"stop.warn_still_busy": "⚠️ Le signal a été envoyé, mais l'agent est toujours occupé.\n\nLe flux d'événements est déjà désactivé, donc aucun message intermédiaire ne sera envoyé.",
|
|
114
|
+
"stop.warn_timeout": "⚠️ Délai dépassé pour la requête d'abandon.\n\nLe flux d'événements est déjà arrêté, réessayez /abort dans quelques secondes.",
|
|
115
|
+
"stop.warn_local_only": "⚠️ Le flux d'événements a été arrêté localement, mais l'abandon côté serveur a échoué.",
|
|
116
|
+
"stop.error": "🔴 Impossible d'arrêter l'action.\n\nLe flux d'événements est arrêté, essayez /abort à nouveau.",
|
|
117
|
+
"opencode_start.already_running_managed": "⚠️ Le serveur OpenCode est déjà en cours d'exécution\n\nPID : {pid}\nTemps de fonctionnement : {seconds} secondes",
|
|
118
|
+
"opencode_start.already_running_external": "✅ Le serveur OpenCode est déjà en cours d'exécution en tant que processus externe\n\nVersion : {version}\n\nCe serveur n'a pas été démarré par le bot, donc /opencode-stop ne peut pas l'arrêter.",
|
|
119
|
+
"opencode_start.starting": "🔄 Démarrage du serveur OpenCode...",
|
|
120
|
+
"opencode_start.start_error": "🔴 Impossible de démarrer le serveur OpenCode\n\nErreur : {error}\n\nVérifiez que l'interface en ligne de commande OpenCode est installée et disponible dans le PATH :\nopencode --version\nnpm install -g @opencode-ai/cli",
|
|
121
|
+
"opencode_start.started_not_ready": "⚠️ Le serveur OpenCode a démarré, mais ne répond pas encore\n\nPID : {pid}\n\nLe serveur est peut-être encore en cours de démarrage. Essayez /status dans quelques secondes.",
|
|
122
|
+
"opencode_start.success": "✅ Serveur OpenCode démarré avec succès\n\nPID : {pid}\nVersion : {version}",
|
|
123
|
+
"opencode_start.error": "🔴 Une erreur s'est produite lors du démarrage du serveur.\n\nConsultez les logs de l'application pour plus de détails.",
|
|
124
|
+
"opencode_stop.external_running": "⚠️ Le serveur OpenCode s'exécute comme processus externe\n\nCe serveur n'a pas été démarré via /opencode-start.\nArrêtez-le manuellement ou utilisez /status pour vérifier son état.",
|
|
125
|
+
"opencode_stop.not_running": "⚠️ Le serveur OpenCode n'est pas en cours d'exécution",
|
|
126
|
+
"opencode_stop.stopping": "🛑 Arrêt du serveur OpenCode...\n\nPID : {pid}",
|
|
127
|
+
"opencode_stop.stop_error": "🔴 Impossible d'arrêter le serveur OpenCode\n\nErreur : {error}",
|
|
128
|
+
"opencode_stop.success": "✅ Serveur OpenCode arrêté avec succès",
|
|
129
|
+
"opencode_stop.error": "🔴 Une erreur s'est produite lors de l'arrêt du serveur.\n\nConsultez les logs de l'application pour plus de détails.",
|
|
130
|
+
"agent.changed_callback": "Mode modifié : {name}",
|
|
131
|
+
"agent.changed_message": "✅ Mode défini sur : {name}",
|
|
132
|
+
"agent.change_error_callback": "Impossible de modifier le mode",
|
|
133
|
+
"agent.menu.current": "Mode actuel : {name}\n\nSélectionnez un mode :",
|
|
134
|
+
"agent.menu.select": "Sélectionnez un mode de travail :",
|
|
135
|
+
"agent.menu.empty": "⚠️ Aucun mode disponible",
|
|
136
|
+
"agent.menu.error": "🔴 Impossible de récupérer la liste des modes",
|
|
137
|
+
"model.changed_callback": "Modèle modifié : {name}",
|
|
138
|
+
"model.changed_message": "✅ Modèle défini sur : {name}",
|
|
139
|
+
"model.change_error_callback": "Impossible de modifier le modèle",
|
|
140
|
+
"model.menu.empty": "⚠️ Aucun modèle disponible",
|
|
141
|
+
"model.menu.select": "Sélectionnez un modèle :",
|
|
142
|
+
"model.menu.current": "Modèle actuel : {name}\n\nSélectionnez un modèle :",
|
|
143
|
+
"model.menu.favorites_title": "⭐ Favoris (ajoutez des modèles aux favoris dans l'interface OpenCode)",
|
|
144
|
+
"model.menu.favorites_empty": "— Vide.",
|
|
145
|
+
"model.menu.recent_title": "🕘 Récents",
|
|
146
|
+
"model.menu.recent_empty": "— Vide.",
|
|
147
|
+
"model.menu.favorites_hint": "ℹ️ Ajoutez des modèles aux favoris dans l'interface OpenCode pour les garder en tête de liste.",
|
|
148
|
+
"model.menu.error": "🔴 Impossible de récupérer la liste des modèles",
|
|
149
|
+
"variant.model_not_selected_callback": "Erreur : aucun modèle sélectionné",
|
|
150
|
+
"variant.changed_callback": "Variante modifiée : {name}",
|
|
151
|
+
"variant.changed_message": "✅ Variante définie sur : {name}",
|
|
152
|
+
"variant.change_error_callback": "Impossible de modifier la variante",
|
|
153
|
+
"variant.select_model_first": "⚠️ Sélectionnez d'abord un modèle",
|
|
154
|
+
"variant.menu.empty": "⚠️ Aucune variante disponible",
|
|
155
|
+
"variant.menu.current": "Variante actuelle : {name}\n\nSélectionnez une variante :",
|
|
156
|
+
"variant.menu.error": "🔴 Impossible de récupérer la liste des variantes",
|
|
157
|
+
"context.button.confirm": "✅ Oui, compacter le contexte",
|
|
158
|
+
"context.no_active_session": "⚠️ Aucune session active. Créez une session avec /new",
|
|
159
|
+
"context.confirm_text": "📊 Réduction du contexte pour la session \"{title}\"\n\nCela réduira l'utilisation du contexte en supprimant les anciens messages de l'historique. La tâche en cours ne sera pas interrompue.\n\nContinuer ?",
|
|
160
|
+
"context.callback_session_not_found": "Session introuvable",
|
|
161
|
+
"context.callback_compacting": "Réduction du contexte en cours...",
|
|
162
|
+
"context.progress": "⏳ Réduction du contexte en cours...",
|
|
163
|
+
"context.error": "❌ La réduction du contexte a échoué",
|
|
164
|
+
"context.success": "✅ Contexte compacté avec succès",
|
|
165
|
+
"permission.inactive_callback": "La demande d'autorisation est inactive",
|
|
166
|
+
"permission.processing_error_callback": "Erreur de traitement",
|
|
167
|
+
"permission.no_active_request_callback": "Erreur : aucune demande active",
|
|
168
|
+
"permission.reply.once": "Autorisé une fois",
|
|
169
|
+
"permission.reply.always": "Toujours autorisé",
|
|
170
|
+
"permission.reply.reject": "Refusé",
|
|
171
|
+
"permission.send_reply_error": "❌ Impossible d'envoyer la réponse d'autorisation",
|
|
172
|
+
"permission.blocked.expected_reply": "⚠️ Veuillez d'abord répondre à la demande d'autorisation avec les boutons ci-dessus.",
|
|
173
|
+
"permission.blocked.command_not_allowed": "⚠️ Cette commande n'est pas disponible tant que vous n'avez pas répondu à la demande d'autorisation.",
|
|
174
|
+
"permission.header": "{emoji} Demande d'autorisation : {name}\n\n",
|
|
175
|
+
"permission.button.allow": "✅ Autoriser une fois",
|
|
176
|
+
"permission.button.always": "🔓 Toujours autoriser",
|
|
177
|
+
"permission.button.reject": "❌ Refuser",
|
|
178
|
+
"permission.name.bash": "Bash",
|
|
179
|
+
"permission.name.edit": "Modifier",
|
|
180
|
+
"permission.name.write": "Écrire",
|
|
181
|
+
"permission.name.read": "Lire",
|
|
182
|
+
"permission.name.webfetch": "Récupération web",
|
|
183
|
+
"permission.name.websearch": "Recherche web",
|
|
184
|
+
"permission.name.glob": "Recherche de fichiers",
|
|
185
|
+
"permission.name.grep": "Recherche de contenu",
|
|
186
|
+
"permission.name.list": "Lister le répertoire",
|
|
187
|
+
"permission.name.task": "Tâche",
|
|
188
|
+
"permission.name.lsp": "LSP",
|
|
189
|
+
"permission.name.external_directory": "Répertoire externe",
|
|
190
|
+
"question.inactive_callback": "Le sondage est inactif",
|
|
191
|
+
"question.processing_error_callback": "Erreur de traitement",
|
|
192
|
+
"question.select_one_required_callback": "Sélectionnez au moins une option",
|
|
193
|
+
"question.enter_custom_callback": "Envoyez votre réponse personnalisée sous forme de message",
|
|
194
|
+
"question.cancelled": "❌ Sondage annulé",
|
|
195
|
+
"question.answer_already_received": "Réponse déjà reçue, veuillez patienter...",
|
|
196
|
+
"question.completed_no_answers": "✅ Sondage terminé (aucune réponse)",
|
|
197
|
+
"question.no_active_project": "❌ Aucun projet actif",
|
|
198
|
+
"question.no_active_request": "❌ Aucune demande active",
|
|
199
|
+
"question.send_answers_error": "❌ Impossible d'envoyer les réponses à l'agent",
|
|
200
|
+
"question.multi_hint": "\n(Vous pouvez sélectionner plusieurs options)",
|
|
201
|
+
"question.button.submit": "✅ Terminer",
|
|
202
|
+
"question.button.custom": "🔤 Réponse personnalisée",
|
|
203
|
+
"question.button.cancel": "❌ Annuler",
|
|
204
|
+
"question.use_custom_button_first": "⚠️ Pour envoyer du texte, appuyez d'abord sur « Réponse personnalisée » pour la question actuelle.",
|
|
205
|
+
"question.summary.title": "✅ Sondage terminé !\n\n",
|
|
206
|
+
"question.summary.question": "Question {index} :\n{question}\n\n",
|
|
207
|
+
"question.summary.answer": "Réponse :\n{answer}\n\n",
|
|
208
|
+
"keyboard.agent_mode": "{emoji} Mode {name}",
|
|
209
|
+
"keyboard.context": "📊 {used} / {limit} ({percent}%)",
|
|
210
|
+
"keyboard.context_empty": "📊 0",
|
|
211
|
+
"keyboard.variant": "💭 {name}",
|
|
212
|
+
"keyboard.variant_default": "💡 Par défaut",
|
|
213
|
+
"keyboard.updated": "⌨️ Clavier mis à jour",
|
|
214
|
+
"pinned.default_session_title": "nouvelle session",
|
|
215
|
+
"pinned.unknown": "Inconnu",
|
|
216
|
+
"pinned.line.project": "Projet : {project}",
|
|
217
|
+
"pinned.line.model": "Modèle : {model}",
|
|
218
|
+
"pinned.line.context": "Contexte : {used} / {limit} ({percent}%)",
|
|
219
|
+
"pinned.files.title": "Fichiers ({count}) :",
|
|
220
|
+
"pinned.files.item": " {path}{diff}",
|
|
221
|
+
"pinned.files.more": " ... et encore {count}",
|
|
222
|
+
"tool.todo.overflow": "*({count} tâches supplémentaires)*",
|
|
223
|
+
"tool.file_header.write": "Écrire Fichier/Chemin : {path}\n============================================================\n\n",
|
|
224
|
+
"tool.file_header.edit": "Modifier Fichier/Chemin : {path}\n============================================================\n\n",
|
|
225
|
+
"runtime.wizard.ask_token": "Entrez le token du bot Telegram (obtenez-le auprès de @BotFather).\n> ",
|
|
226
|
+
"runtime.wizard.ask_language": "Sélectionnez la langue de l'interface.\nEntrez le numéro de la langue dans la liste ou le code locale.\nAppuyez sur Entrée pour conserver la langue par défaut : {defaultLocale}\n{options}\n> ",
|
|
227
|
+
"runtime.wizard.language_invalid": "Entrez un numéro de langue de la liste ou un code locale pris en charge.\n",
|
|
228
|
+
"runtime.wizard.language_selected": "Langue sélectionnée : {language}\n",
|
|
229
|
+
"runtime.wizard.token_required": "Le token est requis. Veuillez réessayer.\n",
|
|
230
|
+
"runtime.wizard.token_invalid": "Le token semble invalide (format attendu <id>:<secret>). Veuillez réessayer.\n",
|
|
231
|
+
"runtime.wizard.ask_user_id": "Entrez votre identifiant utilisateur Telegram (vous pouvez l'obtenir auprès de @userinfobot).\n> ",
|
|
232
|
+
"runtime.wizard.user_id_invalid": "Entrez un entier positif (> 0).\n",
|
|
233
|
+
"runtime.wizard.ask_api_url": "Entrez l'URL de l'API OpenCode (optionnel).\nAppuyez sur Entrée pour utiliser la valeur par défaut : {defaultUrl}\n> ",
|
|
234
|
+
"runtime.wizard.ask_server_username": "Entrez le nom d'utilisateur du serveur OpenCode (optionnel).\nAppuyez sur Entrée pour utiliser la valeur par défaut : {defaultUsername}\n> ",
|
|
235
|
+
"runtime.wizard.ask_server_password": "Entrez le mot de passe du serveur OpenCode (optionnel).\nAppuyez sur Entrée pour le laisser vide.\n> ",
|
|
236
|
+
"runtime.wizard.api_url_invalid": "Entrez une URL valide (http/https) ou appuyez sur Entrée pour la valeur par défaut.\n",
|
|
237
|
+
"runtime.wizard.start": "Configuration d'OpenCode Telegram Bot.\n",
|
|
238
|
+
"runtime.wizard.saved": "Configuration enregistrée :\n- {envPath}\n- {settingsPath}\n",
|
|
239
|
+
"runtime.wizard.not_configured_starting": "L'application n'est pas encore configurée. Lancement de l'assistant...\n",
|
|
240
|
+
"runtime.wizard.tty_required": "L'assistant interactif nécessite un terminal TTY. Exécutez `opencode-telegram config` dans un shell interactif.",
|
|
241
|
+
"rename.no_session": "⚠️ Aucune session active. Créez ou sélectionnez d'abord une session.",
|
|
242
|
+
"rename.prompt": "📝 Entrez le nouveau titre de la session :\n\nActuel : {title}",
|
|
243
|
+
"rename.empty_title": "⚠️ Le titre ne peut pas être vide.",
|
|
244
|
+
"rename.success": "✅ Session renommée en : {title}",
|
|
245
|
+
"rename.error": "🔴 Impossible de renommer la session.",
|
|
246
|
+
"rename.cancelled": "❌ Renommage annulé.",
|
|
247
|
+
"rename.inactive_callback": "La demande de renommage est inactive",
|
|
248
|
+
"rename.inactive": "⚠️ La demande de renommage n'est pas active. Exécutez /rename à nouveau.",
|
|
249
|
+
"rename.blocked.expected_name": "⚠️ Entrez le nouveau nom de la session sous forme de texte ou appuyez sur Annuler dans le message de renommage.",
|
|
250
|
+
"rename.blocked.command_not_allowed": "⚠️ Cette commande n'est pas disponible tant que le renommage attend un nouveau nom.",
|
|
251
|
+
"rename.button.cancel": "❌ Annuler",
|
|
252
|
+
"task.prompt.schedule": "⏰ Envoyez le planning de la tâche en langage naturel.\n\nExemples :\n- toutes les 5 minutes\n- chaque jour à 17:00\n- demain à 12:00",
|
|
253
|
+
"task.schedule_empty": "⚠️ Le planning ne peut pas être vide.",
|
|
254
|
+
"task.parse.in_progress": "⏳ Analyse du planning...",
|
|
255
|
+
"task.parse_error": "🔴 Impossible d'interpréter le planning.\n\n{message}\n\nEnvoyez le créneau à nouveau de façon plus claire.",
|
|
256
|
+
"task.schedule_preview": "✅ Planning interprété\n\nCompris comme : {summary}\n{cronLine}Fuseau horaire : {timezone}\nType : {kind}\nProchaine exécution : {nextRunAt}",
|
|
257
|
+
"task.schedule_preview.cron": "Cron : {cron}",
|
|
258
|
+
"task.prompt.body": "📝 Envoyez maintenant ce que le bot doit faire selon ce planning.",
|
|
259
|
+
"task.prompt_empty": "⚠️ Le texte de la tâche ne peut pas être vide.",
|
|
260
|
+
"task.created": "✅ Tâche planifiée créée\n\nTâche : {description}\nProjet : {project}\nModèle : {model}\nPlanning : {schedule}\n{cronLine}Prochaine exécution : {nextRunAt}",
|
|
261
|
+
"task.created.cron": "Cron : {cron}",
|
|
262
|
+
"task.button.retry_schedule": "🔁 Ressaisir le planning",
|
|
263
|
+
"task.button.cancel": "❌ Annuler",
|
|
264
|
+
"task.retry_schedule_callback": "Retour à la saisie du planning...",
|
|
265
|
+
"task.cancel_callback": "Annulation...",
|
|
266
|
+
"task.cancelled": "❌ Création de la tâche planifiée annulée.",
|
|
267
|
+
"task.inactive_callback": "Ce flux de tâche planifiée n'est plus actif",
|
|
268
|
+
"task.inactive": "⚠️ La création de tâche planifiée n'est pas active. Relancez /task.",
|
|
269
|
+
"task.blocked.expected_input": "⚠️ Terminez d'abord la configuration de la tâche planifiée : envoyez du texte ou utilisez le bouton dans le message du planning.",
|
|
270
|
+
"task.blocked.command_not_allowed": "⚠️ Cette commande n'est pas disponible pendant la création d'une tâche planifiée.",
|
|
271
|
+
"task.limit_reached": "⚠️ Limite de tâches atteinte ({limit}). Supprimez d'abord une tâche planifiée existante.",
|
|
272
|
+
"task.schedule_too_frequent": "Le planning récurrent est trop fréquent. L'intervalle minimum autorisé est d'une fois toutes les 5 minutes.",
|
|
273
|
+
"task.kind.cron": "récurrente",
|
|
274
|
+
"task.kind.once": "ponctuelle",
|
|
275
|
+
"task.run.success": "⏰ Tâche planifiée terminée : {description}\n\n{result}",
|
|
276
|
+
"task.run.error": "🔴 Échec de la tâche planifiée : {description}\n\nErreur : {error}",
|
|
277
|
+
"tasklist.empty": "📭 Aucune tâche planifiée pour le moment.",
|
|
278
|
+
"tasklist.select": "Sélectionnez une tâche planifiée :",
|
|
279
|
+
"tasklist.details": "⏰ Tâche planifiée\n\nTâche : {prompt}\nProjet : {project}\nPlanning : {schedule}\n{cronLine}Fuseau horaire : {timezone}\nProchaine exécution : {nextRunAt}\nDernière exécution : {lastRunAt}\nNombre d'exécutions : {runCount}",
|
|
280
|
+
"tasklist.details.cron": "Cron : {cron}",
|
|
281
|
+
"tasklist.button.delete": "🗑 Supprimer",
|
|
282
|
+
"tasklist.button.cancel": "❌ Annuler",
|
|
283
|
+
"tasklist.deleted_callback": "Supprimée",
|
|
284
|
+
"tasklist.cancelled_callback": "Annulé",
|
|
285
|
+
"tasklist.inactive_callback": "Ce menu des tâches planifiées est inactif",
|
|
286
|
+
"tasklist.load_error": "🔴 Impossible de charger les tâches planifiées.",
|
|
287
|
+
"commands.select": "Choisissez une commande OpenCode :",
|
|
288
|
+
"commands.empty": "📭 Aucune commande OpenCode n'est disponible pour ce projet.",
|
|
289
|
+
"commands.fetch_error": "🔴 Impossible de charger les commandes OpenCode.",
|
|
290
|
+
"commands.no_description": "Aucune description",
|
|
291
|
+
"commands.button.execute": "✅ Exécuter",
|
|
292
|
+
"commands.button.cancel": "❌ Annuler",
|
|
293
|
+
"commands.confirm": "Confirmez l'exécution de la commande {command}. Pour l'exécuter avec des arguments, envoyez-les dans un message.",
|
|
294
|
+
"commands.inactive_callback": "Ce menu de commandes est inactif",
|
|
295
|
+
"commands.cancelled_callback": "Annulé",
|
|
296
|
+
"commands.execute_callback": "Exécution de la commande...",
|
|
297
|
+
"commands.executing_prefix": "⚡ Exécution de la commande :",
|
|
298
|
+
"commands.arguments_empty": "⚠️ Les arguments ne peuvent pas être vides. Envoyez du texte ou appuyez sur Exécuter.",
|
|
299
|
+
"commands.execute_error": "🔴 Impossible d'exécuter la commande OpenCode.",
|
|
300
|
+
"cmd.description.rename": "Renommer la session actuelle",
|
|
301
|
+
"cli.usage": "Utilisation :\n opencode-telegram [start] [--mode sources|installed]\n opencode-telegram status\n opencode-telegram stop\n opencode-telegram config\n\nNotes :\n - Sans commande, `start` est utilisé par défaut\n - `--mode` n'est actuellement pris en charge que pour `start`",
|
|
302
|
+
"cli.placeholder.status": "La commande `status` est actuellement un placeholder. Les vraies vérifications d'état seront ajoutées dans la couche service (Phase 5).",
|
|
303
|
+
"cli.placeholder.stop": "La commande `stop` est actuellement un placeholder. Le véritable arrêt du processus en arrière-plan sera ajouté dans la couche service (Phase 5).",
|
|
304
|
+
"cli.placeholder.unavailable": "Commande indisponible.",
|
|
305
|
+
"cli.error.prefix": "Erreur CLI : {message}",
|
|
306
|
+
"cli.args.unknown_command": "Commande inconnue : {value}",
|
|
307
|
+
"cli.args.mode_requires_value": "L'option --mode nécessite une valeur : sources|installed",
|
|
308
|
+
"cli.args.invalid_mode": "Valeur de mode invalide : {value}. Attendu : sources|installed",
|
|
309
|
+
"cli.args.unknown_option": "Option inconnue : {value}",
|
|
310
|
+
"cli.args.mode_only_start": "L'option --mode est prise en charge uniquement pour la commande start",
|
|
311
|
+
"legacy.models.fetch_error": "🔴 Impossible de récupérer la liste des modèles. Vérifiez l'état du serveur avec /status.",
|
|
312
|
+
"legacy.models.empty": "📋 Aucun modèle disponible. Configurez les fournisseurs dans OpenCode.",
|
|
313
|
+
"legacy.models.header": "📋 Modèles disponibles :\n\n",
|
|
314
|
+
"legacy.models.no_provider_models": " ⚠️ Aucun modèle disponible\n",
|
|
315
|
+
"legacy.models.env_hint": "💡 Pour utiliser le modèle dans .env :\n",
|
|
316
|
+
"legacy.models.error": "🔴 Une erreur s'est produite lors du chargement de la liste des modèles.",
|
|
317
|
+
"stt.recognizing": "🎤 Reconnaissance audio en cours...",
|
|
318
|
+
"stt.recognized": "🎤 Reconnu :\n{text}",
|
|
319
|
+
"stt.not_configured": "🎤 La reconnaissance vocale n'est pas configurée.\n\nDéfinissez STT_API_URL et STT_API_KEY dans .env pour l'activer.",
|
|
320
|
+
"stt.error": "🔴 Impossible de reconnaître l'audio : {error}",
|
|
321
|
+
"stt.empty_result": "🎤 Aucune parole détectée dans le message audio.",
|
|
322
|
+
};
|
package/dist/i18n/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { en } from "./en.js";
|
|
2
2
|
import { de } from "./de.js";
|
|
3
3
|
import { es } from "./es.js";
|
|
4
|
+
import { fr } from "./fr.js";
|
|
4
5
|
import { ru } from "./ru.js";
|
|
5
6
|
import { zh } from "./zh.js";
|
|
6
7
|
const LOCALE_DEFINITIONS = [
|
|
@@ -22,6 +23,12 @@ const LOCALE_DEFINITIONS = [
|
|
|
22
23
|
dateLocale: "es-ES",
|
|
23
24
|
dictionary: es,
|
|
24
25
|
},
|
|
26
|
+
{
|
|
27
|
+
code: "fr",
|
|
28
|
+
label: "Français",
|
|
29
|
+
dateLocale: "fr-FR",
|
|
30
|
+
dictionary: fr,
|
|
31
|
+
},
|
|
25
32
|
{
|
|
26
33
|
code: "ru",
|
|
27
34
|
label: "Русский",
|
package/dist/i18n/ru.js
CHANGED
|
@@ -4,6 +4,8 @@ export const ru = {
|
|
|
4
4
|
"cmd.description.stop": "Прервать текущее действие",
|
|
5
5
|
"cmd.description.sessions": "Список сессий",
|
|
6
6
|
"cmd.description.projects": "Список проектов",
|
|
7
|
+
"cmd.description.task": "Создать задачу по расписанию",
|
|
8
|
+
"cmd.description.tasklist": "Список задач по расписанию",
|
|
7
9
|
"cmd.description.commands": "Пользовательские команды",
|
|
8
10
|
"cmd.description.opencode_start": "Запустить OpenCode сервер",
|
|
9
11
|
"cmd.description.opencode_stop": "Остановить OpenCode сервер",
|
|
@@ -30,7 +32,7 @@ export const ru = {
|
|
|
30
32
|
"inline.cancelled_callback": "Отменено",
|
|
31
33
|
"common.unknown": "неизвестна",
|
|
32
34
|
"common.unknown_error": "неизвестная ошибка",
|
|
33
|
-
"start.welcome": "👋 Добро пожаловать в OpenCode Telegram Bot!\n\nИспользуйте команды:\n/projects — выбрать проект\n/sessions — список сессий\n/new — новая сессия\n/status — статус\n/help — справка\n\nРежим, модель и вариант выбираются кнопками внизу.",
|
|
35
|
+
"start.welcome": "👋 Добро пожаловать в OpenCode Telegram Bot!\n\nИспользуйте команды:\n/projects — выбрать проект\n/sessions — список сессий\n/new — новая сессия\n/task — задача по расписанию\n/tasklist — список задач по расписанию\n/status — статус\n/help — справка\n\nРежим, модель и вариант выбираются кнопками внизу.",
|
|
34
36
|
"help.keyboard_hint": "💡 Режим, модель, вариант и действия с контекстом доступны через нижние кнопки клавиатуры.",
|
|
35
37
|
"help.text": "📖 **Справка**\n\n/status - Проверить статус сервера\n/sessions - Список сессий\n/new - Создать новую сессию\n/help - Справка",
|
|
36
38
|
"bot.thinking": "💭 Думаю...",
|
|
@@ -247,6 +249,41 @@ export const ru = {
|
|
|
247
249
|
"rename.blocked.expected_name": "⚠️ Введите новое название текстом или нажмите Отмена в сообщении переименования.",
|
|
248
250
|
"rename.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока ожидается новое название сессии.",
|
|
249
251
|
"rename.button.cancel": "❌ Отмена",
|
|
252
|
+
"task.prompt.schedule": "⏰ Отправьте расписание задачи обычным языком.\n\nПримеры:\n- каждые 5 минут\n- каждый день в 17:00\n- завтра в 12:00",
|
|
253
|
+
"task.schedule_empty": "⚠️ Расписание не может быть пустым.",
|
|
254
|
+
"task.parse.in_progress": "⏳ Распознаю расписание...",
|
|
255
|
+
"task.parse_error": "🔴 Не удалось распознать расписание.\n\n{message}\n\nОтправьте период еще раз в более явном виде.",
|
|
256
|
+
"task.schedule_preview": "✅ Расписание распознано\n\nКак я понял: {summary}\n{cronLine}Часовой пояс: {timezone}\nТип: {kind}\nСледующий запуск: {nextRunAt}",
|
|
257
|
+
"task.schedule_preview.cron": "Cron: {cron}",
|
|
258
|
+
"task.prompt.body": "📝 Теперь отправьте текст задачи, которую нужно выполнять по расписанию.",
|
|
259
|
+
"task.prompt_empty": "⚠️ Текст задачи не может быть пустым.",
|
|
260
|
+
"task.created": "✅ Задача по расписанию создана\n\nЗадача: {description}\nПроект: {project}\nМодель: {model}\nРасписание: {schedule}\n{cronLine}Следующий запуск: {nextRunAt}",
|
|
261
|
+
"task.created.cron": "Cron: {cron}",
|
|
262
|
+
"task.button.retry_schedule": "🔁 Ввести период заново",
|
|
263
|
+
"task.button.cancel": "❌ Отмена",
|
|
264
|
+
"task.retry_schedule_callback": "Возвращаю ввод периода...",
|
|
265
|
+
"task.cancel_callback": "Отменяю...",
|
|
266
|
+
"task.cancelled": "❌ Создание задачи по расписанию отменено.",
|
|
267
|
+
"task.inactive_callback": "Этот сценарий создания задачи уже неактивен",
|
|
268
|
+
"task.inactive": "⚠️ Сценарий создания задачи неактивен. Запустите /task снова.",
|
|
269
|
+
"task.blocked.expected_input": "⚠️ Сначала завершите создание задачи по расписанию: отправьте текст или используйте кнопку в сообщении с расписанием.",
|
|
270
|
+
"task.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока идет создание задачи по расписанию.",
|
|
271
|
+
"task.limit_reached": "⚠️ Достигнут лимит задач ({limit}). Сначала удалите одну из существующих задач по расписанию.",
|
|
272
|
+
"task.schedule_too_frequent": "Повторяющееся расписание слишком частое. Минимально допустимый интервал - один запуск в 5 минут.",
|
|
273
|
+
"task.kind.cron": "повторяющаяся",
|
|
274
|
+
"task.kind.once": "однократная",
|
|
275
|
+
"task.run.success": "⏰ Задача по расписанию выполнена: {description}\n\n{result}",
|
|
276
|
+
"task.run.error": "🔴 Ошибка выполнения задачи по расписанию: {description}\n\nОшибка: {error}",
|
|
277
|
+
"tasklist.empty": "📭 Задач по расписанию пока нет.",
|
|
278
|
+
"tasklist.select": "Выберите задачу по расписанию:",
|
|
279
|
+
"tasklist.details": "⏰ Задача по расписанию\n\nЗадача: {prompt}\nПроект: {project}\nРасписание: {schedule}\n{cronLine}Часовой пояс: {timezone}\nСледующий запуск: {nextRunAt}\nПоследний запуск: {lastRunAt}\nКоличество запусков: {runCount}",
|
|
280
|
+
"tasklist.details.cron": "Cron: {cron}",
|
|
281
|
+
"tasklist.button.delete": "🗑 Удалить",
|
|
282
|
+
"tasklist.button.cancel": "❌ Отмена",
|
|
283
|
+
"tasklist.deleted_callback": "Удалено",
|
|
284
|
+
"tasklist.cancelled_callback": "Отменено",
|
|
285
|
+
"tasklist.inactive_callback": "Это меню задач по расписанию уже неактивно",
|
|
286
|
+
"tasklist.load_error": "🔴 Не удалось загрузить задачи по расписанию.",
|
|
250
287
|
"commands.select": "Выберите команду OpenCode:",
|
|
251
288
|
"commands.empty": "📭 Для этого проекта нет доступных команд OpenCode.",
|
|
252
289
|
"commands.fetch_error": "🔴 Не удалось загрузить список команд OpenCode.",
|
package/dist/i18n/zh.js
CHANGED
|
@@ -4,6 +4,8 @@ export const zh = {
|
|
|
4
4
|
"cmd.description.stop": "停止当前操作",
|
|
5
5
|
"cmd.description.sessions": "列出会话",
|
|
6
6
|
"cmd.description.projects": "列出项目",
|
|
7
|
+
"cmd.description.task": "创建定时任务",
|
|
8
|
+
"cmd.description.tasklist": "查看定时任务",
|
|
7
9
|
"cmd.description.commands": "自定义命令",
|
|
8
10
|
"cmd.description.opencode_start": "启动 OpenCode 服务器",
|
|
9
11
|
"cmd.description.opencode_stop": "停止 OpenCode 服务器",
|
|
@@ -30,7 +32,7 @@ export const zh = {
|
|
|
30
32
|
"inline.cancelled_callback": "已取消",
|
|
31
33
|
"common.unknown": "未知",
|
|
32
34
|
"common.unknown_error": "未知错误",
|
|
33
|
-
"start.welcome": "👋 欢迎使用 OpenCode Telegram Bot!\n\n可用命令:\n/projects — 选择项目\n/sessions — 会话列表\n/new — 新建会话\n/status — 状态\n/help — 帮助\n\n请使用底部按钮选择模式、模型和变体。",
|
|
35
|
+
"start.welcome": "👋 欢迎使用 OpenCode Telegram Bot!\n\n可用命令:\n/projects — 选择项目\n/sessions — 会话列表\n/new — 新建会话\n/task — 定时任务\n/tasklist — 定时任务列表\n/status — 状态\n/help — 帮助\n\n请使用底部按钮选择模式、模型和变体。",
|
|
34
36
|
"help.keyboard_hint": "💡 代理模式、模型、变体和上下文操作请使用底部键盘按钮。",
|
|
35
37
|
"help.text": "📖 **帮助**\n\n/status - 查看服务器状态\n/sessions - 会话列表\n/new - 创建新会话\n/help - 帮助",
|
|
36
38
|
"bot.thinking": "💭 思考中...",
|
|
@@ -247,6 +249,41 @@ export const zh = {
|
|
|
247
249
|
"rename.blocked.expected_name": "⚠️ 请以文本输入新会话名称,或在重命名消息中点击取消。",
|
|
248
250
|
"rename.blocked.command_not_allowed": "⚠️ 重命名等待新名称期间不可用此命令。",
|
|
249
251
|
"rename.button.cancel": "❌ 取消",
|
|
252
|
+
"task.prompt.schedule": "⏰ 请用自然语言发送任务的时间安排。\n\n示例:\n- 每 5 分钟\n- 每天 17:00\n- 明天 12:00",
|
|
253
|
+
"task.schedule_empty": "⚠️ 时间安排不能为空。",
|
|
254
|
+
"task.parse.in_progress": "⏳ 正在解析时间安排...",
|
|
255
|
+
"task.parse_error": "🔴 无法解析时间安排。\n\n{message}\n\n请用更清晰的方式重新发送。",
|
|
256
|
+
"task.schedule_preview": "✅ 时间安排已解析\n\n理解为:{summary}\n{cronLine}时区:{timezone}\n类型:{kind}\n下次运行:{nextRunAt}",
|
|
257
|
+
"task.schedule_preview.cron": "Cron: {cron}",
|
|
258
|
+
"task.prompt.body": "📝 现在发送机器人按此时间安排需要执行的内容。",
|
|
259
|
+
"task.prompt_empty": "⚠️ 任务文本不能为空。",
|
|
260
|
+
"task.created": "✅ 定时任务已创建\n\n任务:{description}\n项目:{project}\n模型:{model}\n时间安排:{schedule}\n{cronLine}下次运行:{nextRunAt}",
|
|
261
|
+
"task.created.cron": "Cron: {cron}",
|
|
262
|
+
"task.button.retry_schedule": "🔁 重新输入时间安排",
|
|
263
|
+
"task.button.cancel": "❌ 取消",
|
|
264
|
+
"task.retry_schedule_callback": "正在重新输入时间安排...",
|
|
265
|
+
"task.cancel_callback": "正在取消...",
|
|
266
|
+
"task.cancelled": "❌ 定时任务创建已取消。",
|
|
267
|
+
"task.inactive_callback": "这个定时任务流程已失效",
|
|
268
|
+
"task.inactive": "⚠️ 定时任务创建流程未激活。请重新运行 /task。",
|
|
269
|
+
"task.blocked.expected_input": "⚠️ 请先完成当前定时任务设置:发送文本,或使用时间安排消息中的按钮。",
|
|
270
|
+
"task.blocked.command_not_allowed": "⚠️ 定时任务创建进行中时,此命令不可用。",
|
|
271
|
+
"task.limit_reached": "⚠️ 已达到任务数量上限({limit})。请先删除一个现有定时任务。",
|
|
272
|
+
"task.schedule_too_frequent": "重复任务过于频繁。最小允许间隔为每 5 分钟一次。",
|
|
273
|
+
"task.kind.cron": "重复",
|
|
274
|
+
"task.kind.once": "一次性",
|
|
275
|
+
"task.run.success": "⏰ 定时任务已完成: {description}\n\n{result}",
|
|
276
|
+
"task.run.error": "🔴 定时任务执行失败: {description}\n\n错误: {error}",
|
|
277
|
+
"tasklist.empty": "📭 还没有定时任务。",
|
|
278
|
+
"tasklist.select": "请选择一个定时任务:",
|
|
279
|
+
"tasklist.details": "⏰ 定时任务\n\n任务:{prompt}\n项目:{project}\n计划:{schedule}\n{cronLine}时区:{timezone}\n下次运行:{nextRunAt}\n上次运行:{lastRunAt}\n运行次数:{runCount}",
|
|
280
|
+
"tasklist.details.cron": "Cron: {cron}",
|
|
281
|
+
"tasklist.button.delete": "🗑 删除",
|
|
282
|
+
"tasklist.button.cancel": "❌ 取消",
|
|
283
|
+
"tasklist.deleted_callback": "已删除",
|
|
284
|
+
"tasklist.cancelled_callback": "已取消",
|
|
285
|
+
"tasklist.inactive_callback": "此定时任务菜单已失效",
|
|
286
|
+
"tasklist.load_error": "🔴 无法加载定时任务。",
|
|
250
287
|
"commands.select": "请选择一个 OpenCode 命令:",
|
|
251
288
|
"commands.empty": "📭 当前项目没有可用的 OpenCode 命令。",
|
|
252
289
|
"commands.fetch_error": "🔴 加载 OpenCode 命令失败。",
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
import { permissionManager } from "../permission/manager.js";
|
|
2
2
|
import { questionManager } from "../question/manager.js";
|
|
3
3
|
import { renameManager } from "../rename/manager.js";
|
|
4
|
+
import { taskCreationManager } from "../scheduled-task/creation-manager.js";
|
|
4
5
|
import { interactionManager } from "./manager.js";
|
|
5
6
|
import { logger } from "../utils/logger.js";
|
|
6
7
|
export function clearAllInteractionState(reason) {
|
|
7
8
|
const questionActive = questionManager.isActive();
|
|
8
9
|
const permissionActive = permissionManager.isActive();
|
|
9
10
|
const renameActive = renameManager.isWaitingForName();
|
|
11
|
+
const taskCreationActive = taskCreationManager.isActive();
|
|
10
12
|
const interactionSnapshot = interactionManager.getSnapshot();
|
|
11
13
|
questionManager.clear();
|
|
12
14
|
permissionManager.clear();
|
|
13
15
|
renameManager.clear();
|
|
16
|
+
taskCreationManager.clear();
|
|
14
17
|
interactionManager.clear(reason);
|
|
15
|
-
const hasAnyActiveState = questionActive ||
|
|
18
|
+
const hasAnyActiveState = questionActive ||
|
|
19
|
+
permissionActive ||
|
|
20
|
+
renameActive ||
|
|
21
|
+
taskCreationActive ||
|
|
22
|
+
interactionSnapshot !== null;
|
|
16
23
|
const message = `[InteractionCleanup] Cleared state: reason=${reason}, ` +
|
|
17
24
|
`questionActive=${questionActive}, permissionActive=${permissionActive}, ` +
|
|
18
|
-
`renameActive=${renameActive},
|
|
25
|
+
`renameActive=${renameActive}, taskCreationActive=${taskCreationActive}, ` +
|
|
26
|
+
`interactionKind=${interactionSnapshot?.kind || "none"}`;
|
|
19
27
|
if (hasAnyActiveState) {
|
|
20
28
|
logger.info(message);
|
|
21
29
|
return;
|
|
@@ -62,6 +62,10 @@ function isAllowedRenameCancelCallback(ctx, state) {
|
|
|
62
62
|
state.expectedInput === "text" &&
|
|
63
63
|
ctx.callbackQuery?.data === "rename:cancel");
|
|
64
64
|
}
|
|
65
|
+
function isAllowedTaskCallback(ctx, state) {
|
|
66
|
+
return (state.kind === "task" &&
|
|
67
|
+
(ctx.callbackQuery?.data === "task:cancel" || ctx.callbackQuery?.data === "task:retry-schedule"));
|
|
68
|
+
}
|
|
65
69
|
export function resolveInteractionGuardDecision(ctx) {
|
|
66
70
|
const state = interactionManager.getSnapshot();
|
|
67
71
|
const { inputType, command } = classifyIncomingInput(ctx);
|
|
@@ -90,6 +94,9 @@ export function resolveInteractionGuardDecision(ctx) {
|
|
|
90
94
|
if (inputType === "callback" && isAllowedRenameCancelCallback(ctx, state)) {
|
|
91
95
|
return createAllowDecision(inputType, state, command);
|
|
92
96
|
}
|
|
97
|
+
if (inputType === "callback" && isAllowedTaskCallback(ctx, state)) {
|
|
98
|
+
return createAllowDecision(inputType, state, command);
|
|
99
|
+
}
|
|
93
100
|
if (state.expectedInput === inputType) {
|
|
94
101
|
return createAllowDecision(inputType, state, command);
|
|
95
102
|
}
|