mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Let the command go to Codex or OpenRouter, not only Claude Code
Everything the last commit built assumed one agent was installed, which is a poor assumption to bake into a dictation tool. So the provider is a setting, and what it selects is one of three quite different things. Claude Code and Codex are the same shape: a CLI, streaming JSONL, a session id to resume, tools that reach the machine and whatever is connected to it. They share the runner. What differs is spelled out where it differs, which is more than the flag names: Codex has no system prompt to append, so the instruction rides in front of the command with a rule between them; it confines its commands in a sandbox rather than asking about them, so the permission setting is a sandbox mode; and `-s` is not accepted by `exec resume`, so both settings go through `-c` overrides, which are. OpenRouter is the odd one and is meant to be. No tools, no files, no calendar: it can say what the capital of Peru is and not what is in your diary, and the settings box says so rather than letting it be discovered. It also has no session to resume, so the conversation is kept here and resent, capped at 24 messages. A stored conversation names the provider that made it, and is ignored by any other: none of them can pick up another's thread, and a stale id would otherwise fail every command until the timeout cleared it. The interface calls the thing by its name, which in Turkish means the suffix has to agree with it: Claude'a but Codex'e, Claude'u but Codex'i. A name dropped into a sentence through t() cannot be inflected by that sentence, so it arrives inflected, from a small table in i18n. English takes the name as it is and keeps the preposition in the sentence.
This commit is contained in:
@@ -31,6 +31,7 @@ import assistant # noqa: E402
|
||||
import audio # noqa: E402
|
||||
import config as cfg # noqa: E402
|
||||
import hotkey # noqa: E402
|
||||
import i18n # noqa: E402
|
||||
import meeting # noqa: E402
|
||||
from i18n import t # noqa: E402
|
||||
from meeting import MeetingPipeline # noqa: E402
|
||||
@@ -192,6 +193,7 @@ class Dikte:
|
||||
BUSY: ("Working…", "view-refresh", "Dikte: working"),
|
||||
}
|
||||
label, icon, tip = labels[self.state]
|
||||
agent = assistant.display_name(self.conf)
|
||||
if self.ask_mode:
|
||||
tip = "Dikte: talking to Claude"
|
||||
if self.state == RECORDING:
|
||||
@@ -202,9 +204,11 @@ class Dikte:
|
||||
self.toggle_action.setEnabled(
|
||||
self.state == IDLE or (self.state == RECORDING and not self.ask_mode)
|
||||
)
|
||||
asked = i18n.name(agent, "dative")
|
||||
self.ask_action.setText(
|
||||
t("Stop and ask Claude") if self.state == RECORDING and self.ask_mode
|
||||
else t("Ask Claude")
|
||||
t("Stop and ask {name}", name=asked)
|
||||
if self.state == RECORDING and self.ask_mode
|
||||
else t("Ask {name}", name=asked)
|
||||
)
|
||||
self.ask_action.setEnabled(
|
||||
self.state == IDLE or (self.state == RECORDING and self.ask_mode)
|
||||
@@ -213,7 +217,8 @@ class Dikte:
|
||||
# A Claude command is the one job long enough to be worth calling off
|
||||
# once it is already running.
|
||||
self.cancel_action.setText(
|
||||
t("Stop Claude") if self.state == BUSY and self.ask_mode
|
||||
t("Stop {name}", name=i18n.name(agent, "accusative"))
|
||||
if self.state == BUSY and self.ask_mode
|
||||
else t("Cancel recording")
|
||||
)
|
||||
self.cancel_action.setEnabled(
|
||||
@@ -351,7 +356,10 @@ class Dikte:
|
||||
"""Drop the thread Claude has been following, so the next command starts
|
||||
a conversation of its own."""
|
||||
assistant.clear_session()
|
||||
self.overlay.show_done(t("Claude starts fresh next time."), 2500)
|
||||
self.overlay.show_done(
|
||||
t("{name} starts fresh next time.",
|
||||
name=assistant.display_name(self.conf)), 2500
|
||||
)
|
||||
|
||||
def _tick(self):
|
||||
seconds = self.elapsed.elapsed() / 1000.0
|
||||
@@ -493,17 +501,19 @@ class Dikte:
|
||||
|
||||
def _on_finished(self, _raw, text, warning):
|
||||
asked = self.ask_mode
|
||||
agent = assistant.display_name(self.conf)
|
||||
if warning:
|
||||
# The text was still pasted, but something on the way did not run.
|
||||
# Say so loudly: a rejected key, or a tool Claude was not allowed to
|
||||
# touch, otherwise looks exactly like a job that worked.
|
||||
first_line = warning.splitlines()[0]
|
||||
self.overlay.show_warning(
|
||||
t("Claude answered, but: {error}", error=first_line) if asked
|
||||
t("{name} answered, but: {error}", name=agent, error=first_line)
|
||||
if asked
|
||||
else t("Pasted raw, cleanup failed: {error}", error=first_line)
|
||||
)
|
||||
self.tray.showMessage(
|
||||
t("Dikte: Claude could not do all of it") if asked
|
||||
t("Dikte: {name} could not do all of it", name=agent) if asked
|
||||
else t("Dikte: cleanup failed"),
|
||||
f"{warning}\n\n{text}" if asked else warning,
|
||||
QSystemTrayIcon.MessageIcon.Warning, 10000,
|
||||
@@ -514,7 +524,9 @@ class Dikte:
|
||||
if asked:
|
||||
# Longer than a dictation's flash: this one is an answer, and
|
||||
# it is worth being able to read the start of it in the corner.
|
||||
self.overlay.show_done(t("Claude: {preview}", preview=preview), 6000)
|
||||
self.overlay.show_done(
|
||||
t("{name}: {preview}", name=agent, preview=preview), 6000
|
||||
)
|
||||
else:
|
||||
action = t("Pasted") if self.conf["auto_paste"] else t("Copied")
|
||||
self.overlay.show_done(
|
||||
|
||||
Reference in New Issue
Block a user