Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/coding_agent_telegram/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ def default_bot_commands(*, enable_commit_command: bool, locale: str = DEFAULT_L
BotCommand("new", translate(locale, "bot.command.new")),
BotCommand("switch", translate(locale, "bot.command.switch")),
BotCommand("compact", translate(locale, "bot.command.compact")),
BotCommand("diff", translate(locale, "bot.command.diff")),
]
if enable_commit_command:
commands.append(BotCommand("commit", translate(locale, "bot.command.commit")))
commands.append(BotCommand("pull", translate(locale, "bot.command.pull")))
commands.append(BotCommand("push", translate(locale, "bot.command.push")))
commands.append(BotCommand("abort", translate(locale, "bot.command.abort")))
return commands
Expand Down Expand Up @@ -148,14 +150,21 @@ async def log_incoming_private_message(update, _context) -> None:
app.add_handler(CommandHandler("new", router.handle_new, filters=allowed_private, block=False))
app.add_handler(CommandHandler("switch", router.handle_switch, filters=allowed_private))
app.add_handler(CommandHandler("compact", router.handle_compact, filters=allowed_private))
app.add_handler(CommandHandler("diff", router.handle_diff, filters=allowed_private))
app.add_handler(CommandHandler("commit", router.handle_commit, filters=allowed_private))
app.add_handler(CommandHandler("pull", router.handle_pull, filters=allowed_private))
app.add_handler(CommandHandler("push", router.handle_push, filters=allowed_private))
app.add_handler(CommandHandler("abort", router.handle_abort, filters=allowed_private))
app.add_handler(CallbackQueryHandler(router.handle_provider_callback, pattern=r"^provider:set:(codex|copilot)$", block=False))
app.add_handler(CallbackQueryHandler(router.handle_queue_batch_callback, pattern=r"^queuebatch:(group|single|cancel)$", block=False))
app.add_handler(CallbackQueryHandler(router.handle_queue_continue_callback, pattern=r"^queuecontinue:(yes|no)$", block=False))
app.add_handler(CallbackQueryHandler(router.handle_branch_source_callback, pattern=r"^branchsource:[0-9a-f]{12}$", block=False))
app.add_handler(CallbackQueryHandler(router.handle_branch_discrepancy_callback, pattern=r"^branchdiscrepancy:(stored|current)$", block=False))
app.add_handler(CallbackQueryHandler(router.handle_commit_generate_callback, pattern=r"^commitgen:(confirm|cancel)$"))
app.add_handler(CallbackQueryHandler(router.handle_commit_execute_callback, pattern=r"^commitexec:(confirm|cancel)$"))
app.add_handler(CallbackQueryHandler(router.handle_diff_callback, pattern=r"^diff(?:show|page):\d+$"))
app.add_handler(CallbackQueryHandler(router.handle_switch_page_callback, pattern=r"^switchpage:\d+$"))
app.add_handler(CallbackQueryHandler(router.handle_pull_callback, pattern=r"^pull:(confirm|cancel)$"))
app.add_handler(CallbackQueryHandler(router.handle_push_callback, pattern=r"^push:(confirm|cancel)$"))
app.add_handler(CallbackQueryHandler(router.handle_trust_project_callback, pattern=r"^trustproject:(yes|no):"))
app.add_handler(MessageHandler(allowed_private & tg_filters.PHOTO, router.handle_photo, block=False))
Expand Down
58 changes: 54 additions & 4 deletions src/coding_agent_telegram/diff_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,66 @@ def changed_files(project_path: Path) -> list[str]:
]


def _collect_diff_for_file(project_path: Path, path: str) -> str:
return _git(project_path, ["diff", "--", path]).strip()
def split_changed_files(project_path: Path) -> tuple[list[str], list[str]]:
output = _git(project_path, ["status", "--short", "--untracked-files=all"])
tracked: list[str] = []
untracked: list[str] = []
for line in output.splitlines():
if len(line) < 4:
continue
status = line[:2]
path = line[3:].strip()
if " -> " in path:
path = path.split(" -> ", 1)[1].strip()
if (
not path
or path.startswith(f"{INTERNAL_APP_DIR}/")
or is_snapshot_excluded_path(path)
):
continue
if status == "??":
untracked.append(path)
else:
tracked.append(path)
return tracked, untracked


def collect_diffs(project_path: Path, files: list[str]) -> list[FileDiff]:
def _collect_diff_for_file(
project_path: Path,
path: str,
*,
against_ref: str | None = None,
cached: bool = False,
) -> str:
args = ["diff"]
if cached:
args.append("--cached")
if against_ref:
args.append(against_ref)
args.extend(["--", path])
return _git(project_path, args).strip()


def collect_diffs(
project_path: Path,
files: list[str],
*,
against_ref: str | None = None,
include_cached: bool = False,
) -> list[FileDiff]:
results: list[FileDiff] = []
for path in files:
if is_snapshot_excluded_path(path):
continue
diff = _collect_diff_for_file(project_path, path)
parts: list[str] = []
diff = _collect_diff_for_file(project_path, path, against_ref=against_ref)
if diff:
parts.append(diff)
if include_cached:
cached_diff = _collect_diff_for_file(project_path, path, cached=True)
if cached_diff and cached_diff not in parts:
parts.append(cached_diff)
diff = "\n\n".join(parts).strip()
results.append(FileDiff(path=path, diff=diff.strip()))
return results

Expand Down
27 changes: 27 additions & 0 deletions src/coding_agent_telegram/resources/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"bot.command.branch": "Git branch erstellen und wechseln",
"bot.command.commit": "Geprüfte Git commit-Befehle ausführen",
"bot.command.current": "Aktive Sitzung anzeigen",
"bot.command.diff": "Geänderte Dateinamen gegenüber HEAD anzeigen",
"bot.command.new": "Neue Sitzung erstellen",
"bot.command.pull": "Die aktuelle Sitzungs-branch pullen",
"bot.command.project": "Aktuellen Projektordner festlegen",
"bot.command.provider": "Provider für neue Sitzungen wählen",
"bot.command.push": "Die aktuelle Sitzungs-branch pushen",
Expand All @@ -18,6 +20,15 @@
"common.project_folder_missing": "⚠️ Der Projektordner für diese Sitzung existiert nicht mehr: {project_folder}",
"git.branch_unknown": "⚠️ Die branch der aktuellen Sitzung konnte nicht ermittelt werden.",
"git.cancel_button": "Abbrechen",
"git.usage_diff": "Verwendung: /diff",
"git.usage_pull": "Verwendung: /pull",
"git.pull_cancelled": "Pull abgebrochen.",
"git.pull_completed": "Pull abgeschlossen.",
"git.pull_confirm_button": "Pull bestätigen",
"git.pull_confirm_prompt": "Branch `{branch_name}` von `origin` pullen?",
"git.pull_confirm_prompt_with_default": "Branch `{branch_name}` von `origin` pullen und zusätzlich die Standard-branch `{default_branch}` aktualisieren?",
"git.pull_in_progress": "Branch `{branch_name}` wird von `origin` gepullt...",
"git.pull_in_progress_with_default": "Branch `{branch_name}` wird von `origin` gepullt und die Standard-branch `{default_branch}` wird aktualisiert...",
"git.push_cancelled": "Push abgebrochen.",
"git.push_cancelled_checkout_failed": "Push abgebrochen. Wechsel zu `{branch_name}` ist zuerst fehlgeschlagen.",
"git.push_confirm_button": "Push bestätigen",
Expand Down Expand Up @@ -163,13 +174,29 @@
"git.commit_disabled": "/commit ist deaktiviert.\nSetze ENABLE_COMMIT_COMMAND=true in der Bot-Umgebung, um ihn zu aktivieren.",
"git.usage_commit": "Verwendung: /commit git add ... && git commit ...",
"git.no_valid_commit_commands": "Es wurden keine gültigen git commit-Befehle gefunden.",
"git.commit_generate_prompt": "Einen git commit-Befehl für die aktuell geänderten Dateien erzeugen?",
"git.commit_generate_button": "Befehl erzeugen",
"git.commit_generate_cancelled": "Die Generierung des Commit-Befehls wurde abgebrochen.",
"git.commit_generate_no_changes": "Es gibt keine geänderten Dateien, für die ein Commit-Befehl erzeugt werden könnte.",
"git.commit_generated_below": "Der erzeugte Commit-Befehl steht unten.",
"git.commit_generated_command": "Erzeugter Commit-Befehl",
"git.commit_execute_prompt": "Möchtest du den Commit ausführen?",
"git.commit_execute_button": "Commit ausführen",
"git.commit_execute_confirmed": "Der erzeugte Commit-Befehl wird ausgeführt...",
"git.commit_execute_context_changed": "Die aktive Sitzung oder das Projekt wurde geändert. Bitte den Commit-Befehl erneut erzeugen.",
"git.project_not_trusted_for_mutation": "Dieses Projekt ist nicht für verändernde Git-Operationen freigegeben. Verwende ein mit /project angelegtes Projekt oder markiere es zuerst als vertrauenswürdig.",
"git.unsafe_path_arguments": "Unsichere Pfadargumente sind nicht erlaubt. Es dürfen nur Dateien innerhalb des aktuellen Projekts verwendet werden.",
"diff.task_completed": "Aufgabe abgeschlossen.",
"diff.session_label": "Session: {session_name}",
"diff.project_label": "Projekt: {project_folder}",
"diff.changed_files": "Geänderte Dateien:",
"diff.none": "(keine)",
"diff.tracked_files": "Geänderte versionierte Dateien:",
"diff.tracked_files_page_info": "Zeige {start}-{end} von {total}.",
"diff.untracked_files": "Unversionierte Dateien:",
"diff.click_button_to_see_file_diff": "Klicke unten auf eine Schaltfläche, um den Diff einer Datei anzuzeigen.",
"diff.button_prev_page": "Zurück",
"diff.button_next_page": "Weiter",
"diff.new_file_header": "{file_path} (neue Datei) ({index}/{total})",
"diff.changed_file_header": "{file_path} (+{additions} -{deletions}) ({index}/{total})",
"cli.created_env_if_missing": "{env_path} wurde erstellt, falls die Datei noch nicht existierte.",
Expand Down
27 changes: 27 additions & 0 deletions src/coding_agent_telegram/resources/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"bot.command.branch": "Create and switch to a Git branch",
"bot.command.commit": "Run validated Git commit commands",
"bot.command.current": "Show the active session",
"bot.command.diff": "Show changed filenames vs HEAD",
"bot.command.new": "Create a new session",
"bot.command.pull": "Pull the current session branch",
"bot.command.project": "Set the current project folder",
"bot.command.provider": "Choose the provider for new sessions",
"bot.command.push": "Push the current session branch",
Expand All @@ -19,11 +21,20 @@
"common.project_folder_missing": "⚠️ Project folder no longer exists for this session: {project_folder}",
"git.branch_unknown": "⚠️ Could not determine the branch for the current session.",
"git.cancel_button": "Cancel",
"git.usage_diff": "Usage: /diff",
"git.pull_cancelled": "Pull cancelled.",
"git.pull_completed": "Pull completed.",
"git.pull_confirm_button": "Confirm pull",
"git.pull_confirm_prompt": "Pull branch `{branch_name}` from `origin`?",
"git.pull_confirm_prompt_with_default": "Pull branch `{branch_name}` from `origin` and also refresh default branch `{default_branch}`?",
"git.pull_in_progress": "Pulling branch `{branch_name}` from `origin`...",
"git.pull_in_progress_with_default": "Pulling branch `{branch_name}` from `origin` and refreshing default branch `{default_branch}`...",
"git.push_cancelled": "Push cancelled.",
"git.push_cancelled_checkout_failed": "Push cancelled. Failed to switch to `{branch_name}` first.",
"git.push_confirm_button": "Confirm push",
"git.push_confirm_prompt": "Push branch `{branch_name}` to `origin`?",
"git.push_in_progress": "Pushing branch `{branch_name}` to `origin`...",
"git.usage_pull": "Usage: /pull",
"git.usage_push": "Usage: /push",
"message.photo_only_codex": "Photo attachments are currently supported only for codex sessions.",
"message.question_queued": "Question queued as Q{question_number}. It will run after the current agent task finishes.",
Expand Down Expand Up @@ -165,13 +176,29 @@
"git.commit_disabled": "/commit is disabled.\nSet ENABLE_COMMIT_COMMAND=true in the bot environment to enable it.",
"git.usage_commit": "Usage: /commit git add ... && git commit ...",
"git.no_valid_commit_commands": "No valid git commit commands were found.",
"git.commit_generate_prompt": "Generate a git commit command for the current changed files?",
"git.commit_generate_button": "Generate command",
"git.commit_generate_cancelled": "Commit command generation cancelled.",
"git.commit_generate_no_changes": "There are no changed files to generate a commit command for.",
"git.commit_generated_below": "Generated commit command below.",
"git.commit_generated_command": "Generated commit command",
"git.commit_execute_prompt": "Do you want to execute the commit?",
"git.commit_execute_button": "Execute commit",
"git.commit_execute_confirmed": "Executing generated commit command...",
"git.commit_execute_context_changed": "The active session or project changed. Please generate the commit command again.",
"git.project_not_trusted_for_mutation": "This project is not trusted for mutating git operations. Use a project created by /project or mark it trusted first.",
"git.unsafe_path_arguments": "Unsafe path arguments are not allowed. Only files inside the current project may be used.",
"diff.task_completed": "Task completed.",
"diff.session_label": "Session: {session_name}",
"diff.project_label": "Project: {project_folder}",
"diff.changed_files": "Changed files:",
"diff.none": "(none)",
"diff.tracked_files": "Tracked changed files:",
"diff.tracked_files_page_info": "Showing {start}-{end} of {total}.",
"diff.untracked_files": "Untracked files:",
"diff.click_button_to_see_file_diff": "Click a button below to see a file diff.",
"diff.button_prev_page": "Prev",
"diff.button_next_page": "Next",
"diff.new_file_header": "{file_path} (new file) ({index}/{total})",
"diff.changed_file_header": "{file_path} (+{additions} -{deletions}) ({index}/{total})",
"cli.created_env_if_missing": "Created {env_path} if it did not already exist.",
Expand Down
27 changes: 27 additions & 0 deletions src/coding_agent_telegram/resources/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"bot.command.branch": "Créer et changer de Git branch",
"bot.command.commit": "Exécuter des commandes Git commit validées",
"bot.command.current": "Afficher la session active",
"bot.command.diff": "Afficher les noms de fichiers modifiés par rapport à HEAD",
"bot.command.new": "Créer une nouvelle session",
"bot.command.pull": "Pull la branch de la session actuelle",
"bot.command.project": "Définir le dossier de projet actuel",
"bot.command.provider": "Choisir le fournisseur pour les nouvelles sessions",
"bot.command.push": "Push la branch de la session actuelle",
Expand All @@ -18,6 +20,15 @@
"common.project_folder_missing": "⚠️ Le dossier du projet n’existe plus pour cette session : {project_folder}",
"git.branch_unknown": "⚠️ Impossible de déterminer la branch de la session actuelle.",
"git.cancel_button": "Annuler",
"git.usage_diff": "Utilisation : /diff",
"git.usage_pull": "Utilisation : /pull",
"git.pull_cancelled": "Pull annulé.",
"git.pull_completed": "Pull terminé.",
"git.pull_confirm_button": "Confirmer pull",
"git.pull_confirm_prompt": "Pull la branch `{branch_name}` depuis `origin` ?",
"git.pull_confirm_prompt_with_default": "Pull la branch `{branch_name}` depuis `origin` et rafraîchir aussi la branch par défaut `{default_branch}` ?",
"git.pull_in_progress": "Pull de la branch `{branch_name}` depuis `origin`...",
"git.pull_in_progress_with_default": "Pull de la branch `{branch_name}` depuis `origin` et rafraîchissement de la branch par défaut `{default_branch}`...",
"git.push_cancelled": "Push annulé.",
"git.push_cancelled_checkout_failed": "Push annulé. Échec du basculement vers `{branch_name}`.",
"git.push_confirm_button": "Confirmer push",
Expand Down Expand Up @@ -163,13 +174,29 @@
"git.commit_disabled": "/commit est désactivé.\nDéfinissez ENABLE_COMMIT_COMMAND=true dans l'environnement du bot pour l'activer.",
"git.usage_commit": "Utilisation : /commit git add ... && git commit ...",
"git.no_valid_commit_commands": "Aucune commande git commit valide n'a été trouvée.",
"git.commit_generate_prompt": "Générer une commande git commit pour les fichiers actuellement modifiés ?",
"git.commit_generate_button": "Générer la commande",
"git.commit_generate_cancelled": "La génération de la commande de commit a été annulée.",
"git.commit_generate_no_changes": "Aucun fichier modifié n'est disponible pour générer une commande de commit.",
"git.commit_generated_below": "La commande de commit générée se trouve ci-dessous.",
"git.commit_generated_command": "Commande de commit générée",
"git.commit_execute_prompt": "Voulez-vous exécuter le commit ?",
"git.commit_execute_button": "Exécuter le commit",
"git.commit_execute_confirmed": "Exécution de la commande de commit générée...",
"git.commit_execute_context_changed": "La session active ou le projet a changé. Veuillez régénérer la commande de commit.",
"git.project_not_trusted_for_mutation": "Ce projet n'est pas approuvé pour les opérations Git qui modifient l'état. Utilisez un projet créé via /project ou marquez-le d'abord comme approuvé.",
"git.unsafe_path_arguments": "Les arguments de chemin non sûrs ne sont pas autorisés. Seuls les fichiers à l'intérieur du projet actuel peuvent être utilisés.",
"diff.task_completed": "Tâche terminée.",
"diff.session_label": "Session : {session_name}",
"diff.project_label": "Projet : {project_folder}",
"diff.changed_files": "Fichiers modifiés :",
"diff.none": "(aucun)",
"diff.tracked_files": "Fichiers suivis modifiés :",
"diff.tracked_files_page_info": "Affichage de {start}-{end} sur {total}.",
"diff.untracked_files": "Fichiers non suivis :",
"diff.click_button_to_see_file_diff": "Cliquez sur un bouton ci-dessous pour voir le diff d’un fichier.",
"diff.button_prev_page": "Préc.",
"diff.button_next_page": "Suiv.",
"diff.new_file_header": "{file_path} (nouveau fichier) ({index}/{total})",
"diff.changed_file_header": "{file_path} (+{additions} -{deletions}) ({index}/{total})",
"cli.created_env_if_missing": "{env_path} a été créé s'il n'existait pas déjà.",
Expand Down
Loading
Loading