Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Mac 客户端(v1 即将发布):拖入 Applications → 首启完成 onboar
| [docs/DEVELOPMENT_PLAN.md](docs/DEVELOPMENT_PLAN.md) | 整体开发方案 v0.5(1500+ 行 / §3 模块 / §6 里程碑) |
| [docs/VISUAL_DESIGN.html](docs/VISUAL_DESIGN.html) | 视觉设计 v0.4(11 屏 mockup) |
| [docs/security-model.md](docs/security-model.md) | 威胁模型 + 防御层 + 攻击向量测试 + 已知缺口 |
| [docs/design/session-format-v1.md](docs/design/session-format-v1.md) | 统一 session JSONL、旧格式迁移与 writer ownership |
| [docs/design/sandbox-plan-worktree.md](docs/design/sandbox-plan-worktree.md) | sandbox × plan mode × worktree 关系矩阵 |
| [docs/design/plugin-security.md](docs/design/plugin-security.md) | plugin 信任 ladder + sandbox 子进程 |
| [docs/design/effort-levels.md](docs/design/effort-levels.md) | 5 档 effort 到 DeepSeek API 参数映射 |
Expand Down
1 change: 1 addition & 0 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"start": "node ./dist/cli.js"
},
"dependencies": {
"@deepcode/app-server": "workspace:*",
"@deepcode/core": "workspace:*",
"@deepcode/shared-ui": "workspace:*"
},
Expand Down
9 changes: 9 additions & 0 deletions apps/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// M2: onboarding + REPL + slash commands + settings + permissions matcher.

import { CredentialsStore, VERSION, redact } from '@deepcode/core';
import { runAppServer } from '@deepcode/app-server';
import { homedir } from 'node:os';
import { resolve } from 'node:path';
import { runHeadless } from './headless.js';
Expand Down Expand Up @@ -80,6 +81,14 @@ async function main(): Promise<number> {
errOutput: process.stderr,
});
}
if (args.positional[0] === 'app-server') {
await runAppServer({
input: process.stdin,
output: process.stdout,
home: process.env.DEEPCODE_HOME ?? resolve(homedir(), '.deepcode'),
});
return 0;
}
if (args.positional[0] === 'trust') {
return runTrustCommand(args.positional.slice(1), {
cwd: process.cwd(),
Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const SUBCOMMANDS = [
'doctor',
'upgrade',
'mcp',
'app-server',
'trust',
'plugins',
'skills',
Expand Down
22 changes: 13 additions & 9 deletions apps/cli/src/headless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
EFFORT_PARAMS,
HookDispatcher,
ReadTool,
RuntimeHost,
SessionManager,
ToolRegistry,
WebFetchTool,
Expand All @@ -39,7 +40,6 @@ import {
loadSkills,
makeSkillTool,
resolveCredentials,
runAgent,
wirePlugins,
collectPluginContributions,
type AgentEvent,
Expand Down Expand Up @@ -271,25 +271,28 @@ export async function runHeadless(opts: HeadlessOpts): Promise<number> {
}
let exitCode = 0;
try {
const result = await runAgent({
const runtime = new RuntimeHost({
provider,
tools,
cwd,
mode,
permissions: settings.permissions,
hooks,
pluginDirs: pluginContrib.dirs,
autoMode: settings.autoMode,
sandboxConfig: settings.sandbox,
});
const result = await runtime.run({
systemPrompt,
userMessage,
history: [],
model,
maxTokens,
temperature,
maxTurns,
cwd,
signal: ctrl.signal,
session: { manager: sessions, id: session.id },
mode,
permissions: settings.permissions,
hooks,
pluginDirs: pluginContrib.dirs,
autoCompact: { contextWindow: contextWindowFor(model), threshold: 0.8 },
autoMode: settings.autoMode,
sandboxConfig: settings.sandbox,
// In headless mode there's no human to ask: auto-deny anything that
// would normally need approval. Users wanting auto-yes should pass
// --mode dontAsk or --mode bypassPermissions (gated by trust).
Expand Down Expand Up @@ -441,6 +444,7 @@ function formatEventText(out: Writable, e: AgentEvent): void {
return;
case 'usage':
case 'thinking_delta':
case 'model_step_complete':
case 'turn_complete':
return;
}
Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/parse-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ USAGE
deepcode cron <cmd> Scheduled tasks: install/uninstall/list/status
deepcode scheduler run Run due scheduled jobs (invoked by launchd)
deepcode mcp serve Expose DeepCode tools as an MCP server (stdio)
deepcode app-server Run the experimental lifecycle server (JSONL stdio)
deepcode trust [--plan-only] Trust this directory's project config (hooks/MCP/...)
deepcode plugins list [--json] List installed plugins
deepcode plugins install <spec> Install a plugin (gh:owner/repo | name@npm | ./path)
Expand Down
58 changes: 29 additions & 29 deletions apps/cli/src/repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
EFFORT_PARAMS,
HookDispatcher,
ReadTool,
RuntimeHost,
SessionManager,
TaskManager,
ToolRegistry,
Expand Down Expand Up @@ -37,7 +38,6 @@ import {
contextWindowFor,
makeSkillTool,
resolveCredentials,
runAgent,
settingsPaths,
wirePlugins,
collectPluginContributions,
Expand Down Expand Up @@ -429,6 +429,17 @@ export async function startRepl(opts: ReplOpts): Promise<number> {
}

let history: StoredMessage[] = resolved.seededHistory;
const runtime = new RuntimeHost({
provider,
tools,
cwd,
mode,
permissions: settings.permissions,
hooks,
pluginDirs: pluginContrib.dirs,
autoMode: settings.autoMode,
sandboxConfig: settings.sandbox,
});
const ctx: SessionContext = {
cwd,
model,
Expand Down Expand Up @@ -471,25 +482,20 @@ export async function startRepl(opts: ReplOpts): Promise<number> {
// reading ctx.model/ctx.mode live so /model and /mode switches are honored.
const tasks = new TaskManager((spec) => {
const ac = new AbortController();
const done = runAgent({
provider,
tools,
systemPrompt,
userMessage: spec.prompt,
model: ctx.model,
maxTokens,
temperature,
cwd: ctx.cwd,
signal: ac.signal,
mode: ctx.mode as Mode,
permissions: settings.permissions,
hooks,
pluginDirs: pluginContrib.dirs,
sandboxConfig: settings.sandbox,
autoMode: settings.autoMode,
subAgentDepth: 1,
systemReminders: false,
}).then((r) => assistantText(r.history));
const done = runtime
.run({
systemPrompt,
userMessage: spec.prompt,
model: ctx.model,
maxTokens,
temperature,
cwd: ctx.cwd,
signal: ac.signal,
modeOverride: ctx.mode as Mode,
subAgentDepth: 1,
systemReminders: false,
})
.then((r) => assistantText(r.history));
return { done, abort: () => ac.abort() };
});
ctx.tasks = tasks;
Expand Down Expand Up @@ -649,9 +655,7 @@ export async function startRepl(opts: ReplOpts): Promise<number> {
}

// Otherwise: send to agent (with mode/permission/hooks gating from M3b)
const result = await runAgent({
provider,
tools,
const result = await runtime.run({
systemPrompt,
userMessage: userInput,
history,
Expand All @@ -663,13 +667,8 @@ export async function startRepl(opts: ReplOpts): Promise<number> {
// ctx.sessionId (not the launch `session.id`) so a live `/resume <id>`
// switch redirects new messages to the resumed session.
session: { manager: sessions, id: ctx.sessionId },
mode: ctx.mode as Mode,
permissions: settings.permissions,
hooks,
pluginDirs: pluginContrib.dirs,
modeOverride: ctx.mode as Mode,
autoCompact: { contextWindow: contextWindowFor(ctx.model), threshold: 0.8 },
autoMode: settings.autoMode,
sandboxConfig: settings.sandbox,
// Session-scoped manager: the agent's TaskCreate calls land here too, so
// background tasks persist across turns and show up in /tasks.
taskManager: tasks,
Expand Down Expand Up @@ -762,6 +761,7 @@ function formatEvent(out: Writable, e: AgentEvent): void {
else out.write(` ✓ ${truncate(e.result.content, 200)}\n`);
return;
case 'usage':
case 'model_step_complete':
return;
case 'error':
out.write(`\n ✕ ${e.error}\n`);
Expand Down
6 changes: 5 additions & 1 deletion apps/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"],
"references": [{ "path": "../../packages/core" }, { "path": "../../packages/shared-ui" }]
"references": [
{ "path": "../../packages/core" },
{ "path": "../../packages/shared-ui" },
{ "path": "../server" }
]
}
1 change: 1 addition & 0 deletions apps/desktop/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ sha2 = "0.10"
thiserror = "1"
tokio = { version = "1", features = ["fs", "rt-multi-thread", "macros", "sync", "time", "process"] }
dirs = "5"
libc = "0.2"

[profile.release]
panic = "abort"
Expand Down
Loading
Loading