c0de-agent 0.0.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/cli/commands/acp.d.ts +19 -0
- package/dist/cli/commands/acp.js +50 -0
- package/dist/cli/commands/chat.d.ts +13 -0
- package/dist/cli/commands/chat.js +26 -0
- package/dist/cli/commands/config.d.ts +17 -0
- package/dist/cli/commands/config.js +77 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +14 -0
- package/dist/cli/commands/plugin.d.ts +11 -0
- package/dist/cli/commands/plugin.js +31 -0
- package/dist/cli/commands/serve.d.ts +18 -0
- package/dist/cli/commands/serve.js +35 -0
- package/dist/cli/commands/update.d.ts +24 -0
- package/dist/cli/commands/update.js +40 -0
- package/dist/cli/deps.d.ts +19 -0
- package/dist/cli/deps.js +57 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +149 -0
- package/dist/cli/modes/acp.d.ts +18 -0
- package/dist/cli/modes/acp.js +57 -0
- package/dist/cli/modes/print.d.ts +16 -0
- package/dist/cli/modes/print.js +30 -0
- package/dist/cli/parser.d.ts +19 -0
- package/dist/cli/parser.js +28 -0
- package/dist/cli/utils/output.d.ts +11 -0
- package/dist/cli/utils/output.js +23 -0
- package/dist/cli/utils/prompt.d.ts +12 -0
- package/dist/cli/utils/prompt.js +18 -0
- package/dist/core/agent.d.ts +12 -0
- package/dist/core/agent.js +95 -0
- package/dist/core/agents/builtin.d.ts +6 -0
- package/dist/core/agents/builtin.js +76 -0
- package/dist/core/agents/discovery.d.ts +6 -0
- package/dist/core/agents/discovery.js +96 -0
- package/dist/core/agents/index.d.ts +6 -0
- package/dist/core/agents/index.js +4 -0
- package/dist/core/agents/parallel.d.ts +13 -0
- package/dist/core/agents/parallel.js +37 -0
- package/dist/core/agents/registry.d.ts +4 -0
- package/dist/core/agents/registry.js +23 -0
- package/dist/core/agents/types.d.ts +37 -0
- package/dist/core/agents/types.js +1 -0
- package/dist/core/compact.d.ts +11 -0
- package/dist/core/compact.js +31 -0
- package/dist/core/config.d.ts +7 -0
- package/dist/core/config.js +84 -0
- package/dist/core/context.d.ts +23 -0
- package/dist/core/context.js +93 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +11 -0
- package/dist/core/loop.d.ts +25 -0
- package/dist/core/loop.js +651 -0
- package/dist/core/metrics.d.ts +27 -0
- package/dist/core/metrics.js +94 -0
- package/dist/core/prompt-registry.d.ts +21 -0
- package/dist/core/prompt-registry.js +200 -0
- package/dist/core/prompt.d.ts +11 -0
- package/dist/core/prompt.js +13 -0
- package/dist/core/secret.d.ts +12 -0
- package/dist/core/secret.js +51 -0
- package/dist/core/slash.d.ts +15 -0
- package/dist/core/slash.js +114 -0
- package/dist/core/steering.d.ts +8 -0
- package/dist/core/steering.js +15 -0
- package/dist/core/title.d.ts +42 -0
- package/dist/core/title.js +115 -0
- package/dist/core/tool-exec.d.ts +20 -0
- package/dist/core/tool-exec.js +64 -0
- package/dist/core/types.d.ts +95 -0
- package/dist/core/types.js +1 -0
- package/dist/core/worktree.d.ts +24 -0
- package/dist/core/worktree.js +68 -0
- package/dist/dap/index.d.ts +6 -0
- package/dist/dap/index.js +4 -0
- package/dist/dap/protocol.d.ts +40 -0
- package/dist/dap/protocol.js +132 -0
- package/dist/dap/session.d.ts +23 -0
- package/dist/dap/session.js +130 -0
- package/dist/dap/transport.d.ts +8 -0
- package/dist/dap/transport.js +30 -0
- package/dist/dap/types.d.ts +50 -0
- package/dist/dap/types.js +2 -0
- package/dist/db/client.d.ts +22 -0
- package/dist/db/client.js +39 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.js +4 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.js +15 -0
- package/dist/db/schema.d.ts +965 -0
- package/dist/db/schema.js +112 -0
- package/dist/db/types.d.ts +11 -0
- package/dist/db/types.js +1 -0
- package/dist/llm/index.d.ts +13 -0
- package/dist/llm/index.js +8 -0
- package/dist/llm/protocols/openai-compat.d.ts +139 -0
- package/dist/llm/protocols/openai-compat.js +214 -0
- package/dist/llm/protocols/utils/index.d.ts +2 -0
- package/dist/llm/protocols/utils/index.js +2 -0
- package/dist/llm/protocols/utils/lifecycle.d.ts +23 -0
- package/dist/llm/protocols/utils/lifecycle.js +46 -0
- package/dist/llm/protocols/utils/tool-stream.d.ts +46 -0
- package/dist/llm/protocols/utils/tool-stream.js +94 -0
- package/dist/llm/provider-error.d.ts +5 -0
- package/dist/llm/provider-error.js +33 -0
- package/dist/llm/provider.d.ts +32 -0
- package/dist/llm/provider.js +191 -0
- package/dist/llm/registry.d.ts +44 -0
- package/dist/llm/registry.js +107 -0
- package/dist/llm/retry.d.ts +37 -0
- package/dist/llm/retry.js +82 -0
- package/dist/llm/routing.d.ts +36 -0
- package/dist/llm/routing.js +53 -0
- package/dist/llm/schema/errors.d.ts +88 -0
- package/dist/llm/schema/errors.js +33 -0
- package/dist/llm/schema/events.d.ts +135 -0
- package/dist/llm/schema/events.js +35 -0
- package/dist/llm/schema/ids.d.ts +22 -0
- package/dist/llm/schema/ids.js +3 -0
- package/dist/llm/schema/index.d.ts +5 -0
- package/dist/llm/schema/index.js +5 -0
- package/dist/llm/schema/messages.d.ts +97 -0
- package/dist/llm/schema/messages.js +18 -0
- package/dist/llm/schema/options.d.ts +54 -0
- package/dist/llm/schema/options.js +54 -0
- package/dist/llm/token.d.ts +2 -0
- package/dist/llm/token.js +13 -0
- package/dist/llm/transport.d.ts +31 -0
- package/dist/llm/transport.js +165 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +3 -0
- package/dist/plugins/builtin.d.ts +6 -0
- package/dist/plugins/builtin.js +54 -0
- package/dist/plugins/hooks.d.ts +3 -0
- package/dist/plugins/hooks.js +79 -0
- package/dist/plugins/index.d.ts +9 -0
- package/dist/plugins/index.js +8 -0
- package/dist/plugins/init.d.ts +23 -0
- package/dist/plugins/init.js +30 -0
- package/dist/plugins/lifecycle.d.ts +6 -0
- package/dist/plugins/lifecycle.js +74 -0
- package/dist/plugins/loader.d.ts +16 -0
- package/dist/plugins/loader.js +68 -0
- package/dist/plugins/logger.d.ts +4 -0
- package/dist/plugins/logger.js +31 -0
- package/dist/plugins/registry.d.ts +7 -0
- package/dist/plugins/registry.js +24 -0
- package/dist/plugins/types.d.ts +113 -0
- package/dist/plugins/types.js +1 -0
- package/dist/project/detect.d.ts +4 -0
- package/dist/project/detect.js +131 -0
- package/dist/project/index.d.ts +4 -0
- package/dist/project/index.js +2 -0
- package/dist/project/project.d.ts +23 -0
- package/dist/project/project.js +87 -0
- package/dist/project/resolve.d.ts +8 -0
- package/dist/project/resolve.js +81 -0
- package/dist/server/agent-manager.d.ts +32 -0
- package/dist/server/agent-manager.js +54 -0
- package/dist/server/app.d.ts +5 -0
- package/dist/server/app.js +75 -0
- package/dist/server/context.d.ts +20 -0
- package/dist/server/context.js +47 -0
- package/dist/server/dev.d.ts +11 -0
- package/dist/server/dev.js +83 -0
- package/dist/server/index.d.ts +11 -0
- package/dist/server/index.js +7 -0
- package/dist/server/middleware/auth.d.ts +15 -0
- package/dist/server/middleware/auth.js +29 -0
- package/dist/server/middleware/cors.d.ts +16 -0
- package/dist/server/middleware/cors.js +44 -0
- package/dist/server/middleware/error.d.ts +15 -0
- package/dist/server/middleware/error.js +11 -0
- package/dist/server/permission/interactive.d.ts +24 -0
- package/dist/server/permission/interactive.js +56 -0
- package/dist/server/permission/store.d.ts +30 -0
- package/dist/server/permission/store.js +47 -0
- package/dist/server/routes/agent.d.ts +4 -0
- package/dist/server/routes/agent.js +19 -0
- package/dist/server/routes/catalog.d.ts +42 -0
- package/dist/server/routes/catalog.js +194 -0
- package/dist/server/routes/chat.d.ts +8 -0
- package/dist/server/routes/chat.js +282 -0
- package/dist/server/routes/commands.d.ts +5 -0
- package/dist/server/routes/commands.js +17 -0
- package/dist/server/routes/config.d.ts +4 -0
- package/dist/server/routes/config.js +27 -0
- package/dist/server/routes/files.d.ts +4 -0
- package/dist/server/routes/files.js +183 -0
- package/dist/server/routes/filesystem.d.ts +29 -0
- package/dist/server/routes/filesystem.js +108 -0
- package/dist/server/routes/health.d.ts +3 -0
- package/dist/server/routes/health.js +13 -0
- package/dist/server/routes/permissions.d.ts +5 -0
- package/dist/server/routes/permissions.js +23 -0
- package/dist/server/routes/project.d.ts +4 -0
- package/dist/server/routes/project.js +51 -0
- package/dist/server/routes/provider.d.ts +16 -0
- package/dist/server/routes/provider.js +66 -0
- package/dist/server/routes/session.d.ts +4 -0
- package/dist/server/routes/session.js +130 -0
- package/dist/server/routes/tool.d.ts +4 -0
- package/dist/server/routes/tool.js +28 -0
- package/dist/server/routes/update.d.ts +14 -0
- package/dist/server/routes/update.js +49 -0
- package/dist/server/server.d.ts +43 -0
- package/dist/server/server.js +197 -0
- package/dist/server/types.d.ts +73 -0
- package/dist/server/types.js +2 -0
- package/dist/server/util/safe-path.d.ts +7 -0
- package/dist/server/util/safe-path.js +7 -0
- package/dist/session/archive.d.ts +15 -0
- package/dist/session/archive.js +129 -0
- package/dist/session/branch.d.ts +9 -0
- package/dist/session/branch.js +63 -0
- package/dist/session/compaction.d.ts +27 -0
- package/dist/session/compaction.js +192 -0
- package/dist/session/context.d.ts +16 -0
- package/dist/session/context.js +173 -0
- package/dist/session/index.d.ts +10 -0
- package/dist/session/index.js +10 -0
- package/dist/session/message.d.ts +22 -0
- package/dist/session/message.js +145 -0
- package/dist/session/session.d.ts +37 -0
- package/dist/session/session.js +144 -0
- package/dist/session/snapshot.d.ts +11 -0
- package/dist/session/snapshot.js +60 -0
- package/dist/session/squash.d.ts +9 -0
- package/dist/session/squash.js +88 -0
- package/dist/session/token.d.ts +10 -0
- package/dist/session/token.js +33 -0
- package/dist/session/types.d.ts +122 -0
- package/dist/session/types.js +1 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/types/agent.d.ts +202 -0
- package/dist/shared/types/agent.js +1 -0
- package/dist/shared/types/base.d.ts +32 -0
- package/dist/shared/types/base.js +1 -0
- package/dist/shared/types/config.d.ts +104 -0
- package/dist/shared/types/config.js +1 -0
- package/dist/shared/types/index.d.ts +6 -0
- package/dist/shared/types/index.js +1 -0
- package/dist/shared/types/llm.d.ts +122 -0
- package/dist/shared/types/llm.js +1 -0
- package/dist/shared/types/message.d.ts +71 -0
- package/dist/shared/types/message.js +1 -0
- package/dist/shared/types/tool.d.ts +134 -0
- package/dist/shared/types/tool.js +1 -0
- package/dist/shared/utils/path.d.ts +15 -0
- package/dist/shared/utils/path.js +23 -0
- package/dist/shared/utils.d.ts +5 -0
- package/dist/shared/utils.js +10 -0
- package/dist/tools/builtin/bash.d.ts +12 -0
- package/dist/tools/builtin/bash.js +121 -0
- package/dist/tools/builtin/dap.d.ts +23 -0
- package/dist/tools/builtin/dap.js +231 -0
- package/dist/tools/builtin/edit.d.ts +12 -0
- package/dist/tools/builtin/edit.js +151 -0
- package/dist/tools/builtin/glob.d.ts +11 -0
- package/dist/tools/builtin/glob.js +120 -0
- package/dist/tools/builtin/grep.d.ts +6 -0
- package/dist/tools/builtin/grep.js +141 -0
- package/dist/tools/builtin/read.d.ts +6 -0
- package/dist/tools/builtin/read.js +73 -0
- package/dist/tools/builtin/resolvers.d.ts +12 -0
- package/dist/tools/builtin/resolvers.js +79 -0
- package/dist/tools/builtin/task.d.ts +9 -0
- package/dist/tools/builtin/task.js +100 -0
- package/dist/tools/builtin/write.d.ts +6 -0
- package/dist/tools/builtin/write.js +36 -0
- package/dist/tools/builtin/yield.d.ts +9 -0
- package/dist/tools/builtin/yield.js +40 -0
- package/dist/tools/executor.d.ts +9 -0
- package/dist/tools/executor.js +54 -0
- package/dist/tools/hashline/index.d.ts +2 -0
- package/dist/tools/hashline/index.js +3 -0
- package/dist/tools/hashline/patch.d.ts +48 -0
- package/dist/tools/hashline/patch.js +201 -0
- package/dist/tools/index.d.ts +30 -0
- package/dist/tools/index.js +55 -0
- package/dist/tools/permission.d.ts +13 -0
- package/dist/tools/permission.js +39 -0
- package/dist/tools/registry.d.ts +15 -0
- package/dist/tools/registry.js +54 -0
- package/dist/tools/resolver.d.ts +15 -0
- package/dist/tools/resolver.js +47 -0
- package/dist/tools/truncate.d.ts +8 -0
- package/dist/tools/truncate.js +50 -0
- package/dist/tools/types.d.ts +101 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/validate.d.ts +8 -0
- package/dist/tools/validate.js +130 -0
- package/dist/tools/websearch/fetch.d.ts +11 -0
- package/dist/tools/websearch/fetch.js +21 -0
- package/dist/tools/websearch/index.d.ts +19 -0
- package/dist/tools/websearch/index.js +78 -0
- package/dist/tools/websearch/providers/brave.d.ts +5 -0
- package/dist/tools/websearch/providers/brave.js +53 -0
- package/dist/tools/websearch/providers/duckduckgo.d.ts +3 -0
- package/dist/tools/websearch/providers/duckduckgo.js +75 -0
- package/dist/tools/websearch/providers/tavily.d.ts +11 -0
- package/dist/tools/websearch/providers/tavily.js +89 -0
- package/dist/tools/websearch/types.d.ts +51 -0
- package/dist/tools/websearch/types.js +18 -0
- package/dist/tools/websearch/websearch.d.ts +10 -0
- package/dist/tools/websearch/websearch.js +48 -0
- package/dist/update/index.d.ts +10 -0
- package/dist/update/index.js +6 -0
- package/dist/update/ipc.d.ts +15 -0
- package/dist/update/ipc.js +41 -0
- package/dist/update/scheduler.d.ts +34 -0
- package/dist/update/scheduler.js +57 -0
- package/dist/update/snapshot.d.ts +39 -0
- package/dist/update/snapshot.js +99 -0
- package/dist/update/updater.d.ts +48 -0
- package/dist/update/updater.js +83 -0
- package/dist/update/version.d.ts +18 -0
- package/dist/update/version.js +49 -0
- package/drizzle/0000_magical_nightshade.sql +55 -0
- package/drizzle/0001_chemical_doctor_faustus.sql +13 -0
- package/drizzle/0002_amusing_micromacro.sql +12 -0
- package/drizzle/0003_regular_purifiers.sql +2 -0
- package/drizzle/meta/0000_snapshot.json +448 -0
- package/drizzle/meta/0001_snapshot.json +539 -0
- package/drizzle/meta/0002_snapshot.json +633 -0
- package/drizzle/meta/0003_snapshot.json +645 -0
- package/drizzle/meta/_journal.json +34 -0
- package/package.json +100 -8
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { AgentConfig } from '../shared/types/agent.js';
|
|
2
|
+
import type { Config } from '../shared/types/config.js';
|
|
3
|
+
import type { ChatMessage, ChatRequest, ProviderConfig, StreamChunk } from '../shared/types/llm.js';
|
|
4
|
+
import type { Message, Session } from '../shared/types/message.js';
|
|
5
|
+
import type { ToolContext, ToolDef, ToolResult } from '../shared/types/tool.js';
|
|
6
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
7
|
+
type Logger = {
|
|
8
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
9
|
+
info: (msg: string, ...args: unknown[]) => void;
|
|
10
|
+
warn: (msg: string, ...args: unknown[]) => void;
|
|
11
|
+
error: (msg: string, ...args: unknown[]) => void;
|
|
12
|
+
};
|
|
13
|
+
/** Unified event map. `domain:before` = chain (can modify/abort); `domain:after` = broadcast. */
|
|
14
|
+
type HookMap = {
|
|
15
|
+
'agent:start': {
|
|
16
|
+
config: AgentConfig;
|
|
17
|
+
};
|
|
18
|
+
'agent:end': Record<string, never>;
|
|
19
|
+
'tool:before': {
|
|
20
|
+
tool: string;
|
|
21
|
+
input: unknown;
|
|
22
|
+
ctx: ToolContext;
|
|
23
|
+
};
|
|
24
|
+
'tool:after': {
|
|
25
|
+
tool: string;
|
|
26
|
+
input: unknown;
|
|
27
|
+
result: ToolResult;
|
|
28
|
+
ctx: ToolContext;
|
|
29
|
+
};
|
|
30
|
+
'provider:before': {
|
|
31
|
+
request: ChatRequest;
|
|
32
|
+
};
|
|
33
|
+
'provider:after': {
|
|
34
|
+
request: ChatRequest;
|
|
35
|
+
chunks: StreamChunk[];
|
|
36
|
+
};
|
|
37
|
+
'message:before': {
|
|
38
|
+
messages: ChatMessage[];
|
|
39
|
+
};
|
|
40
|
+
'message:after': {
|
|
41
|
+
message: Message;
|
|
42
|
+
};
|
|
43
|
+
'session:create': {
|
|
44
|
+
session: Session;
|
|
45
|
+
};
|
|
46
|
+
'session:fork': {
|
|
47
|
+
source: Session;
|
|
48
|
+
fork: Session;
|
|
49
|
+
};
|
|
50
|
+
'session:compact': {
|
|
51
|
+
before: number;
|
|
52
|
+
after: number;
|
|
53
|
+
};
|
|
54
|
+
'config:resolve': {
|
|
55
|
+
config: Config;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/** Hook handler. Returns T (possibly modified) or false (abort). void = passthrough. */
|
|
59
|
+
type HookHandler<T> = (data: T) => T | false | void | Promise<T | false | void>;
|
|
60
|
+
/** Options for createHookRunner. */
|
|
61
|
+
type HookRunnerOptions = {
|
|
62
|
+
/** Per-handler timeout in ms. Default 5000. */
|
|
63
|
+
timeout?: number;
|
|
64
|
+
/** Logger for error/timeout warnings. Default: console. */
|
|
65
|
+
logger?: Logger;
|
|
66
|
+
};
|
|
67
|
+
/** Mutable event registry. Functions are context-first (runner as hidden state). */
|
|
68
|
+
type HookRunner = {
|
|
69
|
+
on: <K extends keyof HookMap>(event: K, handler: HookHandler<HookMap[K]>, priority?: number) => void;
|
|
70
|
+
off: <K extends keyof HookMap>(event: K, handler: HookHandler<HookMap[K]>) => void;
|
|
71
|
+
runHooks: <K extends keyof HookMap>(event: K, data: HookMap[K]) => Promise<HookMap[K] | false>;
|
|
72
|
+
fireHooks: <K extends keyof HookMap>(event: K, data: HookMap[K]) => Promise<void>;
|
|
73
|
+
dispose: () => void;
|
|
74
|
+
};
|
|
75
|
+
/** A process-level plugin. `setup` is called during activation; `dispose` during deactivation. */
|
|
76
|
+
type Plugin = {
|
|
77
|
+
name: string;
|
|
78
|
+
version: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
setup: (ctx: PluginContext) => void | Promise<void>;
|
|
81
|
+
dispose?: () => void | Promise<void>;
|
|
82
|
+
};
|
|
83
|
+
/** Context passed to plugin.setup(). Delegates to real registries. */
|
|
84
|
+
type PluginContext = {
|
|
85
|
+
registerTool: (tool: ToolDef) => void;
|
|
86
|
+
registerProvider: (provider: ProviderConfig) => void;
|
|
87
|
+
on: HookRunner['on'];
|
|
88
|
+
off: HookRunner['off'];
|
|
89
|
+
getConfig: () => Config;
|
|
90
|
+
getLogger: (name: string) => Logger;
|
|
91
|
+
onDispose: (handler: () => void | Promise<void>) => void;
|
|
92
|
+
};
|
|
93
|
+
/** Runtime status of a loaded plugin. */
|
|
94
|
+
type PluginStatus = 'loaded' | 'active' | 'error' | 'inactive';
|
|
95
|
+
/** Internal record stored in PluginRegistry. */
|
|
96
|
+
type PluginRecord = {
|
|
97
|
+
plugin: Plugin;
|
|
98
|
+
status: PluginStatus;
|
|
99
|
+
error?: string;
|
|
100
|
+
disposeHandlers: (() => void | Promise<void>)[];
|
|
101
|
+
};
|
|
102
|
+
/** Mutable plugin registry. */
|
|
103
|
+
type PluginRegistry = {
|
|
104
|
+
plugins: Map<string, PluginRecord>;
|
|
105
|
+
hookRunner: HookRunner;
|
|
106
|
+
};
|
|
107
|
+
/** Services needed to create PluginContext during activation. */
|
|
108
|
+
type PluginServices = {
|
|
109
|
+
config: Config;
|
|
110
|
+
toolRegistry: unknown;
|
|
111
|
+
llmRegistry: unknown;
|
|
112
|
+
};
|
|
113
|
+
export type { AgentConfig, ChatMessage, ChatRequest, Config, HookHandler, HookMap, HookRunner, HookRunnerOptions, Logger, LogLevel, Message, Plugin, PluginContext, PluginRecord, PluginRegistry, PluginServices, PluginStatus, ProviderConfig, Session, StreamChunk, ToolContext, ToolDef, ToolResult, };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { resolveProject } from './resolve.js';
|
|
4
|
+
/** 框架推断映射:依赖名 → 框架名(按常见前端/后端框架)。 */
|
|
5
|
+
const FRAMEWORK_MAP = {
|
|
6
|
+
react: 'react',
|
|
7
|
+
'react-dom': 'react',
|
|
8
|
+
vue: 'vue',
|
|
9
|
+
svelte: 'svelte',
|
|
10
|
+
'@angular/core': 'angular',
|
|
11
|
+
next: 'next.js',
|
|
12
|
+
nuxt: 'nuxt',
|
|
13
|
+
'@nestjs/core': 'nest',
|
|
14
|
+
'@hono/node-server': 'hono',
|
|
15
|
+
hono: 'hono',
|
|
16
|
+
express: 'express',
|
|
17
|
+
fastify: 'fastify',
|
|
18
|
+
};
|
|
19
|
+
/** 语言推断映射:文件后缀 → 语言名。 */
|
|
20
|
+
const EXT_LANGUAGE_MAP = {
|
|
21
|
+
'.ts': 'TypeScript',
|
|
22
|
+
'.tsx': 'TypeScript',
|
|
23
|
+
'.js': 'JavaScript',
|
|
24
|
+
'.jsx': 'JavaScript',
|
|
25
|
+
'.mjs': 'JavaScript',
|
|
26
|
+
'.py': 'Python',
|
|
27
|
+
'.go': 'Go',
|
|
28
|
+
'.rs': 'Rust',
|
|
29
|
+
'.java': 'Java',
|
|
30
|
+
'.kt': 'Kotlin',
|
|
31
|
+
'.rb': 'Ruby',
|
|
32
|
+
'.php': 'PHP',
|
|
33
|
+
'.cs': 'C#',
|
|
34
|
+
'.swift': 'Swift',
|
|
35
|
+
};
|
|
36
|
+
/** 安全读 package.json,失败返回 null。 */
|
|
37
|
+
function readPackageJson(cwd) {
|
|
38
|
+
const pkgPath = join(cwd, 'package.json');
|
|
39
|
+
if (!existsSync(pkgPath))
|
|
40
|
+
return null;
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** 从 package.json 的 deps 推断主框架。 */
|
|
49
|
+
function inferFramework(pkg) {
|
|
50
|
+
const deps = {
|
|
51
|
+
...(pkg.dependencies ?? {}),
|
|
52
|
+
...(pkg.devDependencies ?? {}),
|
|
53
|
+
};
|
|
54
|
+
if (!deps)
|
|
55
|
+
return undefined;
|
|
56
|
+
for (const depName of Object.keys(deps)) {
|
|
57
|
+
const mapped = FRAMEWORK_MAP[depName];
|
|
58
|
+
if (mapped)
|
|
59
|
+
return mapped;
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
/** 递归扫描源文件后缀统计,推断主语言(浅层,避免深扫 node_modules)。 */
|
|
64
|
+
function inferLanguage(cwd) {
|
|
65
|
+
const counts = {};
|
|
66
|
+
const queue = [join(cwd, 'src')];
|
|
67
|
+
let scanned = 0;
|
|
68
|
+
const MAX_SCAN = 500; // 防御性上限
|
|
69
|
+
while (queue.length > 0 && scanned < MAX_SCAN) {
|
|
70
|
+
const current = queue.shift();
|
|
71
|
+
scanned++;
|
|
72
|
+
let entries;
|
|
73
|
+
try {
|
|
74
|
+
entries = readdirSync(current);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
const full = join(current, entry);
|
|
81
|
+
let st;
|
|
82
|
+
try {
|
|
83
|
+
st = statSync(full);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (st.isDirectory()) {
|
|
89
|
+
if (entry === 'node_modules' || entry === '.git' || entry === 'dist')
|
|
90
|
+
continue;
|
|
91
|
+
queue.push(full);
|
|
92
|
+
}
|
|
93
|
+
else if (st.isFile()) {
|
|
94
|
+
const dot = entry.lastIndexOf('.');
|
|
95
|
+
if (dot < 0)
|
|
96
|
+
continue;
|
|
97
|
+
const ext = entry.slice(dot).toLowerCase();
|
|
98
|
+
const lang = EXT_LANGUAGE_MAP[ext];
|
|
99
|
+
if (lang)
|
|
100
|
+
counts[lang] = (counts[lang] ?? 0) + 1;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const sorted = Object.entries(counts).sort((a, b) => b[1] - a[1]);
|
|
105
|
+
return sorted[0]?.[0] ?? 'unknown';
|
|
106
|
+
}
|
|
107
|
+
/** 探测项目信息:name/language/framework/gitBranch,全部失败回退安全默认值。 */
|
|
108
|
+
function detectProjectInfo(cwd) {
|
|
109
|
+
const pkg = readPackageJson(cwd);
|
|
110
|
+
const name = ((pkg && typeof pkg.name === 'string' && pkg.name) || 'project');
|
|
111
|
+
const framework = pkg ? inferFramework(pkg) : undefined;
|
|
112
|
+
let language = 'unknown';
|
|
113
|
+
if (existsSync(join(cwd, 'src'))) {
|
|
114
|
+
language = inferLanguage(cwd);
|
|
115
|
+
}
|
|
116
|
+
else if (pkg) {
|
|
117
|
+
language = 'JavaScript';
|
|
118
|
+
}
|
|
119
|
+
// 复用已有 git 探测(resolveProject),不重复造轮子
|
|
120
|
+
const resolved = resolveProject(cwd);
|
|
121
|
+
// resolveProject.gitBranch 为 string | null,ProjectInfo.gitBranch 为 string | undefined
|
|
122
|
+
const gitBranch = resolved.vcs === 'git' ? (resolved.gitBranch ?? undefined) : undefined;
|
|
123
|
+
return {
|
|
124
|
+
name,
|
|
125
|
+
language,
|
|
126
|
+
framework,
|
|
127
|
+
rootDir: cwd,
|
|
128
|
+
gitBranch,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export { detectProjectInfo };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DB } from '../db/client.js';
|
|
2
|
+
export type Project = {
|
|
3
|
+
id: string;
|
|
4
|
+
worktree: string;
|
|
5
|
+
vcs: 'git' | null;
|
|
6
|
+
name: string | null;
|
|
7
|
+
gitRemote: string | null;
|
|
8
|
+
createdAt: number;
|
|
9
|
+
updatedAt: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 解析目录 + upsert 项目记录。返回 Project。
|
|
13
|
+
*
|
|
14
|
+
* 历史缺陷修复:旧版 resolveProject 曾用 git remote 作 id,remote 变更(先无后加)
|
|
15
|
+
* 会导致同一目录分裂成多个项目记录,挂在旧 id 的会话随之「消失」。这里在 upsert 后
|
|
16
|
+
* 合并同 worktree 的重复项目:把孤儿 id 名下的会话迁回规范 id,再删除孤儿记录。
|
|
17
|
+
* 幂等——无重复时为 no-op。
|
|
18
|
+
*/
|
|
19
|
+
export declare function fromDirectory(handle: DB, directory: string): Promise<Project>;
|
|
20
|
+
export declare function listProjects(handle: DB): Promise<Project[]>;
|
|
21
|
+
export declare function getProject(handle: DB, id: string): Promise<Project | null>;
|
|
22
|
+
export declare function getByDirectory(handle: DB, directory: string): Promise<Project | null>;
|
|
23
|
+
export declare function updateProjectName(handle: DB, id: string, name: string): Promise<Project | null>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
import { eq } from 'drizzle-orm';
|
|
3
|
+
import { projects, sessions } from '../db/schema.js';
|
|
4
|
+
import { resolveProject } from './resolve.js';
|
|
5
|
+
function rowToProject(row) {
|
|
6
|
+
return {
|
|
7
|
+
id: row.id,
|
|
8
|
+
worktree: row.worktree,
|
|
9
|
+
vcs: row.vcs ?? null,
|
|
10
|
+
name: row.name,
|
|
11
|
+
gitRemote: row.gitRemote,
|
|
12
|
+
createdAt: row.createdAt instanceof Date ? row.createdAt.getTime() : new Date(row.createdAt).getTime(),
|
|
13
|
+
updatedAt: row.updatedAt instanceof Date ? row.updatedAt.getTime() : new Date(row.updatedAt).getTime(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 解析目录 + upsert 项目记录。返回 Project。
|
|
18
|
+
*
|
|
19
|
+
* 历史缺陷修复:旧版 resolveProject 曾用 git remote 作 id,remote 变更(先无后加)
|
|
20
|
+
* 会导致同一目录分裂成多个项目记录,挂在旧 id 的会话随之「消失」。这里在 upsert 后
|
|
21
|
+
* 合并同 worktree 的重复项目:把孤儿 id 名下的会话迁回规范 id,再删除孤儿记录。
|
|
22
|
+
* 幂等——无重复时为 no-op。
|
|
23
|
+
*/
|
|
24
|
+
export async function fromDirectory(handle, directory) {
|
|
25
|
+
const resolved = resolveProject(directory);
|
|
26
|
+
const name = basename(resolved.worktree) || resolved.worktree;
|
|
27
|
+
await handle.db
|
|
28
|
+
.insert(projects)
|
|
29
|
+
.values({
|
|
30
|
+
id: resolved.id,
|
|
31
|
+
worktree: resolved.worktree,
|
|
32
|
+
vcs: resolved.vcs,
|
|
33
|
+
name,
|
|
34
|
+
gitRemote: resolved.gitRemote,
|
|
35
|
+
})
|
|
36
|
+
.onConflictDoUpdate({
|
|
37
|
+
target: projects.id,
|
|
38
|
+
set: {
|
|
39
|
+
worktree: resolved.worktree,
|
|
40
|
+
vcs: resolved.vcs,
|
|
41
|
+
gitRemote: resolved.gitRemote,
|
|
42
|
+
updatedAt: new Date(),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
await mergeDuplicateProjects(handle, resolved.id, resolved.worktree);
|
|
46
|
+
const result = await getProject(handle, resolved.id);
|
|
47
|
+
if (!result)
|
|
48
|
+
throw new Error(`Project upsert failed for ${directory}`);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 合并同 worktree 下 id ≠ canonicalId 的项目记录:迁移其会话到 canonicalId 后删除。
|
|
53
|
+
* 清理因 id 漂移(remote 变更)产生的历史重复项目,使列表不再出现同名重复项,
|
|
54
|
+
* 也让挂在漂移 id 上的会话重新归属规范项目。
|
|
55
|
+
*/
|
|
56
|
+
async function mergeDuplicateProjects(handle, canonicalId, worktree) {
|
|
57
|
+
const dups = await handle.db.select().from(projects).where(eq(projects.worktree, worktree));
|
|
58
|
+
for (const dup of dups) {
|
|
59
|
+
if (dup.id === canonicalId)
|
|
60
|
+
continue;
|
|
61
|
+
await handle.db
|
|
62
|
+
.update(sessions)
|
|
63
|
+
.set({ projectId: canonicalId })
|
|
64
|
+
.where(eq(sessions.projectId, dup.id));
|
|
65
|
+
await handle.db.delete(projects).where(eq(projects.id, dup.id));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function listProjects(handle) {
|
|
69
|
+
const rows = await handle.db.select().from(projects);
|
|
70
|
+
return rows.map(rowToProject);
|
|
71
|
+
}
|
|
72
|
+
export async function getProject(handle, id) {
|
|
73
|
+
const [row] = await handle.db.select().from(projects).where(eq(projects.id, id));
|
|
74
|
+
return row ? rowToProject(row) : null;
|
|
75
|
+
}
|
|
76
|
+
export async function getByDirectory(handle, directory) {
|
|
77
|
+
const resolved = resolveProject(directory);
|
|
78
|
+
return getProject(handle, resolved.id);
|
|
79
|
+
}
|
|
80
|
+
export async function updateProjectName(handle, id, name) {
|
|
81
|
+
const [row] = await handle.db
|
|
82
|
+
.update(projects)
|
|
83
|
+
.set({ name, updatedAt: new Date() })
|
|
84
|
+
.where(eq(projects.id, id))
|
|
85
|
+
.returning();
|
|
86
|
+
return row ? rowToProject(row) : null;
|
|
87
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { existsSync, statSync } from 'node:fs';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
/** 运行 git 命令,失败返回空字符串(不抛错)。 */
|
|
6
|
+
function git(args, cwd) {
|
|
7
|
+
try {
|
|
8
|
+
const result = spawnSync('git', args, {
|
|
9
|
+
cwd,
|
|
10
|
+
encoding: 'utf-8',
|
|
11
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
12
|
+
});
|
|
13
|
+
if (result.status !== 0 || result.error)
|
|
14
|
+
return '';
|
|
15
|
+
return (result.stdout ?? '').trim();
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** 从 directory 向上查找 .git,返回仓库根;非 git 返回 null。 */
|
|
22
|
+
function findGitRoot(directory) {
|
|
23
|
+
let current = resolve(directory);
|
|
24
|
+
// 防御性上限,避免无限向上
|
|
25
|
+
for (let i = 0; i < 64; i++) {
|
|
26
|
+
const dotGit = join(current, '.git');
|
|
27
|
+
if (existsSync(dotGit)) {
|
|
28
|
+
try {
|
|
29
|
+
statSync(dotGit);
|
|
30
|
+
return current;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// ignore
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const parent = resolve(current, '..');
|
|
37
|
+
if (parent === current)
|
|
38
|
+
break; // 到达根
|
|
39
|
+
current = parent;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/** 取第一个 remote 的 URL(origin 无果时的回退)。 */
|
|
44
|
+
function firstRemoteUrl(cwd) {
|
|
45
|
+
const names = git(['remote'], cwd);
|
|
46
|
+
const first = names
|
|
47
|
+
.split('\n')
|
|
48
|
+
.map((s) => s.trim())
|
|
49
|
+
.filter(Boolean)[0];
|
|
50
|
+
if (!first)
|
|
51
|
+
return '';
|
|
52
|
+
return git(['remote', 'get-url', first], cwd);
|
|
53
|
+
}
|
|
54
|
+
function hash16(input) {
|
|
55
|
+
return createHash('sha256').update(input).digest('hex').slice(0, 16);
|
|
56
|
+
}
|
|
57
|
+
export function resolveProject(directory) {
|
|
58
|
+
const absolute = resolve(directory);
|
|
59
|
+
const gitRoot = findGitRoot(absolute);
|
|
60
|
+
if (gitRoot) {
|
|
61
|
+
const remote = git(['remote', 'get-url', 'origin'], gitRoot) || firstRemoteUrl(gitRoot);
|
|
62
|
+
const branch = git(['rev-parse', '--abbrev-ref', 'HEAD'], gitRoot) || null;
|
|
63
|
+
// 身份恒用 worktree(本地路径稳定);remote 是可变元数据,曾用 remote 作 id 会在
|
|
64
|
+
// 「先无 remote 注册、后加 remote」时导致 id 漂移——同一目录分裂成两个项目,
|
|
65
|
+
// 历史会话挂在旧 id 上从列表消失。remote 仅记录到 gitRemote 字段。
|
|
66
|
+
return {
|
|
67
|
+
id: hash16(gitRoot),
|
|
68
|
+
worktree: gitRoot,
|
|
69
|
+
vcs: 'git',
|
|
70
|
+
gitRemote: remote || null,
|
|
71
|
+
gitBranch: branch,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
id: hash16(absolute),
|
|
76
|
+
worktree: absolute,
|
|
77
|
+
vcs: null,
|
|
78
|
+
gitRemote: null,
|
|
79
|
+
gitBranch: null,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AgentDependencies } from '../core/types.js';
|
|
2
|
+
import type { AgentState } from '../shared/types/agent.js';
|
|
3
|
+
/** 一个活跃的 agent run。 */
|
|
4
|
+
type ActiveRun = {
|
|
5
|
+
sessionId: string;
|
|
6
|
+
state: AgentState;
|
|
7
|
+
deps: AgentDependencies;
|
|
8
|
+
/** 若为子 agent run:记录父 sessionId(恢复时重建树)。 */
|
|
9
|
+
parentSessionId?: string;
|
|
10
|
+
/** 子 agent 类型名(调试/展示用)。 */
|
|
11
|
+
agentType?: string;
|
|
12
|
+
/** 后台任务 jobId(后台 subagent)。 */
|
|
13
|
+
jobId?: string;
|
|
14
|
+
};
|
|
15
|
+
/** Agent run 跟踪器 + 控制操作。 */
|
|
16
|
+
type AgentManager = {
|
|
17
|
+
register(run: ActiveRun): void;
|
|
18
|
+
get(sessionId: string): ActiveRun | undefined;
|
|
19
|
+
unregister(sessionId: string): void;
|
|
20
|
+
size(): number;
|
|
21
|
+
abort(sessionId: string): boolean;
|
|
22
|
+
pause(sessionId: string): boolean;
|
|
23
|
+
resume(sessionId: string): boolean;
|
|
24
|
+
steer(sessionId: string, message: string): boolean;
|
|
25
|
+
/** 查询某 session 的所有子 agent run(恢复/展示用)。 */
|
|
26
|
+
children(parentSessionId: string): ActiveRun[];
|
|
27
|
+
/** 查询所有后台任务(jobId 非空的 run)。 */
|
|
28
|
+
backgroundJobs(): ActiveRun[];
|
|
29
|
+
};
|
|
30
|
+
declare function createAgentManager(): AgentManager;
|
|
31
|
+
export type { ActiveRun, AgentManager };
|
|
32
|
+
export { createAgentManager };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/server/agent-manager.ts
|
|
2
|
+
import { abortAgent, injectSteering, pauseAgent, resumeAgent } from '../core/index.js';
|
|
3
|
+
function createAgentManager() {
|
|
4
|
+
const runs = new Map();
|
|
5
|
+
return {
|
|
6
|
+
register(run) {
|
|
7
|
+
runs.set(run.sessionId, run);
|
|
8
|
+
},
|
|
9
|
+
get(sessionId) {
|
|
10
|
+
return runs.get(sessionId);
|
|
11
|
+
},
|
|
12
|
+
unregister(sessionId) {
|
|
13
|
+
runs.delete(sessionId);
|
|
14
|
+
},
|
|
15
|
+
size() {
|
|
16
|
+
return runs.size;
|
|
17
|
+
},
|
|
18
|
+
abort(sessionId) {
|
|
19
|
+
const run = runs.get(sessionId);
|
|
20
|
+
if (!run)
|
|
21
|
+
return false;
|
|
22
|
+
abortAgent(run.state);
|
|
23
|
+
return true;
|
|
24
|
+
},
|
|
25
|
+
pause(sessionId) {
|
|
26
|
+
const run = runs.get(sessionId);
|
|
27
|
+
if (!run)
|
|
28
|
+
return false;
|
|
29
|
+
pauseAgent(run.state);
|
|
30
|
+
return true;
|
|
31
|
+
},
|
|
32
|
+
resume(sessionId) {
|
|
33
|
+
const run = runs.get(sessionId);
|
|
34
|
+
if (!run)
|
|
35
|
+
return false;
|
|
36
|
+
resumeAgent(run.state);
|
|
37
|
+
return true;
|
|
38
|
+
},
|
|
39
|
+
steer(sessionId, message) {
|
|
40
|
+
const run = runs.get(sessionId);
|
|
41
|
+
if (!run)
|
|
42
|
+
return false;
|
|
43
|
+
injectSteering(run.state, message);
|
|
44
|
+
return true;
|
|
45
|
+
},
|
|
46
|
+
children(parentSessionId) {
|
|
47
|
+
return Array.from(runs.values()).filter((r) => r.parentSessionId === parentSessionId);
|
|
48
|
+
},
|
|
49
|
+
backgroundJobs() {
|
|
50
|
+
return Array.from(runs.values()).filter((r) => r.jobId !== undefined);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export { createAgentManager };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/server/app.ts
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
5
|
+
import { Hono } from 'hono';
|
|
6
|
+
import { createAuthMiddleware } from './middleware/auth.js';
|
|
7
|
+
import { createCORSMiddleware } from './middleware/cors.js';
|
|
8
|
+
import { errorHandler } from './middleware/error.js';
|
|
9
|
+
import { createAgentRoute } from './routes/agent.js';
|
|
10
|
+
import { createCatalogRoute } from './routes/catalog.js';
|
|
11
|
+
import { createChatRoute } from './routes/chat.js';
|
|
12
|
+
import { createCommandsRoute } from './routes/commands.js';
|
|
13
|
+
import { createConfigRoute } from './routes/config.js';
|
|
14
|
+
import { createFilesRoute } from './routes/files.js';
|
|
15
|
+
import { createFilesystemRoute } from './routes/filesystem.js';
|
|
16
|
+
import { createHealthRoute } from './routes/health.js';
|
|
17
|
+
import { createPermissionsRoute } from './routes/permissions.js';
|
|
18
|
+
import { createProjectRoute } from './routes/project.js';
|
|
19
|
+
import { createProviderRoute } from './routes/provider.js';
|
|
20
|
+
import { createSessionRoute } from './routes/session.js';
|
|
21
|
+
import { createToolRoute } from './routes/tool.js';
|
|
22
|
+
import { createUpdateRoute } from './routes/update.js';
|
|
23
|
+
/** 创建完整的 Hono 应用,挂载所有路由 + 中间件。 */
|
|
24
|
+
function createApp(ctx) {
|
|
25
|
+
const app = new Hono();
|
|
26
|
+
// 中间件
|
|
27
|
+
app.onError(errorHandler);
|
|
28
|
+
// spec §24.2:仅允许本地/可信 origin 跨域读,拒绝外部网页。
|
|
29
|
+
app.use('*', createCORSMiddleware({ allowedOrigins: ctx.config.security.allowedOrigins }));
|
|
30
|
+
// spec §24.2:Bearer token 认证(配置了 token 时生效;/api/health 探活放行)。
|
|
31
|
+
app.use('/api/*', createAuthMiddleware(ctx.config.security.authEnabled ? ctx.config.security.token : undefined));
|
|
32
|
+
// 路由
|
|
33
|
+
app.route('/api/health', createHealthRoute());
|
|
34
|
+
app.route('/api/agents', createAgentRoute(ctx));
|
|
35
|
+
app.route('/api/sessions', createSessionRoute(ctx));
|
|
36
|
+
app.route('/api/projects', createProjectRoute(ctx));
|
|
37
|
+
app.route('/api/providers', createProviderRoute(ctx));
|
|
38
|
+
app.route('/api/catalog', createCatalogRoute(ctx));
|
|
39
|
+
app.route('/api/filesystem', createFilesystemRoute(ctx));
|
|
40
|
+
app.route('/api/chat', createChatRoute(ctx));
|
|
41
|
+
app.route('/api/commands', createCommandsRoute(ctx));
|
|
42
|
+
app.route('/api/tools', createToolRoute(ctx));
|
|
43
|
+
app.route('/api/update', createUpdateRoute(ctx));
|
|
44
|
+
app.route('/api/config', createConfigRoute(ctx));
|
|
45
|
+
app.route('/api/permissions', createPermissionsRoute(ctx));
|
|
46
|
+
app.route('/api/files', createFilesRoute(ctx));
|
|
47
|
+
// 根路径
|
|
48
|
+
app.get('/', (c) => c.json({
|
|
49
|
+
name: 'c0de-agent',
|
|
50
|
+
version: '0.1.0',
|
|
51
|
+
endpoints: [
|
|
52
|
+
'/api/health',
|
|
53
|
+
'/api/agents',
|
|
54
|
+
'/api/sessions',
|
|
55
|
+
'/api/projects',
|
|
56
|
+
'/api/providers',
|
|
57
|
+
'/api/catalog',
|
|
58
|
+
'/api/filesystem',
|
|
59
|
+
'/api/chat',
|
|
60
|
+
'/api/commands',
|
|
61
|
+
'/api/tools',
|
|
62
|
+
'/api/update',
|
|
63
|
+
'/api/config',
|
|
64
|
+
'/api/permissions',
|
|
65
|
+
'/api/files',
|
|
66
|
+
],
|
|
67
|
+
}));
|
|
68
|
+
// 静态文件服务(生产环境 dist-web/ 存在时启用)
|
|
69
|
+
if (existsSync(path.resolve(ctx.cwd, 'dist-web'))) {
|
|
70
|
+
app.use('/*', serveStatic({ root: './dist-web' }));
|
|
71
|
+
app.get('/*', (c) => c.body(null)); // SPA fallback
|
|
72
|
+
}
|
|
73
|
+
return app;
|
|
74
|
+
}
|
|
75
|
+
export { createApp };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentRegistry } from '../core/agents/types.js';
|
|
2
|
+
import { DEFAULT_CONFIG } from '../core/config.js';
|
|
3
|
+
import type { DB } from '../db/client.js';
|
|
4
|
+
import type { Registry } from '../llm/registry.js';
|
|
5
|
+
import type { Config } from '../shared/types/config.js';
|
|
6
|
+
import type { ToolRegistry } from '../tools/types.js';
|
|
7
|
+
import type { ServerContext } from './types.js';
|
|
8
|
+
type CreateServerContextOptions = {
|
|
9
|
+
db: DB;
|
|
10
|
+
config?: Config;
|
|
11
|
+
toolRegistry?: ToolRegistry;
|
|
12
|
+
llmRegistry: Registry;
|
|
13
|
+
cwd?: string;
|
|
14
|
+
chatStream?: ServerContext['chatStream'];
|
|
15
|
+
/** 测试注入:覆盖默认(内置 agent)注册表。 */
|
|
16
|
+
agentRegistry?: AgentRegistry;
|
|
17
|
+
};
|
|
18
|
+
declare function createServerContext(opts: CreateServerContextOptions): ServerContext;
|
|
19
|
+
export type { CreateServerContextOptions };
|
|
20
|
+
export { createServerContext, DEFAULT_CONFIG };
|