Metadata-Version: 2.4
Name: local-automata
Version: 0.1.0
Summary: ローカルLLM（mlx / llama.cpp / OpenAI互換）で動く、ツール・プロファイル対応の汎用エージェントのコア
Author: ToPo-ToPo-ToPo
License-Expression: Apache-2.0
Project-URL: Repository, https://github.com/ToPo-ToPo-ToPo/local-automata
Keywords: llm,agent,coding-agent,local-llm,mlx,llama.cpp,openai
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openai>=1.0
Requires-Dist: mcp>=1.0
Requires-Dist: pypdf>=4.0
Requires-Dist: mlx-lm>=0.31.3; sys_platform == "darwin" and platform_machine == "arm64"
Requires-Dist: mlx-vlm>=0.5.0; sys_platform == "darwin" and platform_machine == "arm64"
Requires-Dist: twine>=6.2.0
Provides-Extra: science
Requires-Dist: matplotlib>=3.10; extra == "science"
Requires-Dist: numpy>=2.0; extra == "science"
Requires-Dist: pandas>=2.2; extra == "science"
Requires-Dist: scikit-learn>=1.5; extra == "science"
Requires-Dist: scipy>=1.13; extra == "science"
Requires-Dist: sympy>=1.13; extra == "science"
Dynamic: license-file

# local-automata

ローカルLLM（mlx / llama.cpp）で動く、最小の汎用コーディングエージェント。
LLM とツール（ファイル読み書き・編集・検索・シェル実行）を組み合わせた agent loop が土台で、
設定（`agent.toml` ＋ 指示 `AGENTS.md`）だけでコーダー以外のエージェント
（キャラクターチャット等）にも転用できる。

> 挙動の詳細な仕様は [SPEC.md](SPEC.md) を参照。

## 目次

- [クイックスタート](#クイックスタート)
- [使い方](#使い方)
- [設定（agent.toml）](#設定agenttoml)
- [ツールと安全性](#ツールと安全性)
- [機能とオプション](#機能とオプション)
- [ローカルLLMサーバー](#ローカルllmサーバー)
- [サンプル](#サンプル)
- [ライブラリとして使う](#ライブラリとして使う)
- [構成とテスト](#構成とテスト)

## クイックスタート

[uv](https://docs.astral.sh/uv/) を使う。3ステップで動く。

```sh
# 1. 環境構築（OS を自動判定。Apple Silicon では mlx も入る）
uv sync

# 2. ローカルLLMサーバーを起動（別ターミナルで）
uv run local-automata-server

# 3. エージェントを起動
uv run local-automata          # ターミナルで対話
uv run local-automata-web      # ブラウザのチャット GUI（http://127.0.0.1:8765）
```

モデル・接続先・ツールなどの挙動はすべて **`agent.toml`（無ければ既定値）** で決まる
（→ [設定](#設定agenttoml)）。`uv run` の代わりに `.venv` を有効化すれば
`local-automata` を直接呼べる。

## 使い方

### ターミナル（`local-automata`）

対話形式。プロンプトを入力するたびに、エージェントがツールを使ってタスクを進める。
会話履歴はセッション内で保持される。

```sh
uv run local-automata
# > src/ のテストを実行して落ちている箇所を直して
# > さっきの修正にテストを追加して
```

- コマンド: `/help`・`/reset`（履歴クリア）・`/img`/`/file`（添付）・`exit`（終了、Ctrl-D も可）
- 応答はストリーミング表示（既定）。不具合が出る場合は `agent.toml` で `stream = false`。
- 履歴が `max_context_chars` を超えると、古いやり取りを自動で要約して圧縮する。

**画像・ファイルの添付**（ターミナル）:

```
> /img photo.png この画像を説明して          # vision 対応モデル＋サーバーが必要。複数はカンマ区切り、URL も可
> /file paper.pdf この論文の要点をまとめて    # PDF はテキスト抽出。CSV/TXT/JSON/MD も可
```

> 大きなデータは添付せず `workspace/` に置き、pandas 等で処理させる方が文脈を消費せず確実。

### ブラウザ GUI（`local-automata-web`）

追加依存なし（標準ライブラリのみ）の簡易チャット画面。設定は CLI と同じ `agent.toml` から読む。

```sh
uv run local-automata-web                 # http://127.0.0.1:8765 を開く
uv run local-automata-web --port 9000 --no-browser
```

- 応答を SSE でストリーミング表示し、**生成したコードや画像（グラフ）も画面に表示**する。
- 生成物はセッションごとの `workspace/<日時>_<タイトル>/` に保存。「＋ 新しいチャット」で別フォルダに切替。
- フロントエンドの静的ファイルはリポジトリ直下の `frontend/` に分離している。

## 設定（agent.toml）

モデル・パラメータ・運用設定はすべて **`agent.toml`（＋既定値）** で指定する。
**CLI 引数や環境変数では指定しない**（CLI は設定・プロファイル選択用の `--config` / `--profile` のみ）。
設定はトップレベル、または `[profiles.<name>]` 配下に書く。

```toml
# agent.toml
model = "mlx-community/Qwen3.6-27B-4bit"
base_url = "http://localhost:8080/v1"
backend = "mlx"            # mlx / llama-cpp（省略時は OS 自動判定）
temperature = 0.2
max_tokens = 16384
max_steps = 50
max_context_chars = 24000
enable_thinking = false
stream = true
tool_mode = "native"       # native / prompt
allow_install = false      # run_command でのパッケージ導入を許可するか
auto_start = false         # サーバーが無ければ自動起動するか
parallel = 1               # 自動起動時の同時処理スロット数（llama.cpp）
workdir = "workspace"      # ツールの作業ディレクトリ（'.' で現ディレクトリ）
planning = false           # 着手前に計画を立てさせるか
```

| キー | 既定 | 説明 |
| --- | --- | --- |
| `model` | `mlx-community/Qwen3.6-27B-4bit` | モデル名/パス |
| `base_url` | `http://localhost:8080/v1` | OpenAI 互換エンドポイント |
| `backend` | OS自動（macOS arm64→`mlx`、他→`llama-cpp`） | 自動起動するバックエンド |
| `temperature` | `0.2` | サンプリング温度 |
| `max_tokens` | `16384` | 1応答の最大生成トークン |
| `max_steps` | `50` | 1タスクの最大ツール往復回数 |
| `max_context_chars` | `24000` | 超えると古い履歴を要約して圧縮 |
| `enable_thinking` | `false` | 思考(thinking)モード |
| `stream` | `true` | ストリーミング表示 |
| `request_timeout` | （無制限） | LLM 応答の読み取りタイムアウト秒数（0/未指定で無制限） |
| `tool_mode` | `native` | ツール呼び出し方式 `native` / `prompt` |
| `allow_install` | `false` | `run_command` でのパッケージ導入許可 |
| `auto_start` | `false` | サーバー自動起動（既定は接続専用） |
| `parallel` | （なし） | 自動起動時の並列スロット数（llama.cpp） |
| `workdir` | `workspace` | ツールの作業ディレクトリ |
| `planning` | `false` | 着手前の計画 |
| `debug` | `false` | LLM 呼び出しの所要時間・サイズや各ステップを stderr に出す |

**指示（システムプロンプト）は Markdown** で分けて書く（Codex / Claude Code と同様）。
既定で `./AGENTS.md` を読み込み、`instructions_file` でパス変更、無ければ組み込み既定を使う。
サンプルは `AGENTS.md.example` / `agent.toml.example`。

```markdown
<!-- AGENTS.md -->
あなたは読み取り専用アシスタントです。まずファイルを読んでから判断してください。
```

## ツールと安全性

利用可能なツール: `read_file` / `write_file` / `edit_file` / `list_dir` / `grep` / `glob` / `run_command`。
`agent.toml` の `tools` で絞り込める（省略＝全部、`[]`＝無し）。

**作業ディレクトリ**:

- 既定で `./workspace`（自動作成）に閉じ込められる。`workdir = "."` で現ディレクトリ（既存プロジェクト編集用）。
- 各実行は `workspace/<日時>_<タイトル>/` に分離保存され、検討ごとに混ざらない（タイトルは最初のタスクから LLM が生成）。
- ファイルツールは workspace の外を拒否（`..`・絶対パス・シンボリックリンクをブロック）。
- `run_command` は workspace を作業ディレクトリとして実行する。ただしシェルは絶対パスや `cd` で外へ出られるため、
  これは隔離ではない。**信頼できないモデル/タスクはコンテナ/VM（できればネットワーク制限付き）で実行する**こと。
- パッケージ導入は既定でブロック（`pip/uv/conda/npm/apt …` を検出して拒否）。許可は `allow_install = true`。
  導入する場合は `uv pip install`、恒久的に必要なら `pyproject.toml` に追加して `uv sync`。

## 機能とオプション

### ツール呼び出し方式（`tool_mode`）

- **native（既定）**: OpenAI の function calling。形式は正確だが、mlx ではツール呼び出しが一括生成のため
  コード部分はストリーミングされない。
- **prompt**: ツール仕様をプロンプトに注入し、応答中の `tool` コードブロック（JSON）を解析。
  **コード生成もストリーミングされ**、ツール非対応モデルでも動く。形式はモデルの指示追従に依存。

### 思考(thinking)モード

`enable_thinking`（既定 false）。サーバー側は `local-automata-server --thinking` / `--no-thinking` で切替。
mlx_lm.server は起動時に固定（リクエスト単位の上書き不可）、vLLM 等はリクエスト単位で反映。
MLX 変換モデルの一部はテンプレートが未対応で効かないことがある。

### 計画モード・固定ワークフロー

- `planning = true` … 着手前にタスクを分解する `update_plan`（チェックリスト）ツールを追加し、
  「計画 → 実行 → 検証」の手順を促す。多段タスクの成功率が上がりやすい。
- `workflow_file = "workflow.md"` … 決まった手順を外部 Markdown で渡して従わせる（`update_plan` と併用可）。

### 長期メモリ

`[memory] enabled = true` で、セッションをまたいで記憶する `remember` / `recall` ツールが有効になる。
`path` をプロファイルごとに分ければキャラクター単位の記憶になる。

```toml
[memory]
enabled = true
path = ".coder/memory.json"
```

### MCP サーバー

`[mcp.servers.<name>]` に `command`（ローカルプロセス）か `url`（リモート）を書くと、
その MCP サーバーのツールが起動時に自動で取り込まれ、`<name>_<ツール名>` で使える（追加インストール不要）。

```toml
[mcp.servers.fs]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/data"]

[mcp.servers.remote]
url = "http://localhost:3000/sse"
```

### プロファイル

用途ごとに「指示（Markdown）＋ツール＋モデル・パラメータ」を1セットとして `[profiles.<name>]` に定義し、
`--profile <name>` または `default_profile` で切り替える。

```toml
default_profile = "coder"

[profiles.coder]
instructions_file = "AGENTS.md"
tools = ["read_file", "write_file", "edit_file", "list_dir", "run_command"]

[profiles.luna]            # キャラクターチャットの例
instructions_file = "characters/luna.md"
tools = []                 # ツールを使わない純粋な会話
```

```sh
uv run local-automata --profile luna
```

## ローカルLLMサーバー

`local-automata-server` が mlx / llama.cpp を OpenAI 互換 API で起動する（応答可能になるまで待つ）。
`--backend` の既定は OS 自動判定（macOS Apple Silicon → `mlx`、他 → `llama-cpp`）。

```sh
uv run local-automata-server                                  # 既定（OSに応じたバックエンド＋既定モデル）
uv run local-automata-server --backend llama-cpp --model /path/to/model.gguf
uv run local-automata-server --model model.gguf -- --ctx-size 8192 --jinja   # -- 以降はバックエンド固有引数
```

- `--host` / `--port`（既定 `127.0.0.1:8080`）、`--thinking` / `--no-thinking`。
- **並列処理**: llama.cpp は `--parallel N`（continuous batching。スロット数だけ KV キャッシュを消費）。
  mlx は逐次処理なので `--instances N` で連番ポートに N 個起動する（重みは N 倍のメモリ）。

### 接続のしかた

`local-automata` は起動時に `base_url` のサーバーが応答するか判定する。

- **既定（接続専用）**: 既存サーバーに相乗りする（停止しない）。無ければ起動方法を案内して終了。
- **`auto_start = true`**: サーバーが無ければ自動起動し、終了時に停止する。

**複数エージェントの同時実行**: 共有サーバーを1台だけ起動し（llama.cpp は `--parallel` をエージェント数以上に）、
各ターミナルで別プロファイルを接続する。接続専用が既定なので相乗りが安全。

```sh
uv run local-automata-server --backend llama-cpp --model model.gguf --parallel 2
uv run local-automata --profile analyzer   # ターミナル1
uv run local-automata --profile luna       # ターミナル2
```

## サンプル

`examples/` に用途別のエージェント一式がある。サーバーを起動した上で、各ディレクトリで実行する。

| ディレクトリ | 内容 |
| --- | --- |
| `examples/character/` | 会話のみ（ツールなし）＋長期メモリの「ルナ」 |
| `examples/coder/` | 力学（放物運動など）の数値計算コードを作成 → 実行 → 検証 |
| `examples/optimizer/` | 作成 → 実行 → 評価 → やり直しを固定ワークフローで反復 |
| `examples/ml/` | CSV から前処理 → 学習 → 評価 → 保存 |

```sh
cd examples/coder
uv run local-automata                       # CLI（agent.toml を自動読込。生成物は ./workspace/）
uv run local-automata-web                    # 同じ設定をブラウザ GUI で
uv run python run_physics.py             # ライブラリとして埋め込む例
```

詳細は各ディレクトリの `README.md` を参照。

## ライブラリとして使う

PyPI から `uv` でインストールして組み込める（自分のプロジェクトの依存に追加する）。

```sh
uv add local-automata                # コア（mac は mlx、PDF 抽出の pypdf も自動で入る）
uv add 'local-automata[science]'     # 科学計算の例も動かす（numpy/scipy/pandas/...）
```

```python
from local_automata import Agent, Config, LLMClient, build_registry

config = Config.load()  # 既定。agent.toml の設定を使うなら Config.load(load_agent_config(...).runtime)
agent = Agent(LLMClient(config), build_registry(), config)  # 既定で workspace/ を作る
print(agent.run("..."))
```

設定ファイル（`AGENTS.md` / `agent.toml`）から組み立てるなら `load_agent_config` を使う（`examples/` 参照）。
公開 API は `local_automata.__all__` を参照。

> mlx は環境マーカーで判定され、**Apple Silicon のときだけ自動で入る**（`uv add local-automata`・
> `uv sync` 共通。他OSでは自動スキップ）。非mac は llama.cpp（`llama-server` バイナリ）を別途用意する。
> 開発環境（`uv sync`）はさらに科学計算ライブラリと pytest が全OSで入る。Python は `.python-version`（3.11）。

## 構成とテスト

```
AGENTS.md.example    システムプロンプト（指示 Markdown）のサンプル
agent.toml.example   設定（TOML）のサンプル
frontend/            Web GUI の静的ファイル（index.html / style.css / app.js）
backend/local_automata/  Python パッケージ本体（PyPI に公開される。frontend は含まれない）
  config.py        実行時設定（agent.toml ＋ 既定値）
  settings.py      指示 Markdown と設定 TOML の読み込み
  images.py        画像・文書入力（パス/URL → content パーツ）
  llm.py           OpenAI 互換クライアント
  agent.py         エージェントループ（ツール呼び出し）
  cli.py           CLI / 対話モード（local-automata）
  webapp.py        Web GUI サーバー（local-automata-web）
  mcp_client.py    MCP サーバー連携（ツール自動取り込み）
  server.py        ローカルLLMサーバーのランチャー
  server_cli.py    サーバー起動 CLI（local-automata-server）
  spinner.py       進捗表示（生成中／実行中）
  tools/           ツール群（filesystem / shell / memory / plan / workspace）
tests/             pytest テスト一式
```

```sh
uv run pytest
```
