X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/522d226230a2eae0a8a33ae0fbf32f96c6886b26..47f69638bc96100f2e446f63c7c3689023156e64:/README.rst?ds=inline diff --git a/README.rst b/README.rst index c74a815..39a1eff 100644 --- a/README.rst +++ b/README.rst @@ -2,8 +2,9 @@ OneChat ######### -OneChat is a Go program. It prints its name. It is in early development. -Linux is supported. +OneChat is one AI agent in a single chat that never ends. A daemon owns +the agent and its files, and a terminal client and a Telegram bot talk +to it. It is in early development. Linux is supported. **************** Data directory @@ -32,7 +33,7 @@ field is an error. { "endpoint": "chatgpt", - "compactor": {"model": "gpt-6-luna", "effort": "high"} + "compactor": {"model": "gpt-6.1-sol", "effort": "high"} } ``endpoint`` @@ -43,7 +44,7 @@ field is an error. ``compactor`` The model and the reasoning effort of the summaries. The defaults are - ``gpt-6-luna`` and ``high``. + ``gpt-6.1-sol`` and ``high``. ******* Login @@ -63,18 +64,120 @@ before they expire. The file belongs to OneChat only. Do not share it with the Codex CLI, because each program rotates the refresh token and logs the other out. +******* + Agent +******* + +Start the daemon, and then the client in another terminal: + +.. code:: console + + onechat daemon + onechat chat + +The daemon owns the root agent in ``agent/`` in the data directory and +listens on the Unix socket ``onechat.sock`` there. In the client, each +line is a message to the agent, the line ``/stop`` interrupts the +running turn, the line ``/stop NAME`` stops the subagent NAME, and +Ctrl-D ends the client. The client shows the replies, the tool calls, +and the first lines of each tool result as they happen. It also shows +each message that the user sends from another client, with the client as +a mark, such as ``[telegram] text``. The daemon is the only process that +uses the token file while it runs, so ``onechat login`` and ``onechat +probe`` refuse to start until it stops. + +The agent runs commands with bash as the user in its working directory, +with no sandbox. It has the rights of the user, also on the token file. + +When the user asks for it, the agent starts subagents for long tasks. +Each subagent has a name, such as ``GreenOtter``, and runs in the +background while the agent answers other messages. It gets the view of +the agent and its task, and it runs its tools as the agent does, in +``agent/subagents/NAME/work``. A task in a repository gives the path of +the repository. The steps of a subagent go to its own log in +``agent/subagents/NAME``, not to the chat, and its final reply comes +back to the agent as one message that starts with ``[NAME]``. The agent +can send a subagent more messages: a running subagent reads them between +its tool calls, and a finished one goes on from its log, and its reply +comes back in the same way. When the user stops a subagent, the chat +gets a note, and the report of the subagent is logged, but it starts no +turn. Each model call of a subagent has the name in the ``agent`` field +of ``agent/usage.jsonl``. + +``agent/config.json`` holds the settings of the agent. The first start +writes it with the defaults and a random ID. Do not change the ID: the +prompt cache key comes from it. + +.. code:: json + + { + "name": "OneChat", + "id": "0123456789abcdef0123456789abcdef", + "model": "gpt-6.1-sol", + "effort": "medium", + "workdir": "/home/user" + } + +``workdir`` is an absolute path, and its default is the home directory. +``agent/instructions.md`` holds the user's instructions: who they are, +how their files are organized, and how they want work done. The prompt +ends with them, and a change applies at the next call. + +********** + Telegram +********** + +The daemon also connects the agent to a Telegram bot when +``telegram.json`` exists in the data directory. It polls the Bot API for +new messages, so it needs no open port. + +#. Make a bot with BotFather and keep its token. + +#. Find your numeric Telegram user ID. + +#. Write the token and the ID to ``telegram.json``, and give the file + mode 0600, because the token is a secret. The daemon refuses the file + with any other mode. + +#. Start the daemon, open a private chat with the bot, and write. + +.. code:: json + + {"token": "123456:ABC-token-from-BotFather", "owner": 123456789} + +The bot reads only the private chat of the owner and ignores all other +updates. Each text message goes to the agent as a user message, the line +``/stop`` interrupts the running turn, and the line ``/stop NAME`` stops +the subagent NAME. The bot sends the replies in parts of at most 4096 +characters, with their Markdown as Telegram formats: bold, italic, +strikethrough, code, code blocks, links, and headings as bold text. When +Telegram refuses the formats of a part, the bot sends the part again as +plain text. Each error goes as a short message in plain text. It shows +the typing action while a turn runs. It does not send the tool calls. It +sends each message that the user types in the terminal client, with the +mark ``[terminal]``. + +``agent/telegram-offset.json`` holds the ID of the next update. The bot +moves it past an update only after the message is durable in the log, so +a restart of the daemon does not lose a message. A crash just after the +write of a message can make the message repeat once. A network failure +or a rate limit makes the bot wait and try again, and does not stop the +daemon. + ******* Probe ******* -``onechat probe LOG COUNT`` measures the compactor on a log. It appends -the first COUNT messages of LOG, one JSON object ``{"kind", "text"}`` on -each line, to a new chat in ``probe/`` in the data directory, and builds -its tree with real model calls. The calls use the quota of the account. -The run stops at the first failed call, or when the used percent of a -quota window grows by more than 15 points. At the end it reports the -calls per message, the cached share of the input tokens, the retries, -the line sizes, and the quota at the first and the last call. +``onechat probe LOG COUNT [BUILDS]`` measures the compactor on a log. It +appends the first COUNT messages of LOG, one JSON object ``{"kind", +"text"}`` on each line, to a new chat in ``probe/`` in the data +directory, and builds its tree with real model calls. The calls use the +quota of the account. The run stops at the first failed call, after 660 +calls, or when the used percent of a quota window grows by more than 15 +points. At the end it reports the calls per message, the cached share of +the input tokens, the retries, the line sizes, and the quota at the +first and the last call. BUILDS, from 1 to 8, limits the model calls at +once in the run. A test writes a generated log of readable made-up messages: @@ -117,3 +220,6 @@ Format and check all files: bin/format bin/check nix flake check + +``bin/check`` and ``nix build`` run a short replay of the synthetic log. +``nix flake check`` also runs the full replay of 100,000 messages.