Skip to content

Commit 079e6b8

Browse files
committed
refactor: modularize runtime and refresh docs
1 parent 766719f commit 079e6b8

296 files changed

Lines changed: 14361 additions & 9855 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ LoopForge is a **personal AI engineer** for software delivery: long-running wor
1616
- (If the custom domain isn’t configured yet) GitHub Pages: https://rexleimo.github.io/LoopForge/
1717
- 5-minute outcomes: `docs-site/tutorials/five-minute-outcomes.md`
1818
- Positioning: `docs-site/explanation/why-loopforge.md`
19+
- Runtime architecture: `docs-site/explanation/runtime-architecture.md`
20+
- Internal maintainer map: `docs/internal/runtime-module-map.md`
1921

2022
## Status
2123

README.zh-CN.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ LoopForge是一个面向软件交付的 **个人研发助理(Personal AI Engin
1616
- (如自定义域名未配置)GitHub Pages:https://rexleimo.github.io/LoopForge/
1717
- 5 分钟可见结果:`docs-site/tutorials/five-minute-outcomes.md`
1818
- 产品定位说明:`docs-site/explanation/why-loopforge.md`
19+
- 运行时架构说明:`docs-site/explanation/runtime-architecture.md`
20+
- 仓库内部维护者地图:`docs/internal/runtime-module-map.md`
1921

2022
## 状态
2123

crates/loopforge-cli/src/cli.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod commands;
2+
3+
#[cfg(test)]
4+
mod tests;
5+
6+
pub(crate) use commands::{
7+
AcpCommand, AgentCommand, AgentKind, ChannelCommand, Cli, Command, ConfigCommand,
8+
DaemonCommand, HarnessCommand, ReleaseCommand, SkillsCommand,
9+
};
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
mod acp;
2+
mod agent;
3+
mod channel;
4+
mod config;
5+
mod daemon;
6+
mod harness;
7+
mod release;
8+
mod skills;
9+
10+
use clap::Parser;
11+
use std::path::PathBuf;
12+
13+
use crate::onboard::OnboardStarter;
14+
15+
pub(crate) use acp::AcpCommand;
16+
pub(crate) use agent::{AgentCommand, AgentKind};
17+
pub(crate) use channel::ChannelCommand;
18+
pub(crate) use config::ConfigCommand;
19+
pub(crate) use daemon::DaemonCommand;
20+
pub(crate) use harness::HarnessCommand;
21+
pub(crate) use release::ReleaseCommand;
22+
pub(crate) use skills::SkillsCommand;
23+
24+
#[derive(Debug, Parser)]
25+
#[command(name = "loopforge")]
26+
#[command(
27+
about = "LoopForge: long-running agent operating system",
28+
long_about = None
29+
)]
30+
pub(crate) struct Cli {
31+
#[command(subcommand)]
32+
pub(crate) command: Command,
33+
}
34+
35+
#[derive(Debug, clap::Subcommand)]
36+
pub(crate) enum Command {
37+
/// Initialize ~/.loopforge (config + database)
38+
Init,
39+
/// One-command onboarding check (init + config + doctor + optional first task)
40+
Onboard {
41+
/// Workspace directory for the first verification run
42+
#[arg(long, default_value = "loopforge-onboard-demo")]
43+
workspace: PathBuf,
44+
/// Optional explicit prompt for the first verification run
45+
#[arg(long)]
46+
prompt: Option<String>,
47+
/// Starter profile used when `--prompt` is not provided
48+
#[arg(long, value_enum, default_value_t = OnboardStarter::Hello)]
49+
starter: OnboardStarter,
50+
/// Skip running the first agent task and only run setup checks
51+
#[arg(long)]
52+
skip_agent: bool,
53+
/// Timeout for doctor probes (milliseconds)
54+
#[arg(long, default_value_t = 1500)]
55+
timeout_ms: u64,
56+
},
57+
/// Diagnose common setup issues (config, providers, browser, tooling)
58+
Doctor {
59+
/// Print JSON output (machine-readable)
60+
#[arg(long)]
61+
json: bool,
62+
/// Exit non-zero if any warnings are detected
63+
#[arg(long)]
64+
strict: bool,
65+
/// Timeout for network probes (milliseconds)
66+
#[arg(long, default_value_t = 1500)]
67+
timeout_ms: u64,
68+
},
69+
/// Run an agent session (LLM + tools + memory)
70+
Agent {
71+
#[command(subcommand)]
72+
command: AgentCommand,
73+
},
74+
/// Outbound channels (outbox + dispatcher)
75+
Channel {
76+
#[command(subcommand)]
77+
command: ChannelCommand,
78+
},
79+
/// ACP event/checkpoint inspection helpers
80+
Acp {
81+
#[command(subcommand)]
82+
command: AcpCommand,
83+
},
84+
/// Config helpers
85+
Config {
86+
#[command(subcommand)]
87+
command: ConfigCommand,
88+
},
89+
/// Skills discovery, doctor and execution helpers
90+
Skills {
91+
#[command(subcommand)]
92+
command: SkillsCommand,
93+
},
94+
/// Long-running harness helpers (initializer + sessions)
95+
Harness {
96+
#[command(subcommand)]
97+
command: HarnessCommand,
98+
},
99+
/// Run LoopForge daemon (HTTP API)
100+
Daemon {
101+
#[command(subcommand)]
102+
command: DaemonCommand,
103+
},
104+
/// Release assistants (metadata + preflight checks)
105+
Release {
106+
#[command(subcommand)]
107+
command: ReleaseCommand,
108+
},
109+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#[derive(Debug, clap::Subcommand)]
2+
pub(crate) enum AcpCommand {
3+
/// List recent ACP events
4+
Events {
5+
/// Optional session id filter
6+
#[arg(long)]
7+
session: Option<String>,
8+
/// Max events to print
9+
#[arg(long, default_value_t = 100)]
10+
limit: usize,
11+
/// Print JSON output (machine-readable)
12+
#[arg(long)]
13+
json: bool,
14+
},
15+
/// Show ACP delivery checkpoints for one session
16+
Checkpoints {
17+
/// Session id
18+
#[arg(long)]
19+
session: String,
20+
/// Print JSON output (machine-readable)
21+
#[arg(long)]
22+
json: bool,
23+
},
24+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use std::path::PathBuf;
2+
3+
#[derive(Debug, clap::Subcommand)]
4+
pub(crate) enum AgentCommand {
5+
/// Run a single agent session in a workspace
6+
Run {
7+
/// Workspace root directory (tools are sandboxed to this path)
8+
#[arg(long)]
9+
workspace: PathBuf,
10+
/// User instruction for this run
11+
#[arg(long)]
12+
prompt: String,
13+
/// Optional system prompt (string)
14+
#[arg(long)]
15+
system: Option<String>,
16+
/// Optional session id (generated if omitted)
17+
#[arg(long)]
18+
session: Option<String>,
19+
/// Task kind for model routing
20+
#[arg(long, value_enum, default_value_t = AgentKind::Coding)]
21+
kind: AgentKind,
22+
/// Comma-separated allowed tool names for this session (session-level whitelist)
23+
#[arg(long, value_delimiter = ',')]
24+
allowed_tools: Vec<String>,
25+
},
26+
}
27+
28+
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
29+
pub(crate) enum AgentKind {
30+
Planning,
31+
Coding,
32+
Summary,
33+
}
34+
35+
impl From<AgentKind> for rexos::router::TaskKind {
36+
fn from(value: AgentKind) -> Self {
37+
match value {
38+
AgentKind::Planning => rexos::router::TaskKind::Planning,
39+
AgentKind::Coding => rexos::router::TaskKind::Coding,
40+
AgentKind::Summary => rexos::router::TaskKind::Summary,
41+
}
42+
}
43+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#[derive(Debug, clap::Subcommand)]
2+
pub(crate) enum ChannelCommand {
3+
/// Drain queued outbox messages once
4+
Drain {
5+
/// Max messages to attempt in one run
6+
#[arg(long, default_value_t = 50)]
7+
limit: usize,
8+
},
9+
/// Run a long-lived worker that periodically drains the outbox
10+
Worker {
11+
/// Seconds between drain attempts
12+
#[arg(long, default_value_t = 5)]
13+
interval_secs: u64,
14+
/// Max messages to attempt per drain cycle
15+
#[arg(long, default_value_t = 50)]
16+
limit: usize,
17+
},
18+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[derive(Debug, clap::Subcommand)]
2+
pub(crate) enum ConfigCommand {
3+
/// Validate ~/.loopforge/config.toml and exit non-zero when invalid
4+
Validate {
5+
/// Print JSON output (machine-readable)
6+
#[arg(long)]
7+
json: bool,
8+
},
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[derive(Debug, clap::Subcommand)]
2+
pub(crate) enum DaemonCommand {
3+
/// Start the daemon HTTP server
4+
Start {
5+
/// Listen address, e.g. 127.0.0.1:8787
6+
#[arg(long, default_value = "127.0.0.1:8787")]
7+
addr: String,
8+
},
9+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use std::path::PathBuf;
2+
3+
#[derive(Debug, clap::Subcommand)]
4+
pub(crate) enum HarnessCommand {
5+
/// Initialize a workspace directory for long-running agent sessions
6+
Init {
7+
dir: PathBuf,
8+
/// Optional initializer prompt (generates a comprehensive features.json)
9+
#[arg(long)]
10+
prompt: Option<String>,
11+
/// Override session id (default: persisted per-workspace)
12+
#[arg(long)]
13+
session: Option<String>,
14+
},
15+
/// Run a harness session (preflight + agent run)
16+
Run {
17+
dir: PathBuf,
18+
/// User instruction for this session (if omitted, only runs preflight)
19+
#[arg(long)]
20+
prompt: Option<String>,
21+
/// Override session id (default: derived UUID per run)
22+
#[arg(long)]
23+
session: Option<String>,
24+
/// Max attempts when init.sh fails (default 3)
25+
#[arg(long, default_value_t = 3)]
26+
max_attempts: usize,
27+
},
28+
}

0 commit comments

Comments
 (0)