Skip to content
24 changes: 12 additions & 12 deletions Feishu_readme/Feishu_readme.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

# Feishu Setup Guide up to Entering the `chat_id` in `codexloop init`
# Feishu Setup Guide up to Entering the `chat_id` in `argusbot init`

This document focuses on one specific task only:

starting from scratch, preparing all information required for a Feishu bot, and then running `codexloop init` in the current project until the `Feishu chat id` field is filled in.
starting from scratch, preparing all information required for a Feishu bot, and then running `argusbot init` in the current project until the `Feishu chat id` field is filled in.

It does **not** cover subsequent steps such as `/run`, `/inject`, message delivery validation, or troubleshooting.

Expand All @@ -15,14 +15,14 @@ Enter the current repository directory:
cd ./ArgusBot
```

Confirm that both codex and codexloop are available:
Confirm that both codex/claude and argusbot are available:

```bash
codex --help
codexloop help
codex --help # or claude: claude --help
argusbot help
```

If codexloop is not available in your PATH, install the current repository in editable mode first:
If argusbot is not available in your PATH, install the current repository in editable mode first:

```bash
pip install -e .
Expand All @@ -41,7 +41,7 @@ You will need the following two values later:
- `App ID`
- `App Secret`

Please save them, as `codexloop init` will later prompt you for:
Please save them, as `argusbot init` will later prompt you for:

- `Feishu app id`
- `Feishu app secret`
Expand Down Expand Up @@ -98,7 +98,7 @@ A typical chat_id looks like:
oc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## 5. Run `codexloop init` in the Current Project
## 5. Run `argusbot init` in the Current Project

Make sure you are inside the target project directory:

Expand All @@ -109,7 +109,7 @@ cd ./ArgusBot
Then run:

```bash
codexloop init
argusbot init
```

During initialization, you will see prompts similar to the following:
Expand Down Expand Up @@ -142,7 +142,7 @@ At this point, this document ends.

## 6. Where the Configuration Will Be Written

After `codexloop init` completes, the configuration will be written to:
After `argusbot init` completes, the configuration will be written to:

```text
.codex_daemon/daemon_config.json
Expand All @@ -160,11 +160,11 @@ The Feishu-related fields are:

## 7. Minimal Checklist

Before running `codexloop init`, you only need to confirm the following four items:
Before running `argusbot init`, you only need to confirm the following four items:

- a Feishu custom app has been created
- the `App ID` has been obtained
- the `App Secret` has been obtained
- the target group `chat_id` has been obtained

Once these four values are ready, you can start `codexloop init` and enter the `Feishu chat id`.
Once these four values are ready, you can start `argusbot init` and enter the `Feishu chat id`.
24 changes: 12 additions & 12 deletions Feishu_readme/Feishu_readme_CN.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

# Feishu 配置到 `codexloop init` 输入 `chat id` 为止
# Feishu 配置到 `argusbot init` 输入 `chat id` 为止

这份文档只覆盖一件事:

从 0 开始准备飞书机器人所需信息,然后在当前项目里执行 `codexloop init`,并把 `Feishu chat id` 填进去为止。
从 0 开始准备飞书机器人所需信息,然后在当前项目里执行 `argusbot init`,并把 `Feishu chat id` 填进去为止。

不展开后续 `/run`、`/inject`、消息收发验证和故障排查。

Expand All @@ -15,14 +15,14 @@
cd ./ArgusBot
```

确认 `codex` 和 `codexloop` 可用:
确认 `codex`/`claude` 和 `argusbot` 可用:

```bash
codex --help
codexloop help
codex --help # 检查claude: claude --help
argusbot help
```

如果 `codexloop` 不在 PATH,先在当前仓库安装:
如果 `argusbot` 不在 PATH,先在当前仓库安装:

```bash
pip install -e .
Expand All @@ -41,7 +41,7 @@ pip install -e .
- `App ID`
- `App Secret`

把它们记下来,后面 `codexloop init` 会要求输入:
把它们记下来,后面 `argusbot init` 会要求输入:

- `Feishu app id`
- `Feishu app secret`
Expand Down Expand Up @@ -100,7 +100,7 @@ pip install -e .
oc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## 5. 在当前项目里执行 `codexloop init`
## 5. 在当前项目里执行 `argusbot init`

确认你当前就在目标项目目录下:

Expand All @@ -111,7 +111,7 @@ cd ./ArgusBot
然后执行:

```bash
codexloop init
argusbot init
```

初始化过程中会出现类似下面这些问题:
Expand Down Expand Up @@ -144,7 +144,7 @@ Feishu chat id:

## 6. 你填完以后,配置会写到哪里

`codexloop init` 会把配置写到当前项目下的:
`argusbot init` 会把配置写到当前项目下的:

```text
.codex_daemon/daemon_config.json
Expand All @@ -162,11 +162,11 @@ Feishu chat id:

## 7. 一个最短检查清单

在执行 `codexloop init` 之前,你只需要确认这 4 件事:
在执行 `argusbot init` 之前,你只需要确认这 4 件事:

- 已创建飞书自建应用
- 已拿到 `App ID`
- 已拿到 `App Secret`
- 已拿到目标群的 `chat_id`

如果这 4 个值齐了,就可以开始 `codexloop init` 并把 `Feishu chat id` 填进去。
如果这 4 个值齐了,就可以开始 `argusbot init` 并把 `Feishu chat id` 填进去。
4 changes: 2 additions & 2 deletions codex_autoloop/apps/cli_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def reply_to_source(source: str, message: str) -> None:
btw_agent = BtwAgent(
runner=build_codex_runner(
backend=args.runner_backend,
codex_bin=args.codex_bin,
runner_bin=args.runner_bin,
config=copilot_proxy,
),
config=BtwConfig(
Expand Down Expand Up @@ -424,7 +424,7 @@ def on_control_command(command) -> None:
event_sink = CompositeEventSink(sinks)
runner = build_codex_runner(
backend=args.runner_backend,
codex_bin=args.codex_bin,
runner_bin=args.runner_bin,
config=copilot_proxy,
event_callback=event_sink.handle_stream_line,
)
Expand Down
8 changes: 4 additions & 4 deletions codex_autoloop/apps/daemon_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__(self, args: argparse.Namespace) -> None:
self.btw_agent = BtwAgent(
runner=build_codex_runner(
backend=getattr(args, "run_runner_backend", DEFAULT_RUNNER_BACKEND),
codex_bin=getattr(args, "run_codex_bin", None),
runner_bin=getattr(args, "run_runner_bin", None),
config=run_copilot_proxy,
),
config=BtwConfig(
Expand Down Expand Up @@ -640,9 +640,9 @@ def build_child_command(
else:
cmd.append("--no-copilot-proxy")
cmd.extend(["--runner-backend", getattr(args, "run_runner_backend", DEFAULT_RUNNER_BACKEND)])
run_codex_bin = str(getattr(args, "run_codex_bin", "") or "").strip()
if run_codex_bin:
cmd.extend(["--runner-bin", run_codex_bin])
run_runner_bin = str(getattr(args, "run_runner_bin", "") or "").strip()
if run_runner_bin:
cmd.extend(["--runner-bin", run_runner_bin])
run_copilot_proxy_dir = str(getattr(args, "run_copilot_proxy_dir", "") or "").strip()
if run_copilot_proxy_dir:
cmd.extend(["--copilot-proxy-dir", run_copilot_proxy_dir])
Expand Down
3 changes: 1 addition & 2 deletions codex_autoloop/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ def build_parser() -> argparse.ArgumentParser:
)
parser.add_argument(
"--runner-bin",
"--codex-bin",
dest="codex_bin",
dest="runner_bin",
default=None,
help="CLI binary path for the selected execution backend.",
)
Expand Down
8 changes: 4 additions & 4 deletions codex_autoloop/codexloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ def run_interactive_config(*, home_dir: Path, run_cd: Path) -> dict[str, Any]:
"run_plan_record_file": None,
"run_resume_last_session": True,
"run_runner_backend": runner_backend,
"run_codex_bin": runner_bin,
"run_runner_bin": runner_bin,
"run_main_reasoning_effort": None,
"run_reviewer_reasoning_effort": None,
"run_main_model": None,
Expand Down Expand Up @@ -795,9 +795,9 @@ def build_daemon_command(*, config: dict[str, Any], home_dir: Path, token_lock_d
cmd.extend(["--run-model-preset", run_model_preset])
run_runner_backend = str(config.get("run_runner_backend") or DEFAULT_RUNNER_BACKEND).strip() or DEFAULT_RUNNER_BACKEND
cmd.extend(["--run-runner-backend", run_runner_backend])
run_codex_bin = str(config.get("run_codex_bin") or "").strip()
if run_codex_bin:
cmd.extend(["--run-runner-bin", run_codex_bin])
run_runner_bin = str(config.get("run_runner_bin") or "").strip()
if run_runner_bin:
cmd.extend(["--run-runner-bin", run_runner_bin])
if bool(config.get("run_copilot_proxy")):
cmd.append("--run-copilot-proxy")
else:
Expand Down
8 changes: 4 additions & 4 deletions codex_autoloop/copilot_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,20 +213,20 @@ def ensure_proxy_running(
def build_codex_runner(
*,
backend: RunnerBackend,
codex_bin: str,
runner_bin: str | None,
config: CopilotProxyConfig,
event_callback=None,
) -> CodexRunner:
if not backend_supports_copilot_proxy(backend):
return CodexRunner(
codex_bin=codex_bin,
codex_bin=runner_bin,
backend=backend,
event_callback=event_callback,
)
if not config.enabled:
return CodexRunner(codex_bin=codex_bin, backend=backend, event_callback=event_callback)
return CodexRunner(codex_bin=runner_bin, backend=backend, event_callback=event_callback)
return CodexRunner(
codex_bin=codex_bin,
codex_bin=runner_bin,
backend=backend,
event_callback=event_callback,
default_extra_args=codex_config_overrides(config),
Expand Down
45 changes: 33 additions & 12 deletions codex_autoloop/live_updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,41 @@ def extract_agent_message(stream: str, line: str) -> tuple[str, str] | None:
return None
if not isinstance(payload, dict):
return None
if payload.get("type") != "item.completed":
return None
item = payload.get("item", {})
if not isinstance(item, dict):
return None
if item.get("type") != "agent_message":
return None
text = item.get("text", "")
if not isinstance(text, str):

# Codex format: item.completed with agent_message
if payload.get("type") == "item.completed":
item = payload.get("item", {})
if not isinstance(item, dict):
return None
if item.get("type") != "agent_message":
return None
text = item.get("text", "")
if not isinstance(text, str):
return None
message = text.strip()
if message:
return actor, message
return None
message = text.strip()
if not message:

# Claude format: assistant message
if payload.get("type") == "assistant":
message_obj = payload.get("message", {})
if not isinstance(message_obj, dict):
return None
content = message_obj.get("content", [])
if not isinstance(content, list):
return None
parts: list[str] = []
for c in content:
if isinstance(c, dict) and c.get("type") == "text":
text = c.get("text", "")
if isinstance(text, str) and text.strip():
parts.append(text.strip())
if parts:
return actor, "\n".join(parts)
return None
return actor, message

return None


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion codex_autoloop/setup_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def main() -> None:
"run_yolo": args.run_yolo,
"run_resume_last_session": args.run_resume_last_session,
"run_runner_backend": runner_backend,
"run_codex_bin": runner_bin,
"run_runner_bin": runner_bin,
"run_main_reasoning_effort": main_reasoning_effort,
"run_reviewer_reasoning_effort": reviewer_reasoning_effort,
"run_main_model": main_model,
Expand Down
13 changes: 6 additions & 7 deletions codex_autoloop/telegram_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def main() -> None:
btw_agent = BtwAgent(
runner=build_codex_runner(
backend=args.run_runner_backend,
codex_bin=args.run_codex_bin,
runner_bin=args.run_runner_bin,
config=run_copilot_proxy,
),
config=BtwConfig(
Expand Down Expand Up @@ -1349,9 +1349,9 @@ def build_child_command(
else:
cmd.append("--no-copilot-proxy")
cmd.extend(["--runner-backend", getattr(args, "run_runner_backend", DEFAULT_RUNNER_BACKEND)])
run_codex_bin = str(getattr(args, "run_codex_bin", "") or "").strip()
if run_codex_bin:
cmd.extend(["--runner-bin", run_codex_bin])
run_runner_bin = str(getattr(args, "run_runner_bin", "") or "").strip()
if run_runner_bin:
cmd.extend(["--runner-bin", run_runner_bin])
run_copilot_proxy_dir = str(getattr(args, "run_copilot_proxy_dir", "") or "").strip()
if run_copilot_proxy_dir:
cmd.extend(["--copilot-proxy-dir", run_copilot_proxy_dir])
Expand Down Expand Up @@ -1481,7 +1481,7 @@ def set_force_fresh_session_marker(state_file: str | None, *, enabled: bool, rea
payload[FORCE_FRESH_SESSION_KEY] = bool(enabled)
if enabled:
payload["session_id"] = None
payload["force_fresh_updated_at"] = dt.datetime.now(dt.UTC).isoformat().replace("+00:00", "Z")
payload["force_fresh_updated_at"] = dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z")
if reason:
payload[FORCE_FRESH_REASON_KEY] = reason
else:
Expand Down Expand Up @@ -2017,8 +2017,7 @@ def build_parser() -> argparse.ArgumentParser:
)
parser.add_argument(
"--run-runner-bin",
"--run-codex-bin",
dest="run_codex_bin",
dest="run_runner_bin",
default=None,
help="CLI binary path for the selected child execution backend.",
)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ argusbot-setup = "codex_autoloop.setup_wizard:main"
argusbot-models = "codex_autoloop.model_catalog:main"

[tool.setuptools]
packages = ["codex_autoloop"]
packages = ["codex_autoloop", "codex_autoloop.core", "codex_autoloop.adapters", "codex_autoloop.apps"]

[tool.setuptools.package-data]
codex_autoloop = ["planner_schema.json", "reviewer_schema.json"]
Loading
Loading