saeeol 1.0.5 → 1.0.7
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/package.json +1 -1
- package/script/build.ts +107 -6
- package/src/addons/addon-analytics.ts +14 -0
- package/src/addons/addon-core.ts +15 -0
- package/src/addons/addon-data.ts +14 -0
- package/src/addons/addon-dev.ts +13 -0
- package/src/addons/addon-lifecycle.ts +13 -0
- package/src/addons/addon-llm.ts +15 -0
- package/src/addons/addon-remote.ts +12 -0
- package/src/addons/addon-server.ts +14 -0
- package/src/addons/addon-tools.ts +13 -0
- package/src/addons/addon-web.ts +12 -0
- package/src/addons/registry.ts +65 -0
- package/src/addons/types.ts +31 -0
- package/src/index.ts +131 -69
- package/src/provider/bundled-providers.ts +28 -27
- package/src/provider/tiers/code.ts +21 -0
- package/src/provider/tiers/light.ts +14 -0
- package/src/provider/tiers/master.ts +17 -0
package/package.json
CHANGED
package/script/build.ts
CHANGED
|
@@ -55,7 +55,99 @@ const baselineFlag = process.argv.includes("--baseline")
|
|
|
55
55
|
const skipInstall = process.argv.includes("--skip-install")
|
|
56
56
|
const sourcemapsFlag = process.argv.includes("--sourcemaps")
|
|
57
57
|
const plugin = createSolidTransformPlugin()
|
|
58
|
-
|
|
58
|
+
|
|
59
|
+
// ══════════════════════════════════════════════════════════════════
|
|
60
|
+
// Tier-based tree-sitter WASM selection
|
|
61
|
+
//
|
|
62
|
+
// LIGHT = 5 langs (markdown, json, yaml, toml, tsx) ~8 MB
|
|
63
|
+
// CODE = 15 langs (+ python, rust, go, c, cpp...) ~18 MB
|
|
64
|
+
// MASTER = all 37 langs ~50 MB
|
|
65
|
+
// ══════════════════════════════════════════════════════════════════
|
|
66
|
+
|
|
67
|
+
// ══════════════════════════════════════════════════════════════════
|
|
68
|
+
// Tier-based external packages
|
|
69
|
+
// These packages are excluded from the bundle entirely
|
|
70
|
+
// ══════════════════════════════════════════════════════════════════
|
|
71
|
+
|
|
72
|
+
const allProviderPkgs = [
|
|
73
|
+
"@ai-sdk/amazon-bedrock",
|
|
74
|
+
"@ai-sdk/anthropic",
|
|
75
|
+
"@ai-sdk/azure",
|
|
76
|
+
"@ai-sdk/google",
|
|
77
|
+
"@ai-sdk/google-vertex",
|
|
78
|
+
"@ai-sdk/openai",
|
|
79
|
+
"@ai-sdk/openai-compatible",
|
|
80
|
+
"@openrouter/ai-sdk-provider",
|
|
81
|
+
"@ai-sdk/xai",
|
|
82
|
+
"@ai-sdk/mistral",
|
|
83
|
+
"@ai-sdk/groq",
|
|
84
|
+
"@ai-sdk/deepinfra",
|
|
85
|
+
"@ai-sdk/cerebras",
|
|
86
|
+
"@ai-sdk/cohere",
|
|
87
|
+
"@ai-sdk/gateway",
|
|
88
|
+
"@ai-sdk/togetherai",
|
|
89
|
+
"@ai-sdk/perplexity",
|
|
90
|
+
"@ai-sdk/vercel",
|
|
91
|
+
"@ai-sdk/alibaba",
|
|
92
|
+
"gitlab-ai-provider",
|
|
93
|
+
"venice-ai-sdk-provider",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
const lightRequired = new Set([
|
|
97
|
+
"@ai-sdk/anthropic",
|
|
98
|
+
"@ai-sdk/openai",
|
|
99
|
+
"@ai-sdk/openai-compatible",
|
|
100
|
+
"@ai-sdk/google",
|
|
101
|
+
"@saeeol/gateway",
|
|
102
|
+
])
|
|
103
|
+
|
|
104
|
+
const codeRequired = new Set([
|
|
105
|
+
...lightRequired,
|
|
106
|
+
"@ai-sdk/amazon-bedrock",
|
|
107
|
+
"@ai-sdk/azure",
|
|
108
|
+
"@ai-sdk/google-vertex",
|
|
109
|
+
"@openrouter/ai-sdk-provider",
|
|
110
|
+
"@ai-sdk/groq",
|
|
111
|
+
"@ai-sdk/deepinfra",
|
|
112
|
+
"@ai-sdk/gateway",
|
|
113
|
+
"@ai-sdk/alibaba",
|
|
114
|
+
"@ai-sdk/cerebras",
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
function tierExternals(tier: string): string[] {
|
|
118
|
+
if (tier === "master") return []
|
|
119
|
+
const required = tier === "light" ? lightRequired : codeRequired
|
|
120
|
+
return allProviderPkgs.filter((p) => !required.has(p))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const tierArg = process.argv.find((a) => a.startsWith("--tier="))?.split("=")[1] ?? "master"
|
|
124
|
+
|
|
125
|
+
const treeSitterLanguages: Record<string, string[]> = {
|
|
126
|
+
light: [
|
|
127
|
+
"markdown", "markdown_inline",
|
|
128
|
+
"json",
|
|
129
|
+
"yaml",
|
|
130
|
+
"toml",
|
|
131
|
+
"tsx", "typescript",
|
|
132
|
+
],
|
|
133
|
+
code: [
|
|
134
|
+
"markdown", "markdown_inline",
|
|
135
|
+
"json",
|
|
136
|
+
"yaml",
|
|
137
|
+
"toml",
|
|
138
|
+
"tsx", "typescript",
|
|
139
|
+
"python",
|
|
140
|
+
"rust",
|
|
141
|
+
"go",
|
|
142
|
+
"c", "cpp",
|
|
143
|
+
"java",
|
|
144
|
+
"javascript",
|
|
145
|
+
"bash",
|
|
146
|
+
],
|
|
147
|
+
master: [], // empty = all
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function copyTreeSitterWasms(outputDir: string, tier: string) {
|
|
59
151
|
const runtimeWasmPath = require.resolve("web-tree-sitter/tree-sitter.wasm")
|
|
60
152
|
const languagePackagePath = require.resolve("tree-sitter-wasms/package.json")
|
|
61
153
|
const languageWasmDir = path.join(path.dirname(languagePackagePath), "out")
|
|
@@ -64,13 +156,21 @@ async function copyTreeSitterWasms(outputDir: string) {
|
|
|
64
156
|
await fs.promises.mkdir(targetDir, { recursive: true })
|
|
65
157
|
await fs.promises.copyFile(runtimeWasmPath, path.join(targetDir, "tree-sitter.wasm"))
|
|
66
158
|
|
|
67
|
-
const
|
|
159
|
+
const allWasmFiles = (await fs.promises.readdir(languageWasmDir)).filter((file) => file.endsWith(".wasm"))
|
|
160
|
+
const allowed = treeSitterLanguages[tier]
|
|
161
|
+
|
|
162
|
+
const filesToCopy = allowed.length === 0
|
|
163
|
+
? allWasmFiles
|
|
164
|
+
: allWasmFiles.filter((file) => {
|
|
165
|
+
const langName = file.replace("tree-sitter-", "").replace(".wasm", "")
|
|
166
|
+
return allowed.some((a) => langName === a || langName.startsWith(a + "-"))
|
|
167
|
+
})
|
|
68
168
|
|
|
69
169
|
await Promise.all(
|
|
70
|
-
|
|
170
|
+
filesToCopy.map((file) => fs.promises.copyFile(path.join(languageWasmDir, file), path.join(targetDir, file))),
|
|
71
171
|
)
|
|
72
172
|
|
|
73
|
-
console.log(`copied ${
|
|
173
|
+
console.log(`copied ${filesToCopy.length + 1} tree-sitter wasm files to ${targetDir} (tier=${tier})`)
|
|
74
174
|
}
|
|
75
175
|
|
|
76
176
|
const allTargets: {
|
|
@@ -192,7 +292,7 @@ for (const item of targets) {
|
|
|
192
292
|
tsconfig: "./tsconfig.json",
|
|
193
293
|
plugins: [plugin],
|
|
194
294
|
sourcemap: Script.release ? "none" : "external",
|
|
195
|
-
external: ["node-gyp", ...LanceDBRuntime.external],
|
|
295
|
+
external: ["node-gyp", ...LanceDBRuntime.external, ...tierExternals(tierArg)],
|
|
196
296
|
format: "esm",
|
|
197
297
|
minify: true,
|
|
198
298
|
splitting: true,
|
|
@@ -216,10 +316,11 @@ for (const item of targets) {
|
|
|
216
316
|
SAEEOL_CHANNEL: `'${Script.channel}'`,
|
|
217
317
|
SAEEOL_LIBC: item.os === "linux" ? `'${item.abi ?? "glibc"}'` : "",
|
|
218
318
|
SAEEOL_BUILD_KIND: Script.release ? `'release'` : `'source'`,
|
|
319
|
+
SAEEOL_TIER: `'${tierArg}'`,
|
|
219
320
|
},
|
|
220
321
|
})
|
|
221
322
|
|
|
222
|
-
await copyTreeSitterWasms(path.resolve(dir, `dist/${name}/bin`))
|
|
323
|
+
await copyTreeSitterWasms(path.resolve(dir, `dist/${name}/bin`), tierArg)
|
|
223
324
|
if (item.os === "linux") {
|
|
224
325
|
const interpreters: Record<string, string> = {
|
|
225
326
|
x64: "/lib64/ld-linux-x86-64.so.2",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── analytics: 사용량 통계 + 모델 테스트 + PR ────────────────────────
|
|
4
|
+
export const analytics: Addon = {
|
|
5
|
+
id: "analytics",
|
|
6
|
+
category: "analytics",
|
|
7
|
+
minTier: "master",
|
|
8
|
+
required: false,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/stats").then((m) => ({ StatsCommand: m.StatsCommand })),
|
|
11
|
+
() => import("../cli/cmd/pr").then((m) => ({ PrCommand: m.PrCommand })),
|
|
12
|
+
() => import("../saeeol/cli/cmd/roll-call").then((m) => ({ RollCallCommand: m.RollCallCommand })),
|
|
13
|
+
],
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── core: TUI 채팅 + 프롬프트 실행 ──────────────────────────────────
|
|
4
|
+
export const core: Addon = {
|
|
5
|
+
id: "core",
|
|
6
|
+
category: "core",
|
|
7
|
+
minTier: "light",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/tui/thread").then((m) => ({ TuiThreadCommand: m.TuiThreadCommand })),
|
|
11
|
+
() => import("../cli/cmd/run").then((m) => ({ RunCommand: m.RunCommand })),
|
|
12
|
+
() => import("../cli/cmd/generate").then((m) => ({ GenerateCommand: m.GenerateCommand })),
|
|
13
|
+
() => import("../cli/cmd/session").then((m) => ({ SessionCommand: m.SessionCommand })),
|
|
14
|
+
],
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── data: 세션 내보내기/가져오기 + DB ───────────────────────────────
|
|
4
|
+
export const data: Addon = {
|
|
5
|
+
id: "data",
|
|
6
|
+
category: "data",
|
|
7
|
+
minTier: "code",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/export").then((m) => ({ ExportCommand: m.ExportCommand })),
|
|
11
|
+
() => import("../cli/cmd/import").then((m) => ({ ImportCommand: m.ImportCommand })),
|
|
12
|
+
() => import("../cli/cmd/db").then((m) => ({ DbCommand: m.DbCommand })),
|
|
13
|
+
],
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── dev: 에이전트 관리 + 디버깅 ─────────────────────────────────────
|
|
4
|
+
export const dev: Addon = {
|
|
5
|
+
id: "dev",
|
|
6
|
+
category: "dev",
|
|
7
|
+
minTier: "code",
|
|
8
|
+
required: false,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/agent").then((m) => ({ AgentCommand: m.AgentCommand })),
|
|
11
|
+
() => import("../cli/cmd/debug").then((m) => ({ DebugCommand: m.DebugCommand })),
|
|
12
|
+
],
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── lifecycle: 설치/업그레이드/제거 ──────────────────────────────────
|
|
4
|
+
export const lifecycle: Addon = {
|
|
5
|
+
id: "lifecycle",
|
|
6
|
+
category: "lifecycle",
|
|
7
|
+
minTier: "light",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/upgrade").then((m) => ({ UpgradeCommand: m.UpgradeCommand })),
|
|
11
|
+
() => import("../cli/cmd/uninstall").then((m) => ({ UninstallCommand: m.UninstallCommand })),
|
|
12
|
+
],
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── llm: LLM provider 설정 + 모델 관리 ──────────────────────────────
|
|
4
|
+
export const llm: Addon = {
|
|
5
|
+
id: "llm",
|
|
6
|
+
category: "llm",
|
|
7
|
+
minTier: "light",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/init").then((m) => ({ InitCommand: m.InitCommand })),
|
|
11
|
+
() => import("../cli/cmd/providers").then((m) => ({ ProvidersCommand: m.ProvidersCommand })),
|
|
12
|
+
() => import("../cli/cmd/models").then((m) => ({ ModelsCommand: m.ModelsCommand })),
|
|
13
|
+
() => import("../cli/cmd/config").then((m) => ({ ConfigCLICommand: m.ConfigCommand })),
|
|
14
|
+
],
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── remote: 실시간 세션 릴레이 ──────────────────────────────────────
|
|
4
|
+
export const remote: Addon = {
|
|
5
|
+
id: "remote",
|
|
6
|
+
category: "remote",
|
|
7
|
+
minTier: "master",
|
|
8
|
+
required: false,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/remote").then((m) => ({ RemoteCommand: m.RemoteCommand })),
|
|
11
|
+
],
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── server: headless 서버 + 원격 연결 + ACP ─────────────────────────
|
|
4
|
+
export const server: Addon = {
|
|
5
|
+
id: "server",
|
|
6
|
+
category: "server",
|
|
7
|
+
minTier: "code",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/serve").then((m) => ({ ServeCommand: m.ServeCommand })),
|
|
11
|
+
() => import("../cli/cmd/tui/attach").then((m) => ({ AttachCommand: m.AttachCommand })),
|
|
12
|
+
() => import("../cli/cmd/acp").then((m) => ({ AcpCommand: m.AcpCommand })),
|
|
13
|
+
],
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── tools: MCP + 플러그인 시스템 ────────────────────────────────────
|
|
4
|
+
export const tools: Addon = {
|
|
5
|
+
id: "tools",
|
|
6
|
+
category: "tools",
|
|
7
|
+
minTier: "code",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/mcp").then((m) => ({ McpCommand: m.McpCommand })),
|
|
11
|
+
() => import("../cli/cmd/plug").then((m) => ({ PluginCommand: m.PluginCommand })),
|
|
12
|
+
],
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Addon } from "./types"
|
|
2
|
+
|
|
3
|
+
// ── web: 브라우저 채팅 UI ───────────────────────────────────────────
|
|
4
|
+
export const web: Addon = {
|
|
5
|
+
id: "web",
|
|
6
|
+
category: "web",
|
|
7
|
+
minTier: "master",
|
|
8
|
+
required: true,
|
|
9
|
+
commands: [
|
|
10
|
+
() => import("../cli/cmd/web").then((m) => ({ WebCommand: m.WebCommand })),
|
|
11
|
+
],
|
|
12
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Addon, Tier } from "./types"
|
|
2
|
+
import { core } from "./addon-core"
|
|
3
|
+
import { llm } from "./addon-llm"
|
|
4
|
+
import { lifecycle } from "./addon-lifecycle"
|
|
5
|
+
import { server } from "./addon-server"
|
|
6
|
+
import { tools } from "./addon-tools"
|
|
7
|
+
import { data } from "./addon-data"
|
|
8
|
+
import { dev } from "./addon-dev"
|
|
9
|
+
import { web } from "./addon-web"
|
|
10
|
+
import { remote } from "./addon-remote"
|
|
11
|
+
import { analytics } from "./addon-analytics"
|
|
12
|
+
|
|
13
|
+
// ╔══════════════════════════════════════════════════════════════════╗
|
|
14
|
+
// ║ 애드온 레지스트리 ║
|
|
15
|
+
// ║ ║
|
|
16
|
+
// ║ LIGHT = core + llm + lifecycle (3 addons, 10 cmd) ║
|
|
17
|
+
// ║ CODE = LIGHT + server + tools + data + dev (8 addons, 20 cmd) ║
|
|
18
|
+
// ║ MASTER = CODE + web + remote + analytics (11 addons, 24 cmd)║
|
|
19
|
+
// ╚══════════════════════════════════════════════════════════════════╝
|
|
20
|
+
|
|
21
|
+
export const allAddons: Addon[] = [
|
|
22
|
+
// LIGHT
|
|
23
|
+
core, // TUI 채팅, run, generate, session
|
|
24
|
+
llm, // init, auth, models, config
|
|
25
|
+
lifecycle, // upgrade, uninstall
|
|
26
|
+
|
|
27
|
+
// CODE
|
|
28
|
+
server, // serve, attach, acp
|
|
29
|
+
tools, // mcp, plugin
|
|
30
|
+
data, // export, import, db
|
|
31
|
+
dev, // agent, debug
|
|
32
|
+
|
|
33
|
+
// MASTER
|
|
34
|
+
web, // web UI
|
|
35
|
+
remote, // real-time relay
|
|
36
|
+
analytics, // stats, pr, roll-call
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
const tierPriority: Record<Tier, number> = { light: 0, code: 1, master: 2 }
|
|
40
|
+
|
|
41
|
+
export function addonsForTier(tier: Tier): Addon[] {
|
|
42
|
+
return allAddons.filter((a) => tierPriority[tier] >= tierPriority[a.minTier])
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function commandsForTier(tier: Tier): Promise<any[]> {
|
|
46
|
+
const addons = addonsForTier(tier)
|
|
47
|
+
const commands: any[] = []
|
|
48
|
+
for (const addon of addons) {
|
|
49
|
+
for (const loader of addon.commands) {
|
|
50
|
+
const mod = await loader()
|
|
51
|
+
commands.push(...Object.values(mod))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return commands
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function manifest(tier: Tier) {
|
|
58
|
+
const addons = addonsForTier(tier)
|
|
59
|
+
return addons.map((a) => ({
|
|
60
|
+
id: a.id,
|
|
61
|
+
category: a.category,
|
|
62
|
+
commands: a.commands.length,
|
|
63
|
+
required: a.required,
|
|
64
|
+
}))
|
|
65
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// ╔══════════════════════════════════════════════════════════════════╗
|
|
2
|
+
// ║ SAEEOL 애드온 시스템 ║
|
|
3
|
+
// ║ ║
|
|
4
|
+
// ║ 원자 단위 기능 → 애드온 → 티어별 자동 활성화 ║
|
|
5
|
+
// ║ ║
|
|
6
|
+
// ║ LIGHT = core + llm + lifecycle ║
|
|
7
|
+
// ║ CODE = LIGHT + server + tools + data + dev ║
|
|
8
|
+
// ║ MASTER = CODE + web + remote + analytics ║
|
|
9
|
+
// ╚══════════════════════════════════════════════════════════════════╝
|
|
10
|
+
|
|
11
|
+
export type Tier = "light" | "code" | "master"
|
|
12
|
+
|
|
13
|
+
export interface Addon {
|
|
14
|
+
/** 애드온 ID */
|
|
15
|
+
id: string
|
|
16
|
+
/** 분류 */
|
|
17
|
+
category: "core" | "llm" | "lifecycle" | "server" | "tools" | "data" | "web" | "remote" | "analytics" | "dev"
|
|
18
|
+
/** 포함 명령어 */
|
|
19
|
+
commands: (() => Promise<Record<string, any>>)[]
|
|
20
|
+
/** 필요 티어 (이 티어부터 활성화) */
|
|
21
|
+
minTier: Tier
|
|
22
|
+
/** 필수/선택 */
|
|
23
|
+
required: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 티어 우선순위
|
|
27
|
+
const tierPriority: Record<Tier, number> = { light: 0, code: 1, master: 2 }
|
|
28
|
+
|
|
29
|
+
export function tierActive(addon: Addon, tier: Tier): boolean {
|
|
30
|
+
return tierPriority[tier] >= tierPriority[addon.minTier]
|
|
31
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,68 +1,97 @@
|
|
|
1
1
|
import yargs from "yargs"
|
|
2
2
|
import { hideBin } from "yargs/helpers"
|
|
3
|
+
|
|
4
|
+
// ╔══════════════════════════════════════════════════════════════════╗
|
|
5
|
+
// ║ SAEEOL CLI — 애드온 아키텍처 ║
|
|
6
|
+
// ║ ║
|
|
7
|
+
// ║ 원자 단위 애드온 → 티어별 자동 활성화 ║
|
|
8
|
+
// ║ ║
|
|
9
|
+
// ║ LIGHT = core + llm + lifecycle ║
|
|
10
|
+
// ║ CODE = LIGHT + server + tools + data + dev ║
|
|
11
|
+
// ║ MASTER = CODE + web + remote + analytics ║
|
|
12
|
+
// ╚══════════════════════════════════════════════════════════════════╝
|
|
13
|
+
|
|
14
|
+
// ── LIGHT: core ────────────────────────────────────────────────────
|
|
15
|
+
import { TuiThreadCommand } from "./cli/cmd/tui/thread"
|
|
3
16
|
import { RunCommand } from "./cli/cmd/run"
|
|
4
17
|
import { GenerateCommand } from "./cli/cmd/generate"
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
//
|
|
8
|
-
import {
|
|
18
|
+
import { SessionCommand } from "./cli/cmd/session"
|
|
19
|
+
|
|
20
|
+
// ── LIGHT: llm ─────────────────────────────────────────────────────
|
|
21
|
+
import { InitCommand } from "./cli/cmd/init"
|
|
9
22
|
import { ProvidersCommand } from "./cli/cmd/providers"
|
|
10
|
-
import {
|
|
23
|
+
import { ModelsCommand } from "./cli/cmd/models"
|
|
24
|
+
import { ConfigCommand as ConfigCLICommand } from "./cli/cmd/config"
|
|
25
|
+
|
|
26
|
+
// ── LIGHT: lifecycle ───────────────────────────────────────────────
|
|
11
27
|
import { UpgradeCommand } from "./cli/cmd/upgrade"
|
|
12
28
|
import { UninstallCommand } from "./cli/cmd/uninstall"
|
|
13
|
-
|
|
29
|
+
|
|
30
|
+
// ── CODE: server ───────────────────────────────────────────────────
|
|
31
|
+
import { ServeCommand } from "./cli/cmd/serve"
|
|
32
|
+
import { AttachCommand } from "./cli/cmd/tui/attach"
|
|
33
|
+
import { AcpCommand } from "./cli/cmd/acp"
|
|
34
|
+
|
|
35
|
+
// ── CODE: tools ────────────────────────────────────────────────────
|
|
36
|
+
import { McpCommand } from "./cli/cmd/mcp"
|
|
37
|
+
import { PluginCommand } from "./cli/cmd/plug"
|
|
38
|
+
|
|
39
|
+
// ── CODE: data ─────────────────────────────────────────────────────
|
|
40
|
+
import { ExportCommand } from "./cli/cmd/export"
|
|
41
|
+
import { ImportCommand } from "./cli/cmd/import"
|
|
42
|
+
import { DbCommand } from "./cli/cmd/db"
|
|
43
|
+
|
|
44
|
+
// ── CODE: dev (선택) ───────────────────────────────────────────────
|
|
45
|
+
import { AgentCommand } from "./cli/cmd/agent"
|
|
46
|
+
import { DebugCommand } from "./cli/cmd/debug"
|
|
47
|
+
|
|
48
|
+
// ── MASTER: web ────────────────────────────────────────────────────
|
|
49
|
+
import { WebCommand } from "./cli/cmd/web"
|
|
50
|
+
|
|
51
|
+
// ── MASTER: remote (선택) ──────────────────────────────────────────
|
|
52
|
+
import { RemoteCommand } from "./cli/cmd/remote"
|
|
53
|
+
|
|
54
|
+
// ── MASTER: analytics (선택) ───────────────────────────────────────
|
|
55
|
+
import { StatsCommand } from "./cli/cmd/stats"
|
|
56
|
+
import { PrCommand } from "./cli/cmd/pr"
|
|
57
|
+
import { RollCallCommand } from "./saeeol/cli/cmd/roll-call"
|
|
58
|
+
|
|
59
|
+
// ── DEV 전용 ───────────────────────────────────────────────────────
|
|
60
|
+
import { DevSetupCommand, DevAliasCommand } from "./saeeol/cli/dev-setup"
|
|
61
|
+
|
|
62
|
+
// ── 공통 ────────────────────────────────────────────────────────────
|
|
63
|
+
import * as Log from "@saeeol/core/util/log"
|
|
14
64
|
import { UI } from "./cli/ui"
|
|
15
65
|
import { Installation } from "./installation"
|
|
16
66
|
import { InstallationBuildKind, InstallationVersion } from "@saeeol/core/installation/version"
|
|
17
67
|
import { NamedError } from "@saeeol/core/util/error"
|
|
18
68
|
import { FormatError } from "./cli/error"
|
|
19
|
-
import { ServeCommand } from "./cli/cmd/serve"
|
|
20
69
|
import { Filesystem } from "@/util/filesystem"
|
|
21
|
-
import { ConfigCommand as ConfigCLICommand } from "./cli/cmd/config"
|
|
22
|
-
import { DebugCommand } from "./cli/cmd/debug"
|
|
23
|
-
import { StatsCommand } from "./cli/cmd/stats"
|
|
24
|
-
import { McpCommand } from "./cli/cmd/mcp"
|
|
25
|
-
// import { GithubCommand } from "./cli/cmd/github"
|
|
26
|
-
import { ExportCommand } from "./cli/cmd/export"
|
|
27
|
-
import { ImportCommand } from "./cli/cmd/import"
|
|
28
|
-
import { AttachCommand } from "./cli/cmd/tui/attach"
|
|
29
|
-
import { TuiThreadCommand } from "./cli/cmd/tui/thread"
|
|
30
|
-
import { AcpCommand } from "./cli/cmd/acp"
|
|
31
70
|
import { EOL } from "os"
|
|
32
|
-
// import { WebCommand } from "./cli/cmd/web"
|
|
33
|
-
import { PrCommand } from "./cli/cmd/pr"
|
|
34
|
-
import { SessionCommand } from "./cli/cmd/session"
|
|
35
|
-
import { RemoteCommand } from "./cli/cmd/remote"
|
|
36
|
-
import { RollCallCommand } from "./saeeol/cli/cmd/roll-call"
|
|
37
|
-
import { DevSetupCommand, DevAliasCommand } from "./saeeol/cli/dev-setup"
|
|
38
|
-
import { WebCommand } from "./cli/cmd/web"
|
|
39
71
|
import { Telemetry } from "@saeeol/telemetry"
|
|
40
72
|
import { InstanceStore } from "./project/instance-store"
|
|
41
73
|
import { migrateLegacySaeeolAuth, ENV_FEATURE, ENV_VERSION } from "@saeeol/gateway"
|
|
42
|
-
// (extension, cloud) which set their own SAEEOL_FEATURE env var. Direct CLI use
|
|
43
|
-
// (any command other than 'serve') is tagged as 'cli'. If 'serve' is spawned without
|
|
44
|
-
// the env var, it gets 'unknown' so the misconfiguration is visible in data.
|
|
45
|
-
if (!process.env[ENV_FEATURE]) {
|
|
46
|
-
const isServe = process.argv.includes("serve")
|
|
47
|
-
process.env[ENV_FEATURE] = isServe ? "unknown" : "cli"
|
|
48
|
-
}
|
|
49
|
-
if (!process.env[ENV_VERSION]) {
|
|
50
|
-
process.env[ENV_VERSION] = InstallationVersion
|
|
51
|
-
}
|
|
52
74
|
import { Config } from "./config/config"
|
|
53
75
|
import { Auth } from "./auth"
|
|
54
|
-
import { DbCommand } from "./cli/cmd/db"
|
|
55
76
|
import path from "path"
|
|
56
77
|
import { Global } from "@saeeol/core/global"
|
|
57
78
|
import { createHelpCommand } from "./saeeol/help-command"
|
|
58
79
|
import { JsonMigration } from "@/storage/json-migration"
|
|
59
80
|
import { Database } from "@/storage/db"
|
|
60
81
|
import { errorMessage } from "./util/error"
|
|
61
|
-
import { PluginCommand } from "./cli/cmd/plug"
|
|
62
|
-
import { InitCommand } from "./cli/cmd/init"
|
|
63
82
|
import { Heap } from "./cli/heap"
|
|
64
83
|
import { drizzle } from "drizzle-orm/bun-sqlite"
|
|
65
84
|
import { ensureProcessMetadata } from "@saeeol/core/util/saeeol-process"
|
|
85
|
+
import type { Tier } from "./addons/types"
|
|
86
|
+
import { addonsForTier, manifest } from "./addons/registry"
|
|
87
|
+
|
|
88
|
+
if (!process.env[ENV_FEATURE]) {
|
|
89
|
+
const isServe = process.argv.includes("serve")
|
|
90
|
+
process.env[ENV_FEATURE] = isServe ? "unknown" : "cli"
|
|
91
|
+
}
|
|
92
|
+
if (!process.env[ENV_VERSION]) {
|
|
93
|
+
process.env[ENV_VERSION] = InstallationVersion
|
|
94
|
+
}
|
|
66
95
|
|
|
67
96
|
const processMetadata = ensureProcessMetadata("main")
|
|
68
97
|
|
|
@@ -205,38 +234,71 @@ let cli = yargs(args)
|
|
|
205
234
|
})
|
|
206
235
|
.usage("")
|
|
207
236
|
.completion("completion", "generate shell completion script")
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
.command(
|
|
213
|
-
.command(
|
|
214
|
-
.command(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
.command(
|
|
221
|
-
.command(
|
|
222
|
-
.command(
|
|
223
|
-
.command(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
.command(
|
|
229
|
-
.command(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
.command(
|
|
235
|
-
.command(
|
|
236
|
-
.command(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
|
|
238
|
+
// ════════════════════════════════════════════════════════════════
|
|
239
|
+
// LIGHT: core (TUI 채팅 + 프롬프트 + 세션)
|
|
240
|
+
// ════════════════════════════════════════════════════════════════
|
|
241
|
+
.command(TuiThreadCommand) // [default] TUI 채팅
|
|
242
|
+
.command(RunCommand) // run 프롬프트 실행
|
|
243
|
+
.command(GenerateCommand) // generate 코드 생성
|
|
244
|
+
.command(SessionCommand) // session 세션 관리
|
|
245
|
+
|
|
246
|
+
// ════════════════════════════════════════════════════════════════
|
|
247
|
+
// LIGHT: llm (provider + 모델 + 설정)
|
|
248
|
+
// ════════════════════════════════════════════════════════════════
|
|
249
|
+
.command(InitCommand) // init 최초 설정
|
|
250
|
+
.command(ProvidersCommand) // auth provider 인증
|
|
251
|
+
.command(ModelsCommand) // models 모델 목록
|
|
252
|
+
.command(ConfigCLICommand) // config 설정 관리
|
|
253
|
+
|
|
254
|
+
// ════════════════════════════════════════════════════════════════
|
|
255
|
+
// LIGHT: lifecycle (설치/업그레이드/제거)
|
|
256
|
+
// ════════════════════════════════════════════════════════════════
|
|
257
|
+
.command(UpgradeCommand) // upgrade 버전 업그레이드
|
|
258
|
+
.command(UninstallCommand) // uninstall 제거
|
|
259
|
+
|
|
260
|
+
// ════════════════════════════════════════════════════════════════
|
|
261
|
+
// CODE: server (headless + 원격 + ACP)
|
|
262
|
+
// ════════════════════════════════════════════════════════════════
|
|
263
|
+
.command(ServeCommand) // serve headless 서버
|
|
264
|
+
.command(AttachCommand) // attach 원격 연결
|
|
265
|
+
.command(AcpCommand) // acp ACP 서버
|
|
266
|
+
|
|
267
|
+
// ════════════════════════════════════════════════════════════════
|
|
268
|
+
// CODE: tools (MCP + 플러그인)
|
|
269
|
+
// ════════════════════════════════════════════════════════════════
|
|
270
|
+
.command(McpCommand) // mcp MCP 서버 관리
|
|
271
|
+
.command(PluginCommand) // plugin 플러그인
|
|
272
|
+
|
|
273
|
+
// ════════════════════════════════════════════════════════════════
|
|
274
|
+
// CODE: data (export + import + db)
|
|
275
|
+
// ════════════════════════════════════════════════════════════════
|
|
276
|
+
.command(ExportCommand) // export 세션 내보내기
|
|
277
|
+
.command(ImportCommand) // import 세션 가져오기
|
|
278
|
+
.command(DbCommand) // db 데이터베이스
|
|
279
|
+
|
|
280
|
+
// ════════════════════════════════════════════════════════════════
|
|
281
|
+
// CODE: dev (선택)
|
|
282
|
+
// ════════════════════════════════════════════════════════════════
|
|
283
|
+
.command(AgentCommand) // agent 에이전트 관리
|
|
284
|
+
.command(DebugCommand) // debug 디버깅
|
|
285
|
+
|
|
286
|
+
// ════════════════════════════════════════════════════════════════
|
|
287
|
+
// MASTER: web (브라우저 채팅 UI)
|
|
288
|
+
// ════════════════════════════════════════════════════════════════
|
|
289
|
+
.command(WebCommand) // web 웹 UI + 브라우저
|
|
290
|
+
|
|
291
|
+
// ════════════════════════════════════════════════════════════════
|
|
292
|
+
// MASTER: remote (선택)
|
|
293
|
+
// ════════════════════════════════════════════════════════════════
|
|
294
|
+
.command(RemoteCommand) // remote 실시간 릴레이
|
|
295
|
+
|
|
296
|
+
// ════════════════════════════════════════════════════════════════
|
|
297
|
+
// MASTER: analytics (선택)
|
|
298
|
+
// ════════════════════════════════════════════════════════════════
|
|
299
|
+
.command(StatsCommand) // stats 사용량 통계
|
|
300
|
+
.command(PrCommand) // pr GitHub PR
|
|
301
|
+
.command(RollCallCommand) // roll-call 모델 연결 테스트
|
|
240
302
|
if (InstallationBuildKind !== "release") {
|
|
241
303
|
cli = cli.command(DevSetupCommand).command(DevAliasCommand)
|
|
242
304
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { SAEEOL_BUNDLED_PROVIDERS } from "@/saeeol/provider/provider"
|
|
2
1
|
import type { BundledSDK } from "./provider-types"
|
|
3
2
|
|
|
4
3
|
export function shouldUseCopilotResponsesApi(modelID: string): boolean {
|
|
@@ -11,30 +10,32 @@ export function useLanguageModel(sdk: any) {
|
|
|
11
10
|
return sdk.responses === undefined && sdk.chat === undefined
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
13
|
+
// ╔══════════════════════════════════════════════════════════════════╗
|
|
14
|
+
// ║ 티어별 provider 로딩 ║
|
|
15
|
+
// ║ ║
|
|
16
|
+
// ║ SAEEOL_TIER는 build.ts define으로 "light"|"code"|"master" 주입 ║
|
|
17
|
+
// ║ Bun은 dead branch를 제거하므로 다른 티어의 import()가 제외됨 ║
|
|
18
|
+
// ╚══════════════════════════════════════════════════════════════════╝
|
|
19
|
+
|
|
20
|
+
declare const SAEEOL_TIER: string
|
|
21
|
+
|
|
22
|
+
type ProviderLoader = () => Promise<(opts: any) => BundledSDK>
|
|
23
|
+
|
|
24
|
+
// 티어별 파일에서 각각 서로 다른 provider 집합을 import
|
|
25
|
+
// Bun은 조건에 맞지 않는 branch의 import()를 dead code로 처리
|
|
26
|
+
|
|
27
|
+
function getProviders(): Record<string, ProviderLoader> {
|
|
28
|
+
if (SAEEOL_TIER === "light") {
|
|
29
|
+
// Bun replaces SAEEOL_TIER with literal, dead-eliminates else branches
|
|
30
|
+
const m = require("./tiers/light") as typeof import("./tiers/light")
|
|
31
|
+
return m.lightProviders
|
|
32
|
+
}
|
|
33
|
+
if (SAEEOL_TIER === "code") {
|
|
34
|
+
const m = require("./tiers/code") as typeof import("./tiers/code")
|
|
35
|
+
return m.codeProviders
|
|
36
|
+
}
|
|
37
|
+
const m = require("./tiers/master") as typeof import("./tiers/master")
|
|
38
|
+
return m.masterProviders
|
|
40
39
|
}
|
|
40
|
+
|
|
41
|
+
export const BUNDLED_PROVIDERS: Record<string, ProviderLoader> = getProviders()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// CODE 티어 provider 맵 — LIGHT + 개발용 provider
|
|
2
|
+
import type { BundledSDK } from "../../provider/provider-types"
|
|
3
|
+
import { createSaeeol } from "@saeeol/gateway"
|
|
4
|
+
import { lightProviders } from "./light"
|
|
5
|
+
|
|
6
|
+
type L = () => Promise<(opts: any) => BundledSDK>
|
|
7
|
+
|
|
8
|
+
export const codeProviders: Record<string, L> = {
|
|
9
|
+
...lightProviders,
|
|
10
|
+
"@ai-sdk/amazon-bedrock": () => import("@ai-sdk/amazon-bedrock").then((m) => m.createAmazonBedrock),
|
|
11
|
+
"@ai-sdk/azure": () => import("@ai-sdk/azure").then((m) => m.createAzure),
|
|
12
|
+
"@ai-sdk/google-vertex": () => import("@ai-sdk/google-vertex").then((m) => m.createVertex),
|
|
13
|
+
"@ai-sdk/google-vertex/anthropic": () =>
|
|
14
|
+
import("@ai-sdk/google-vertex/anthropic").then((m) => m.createVertexAnthropic),
|
|
15
|
+
"@openrouter/ai-sdk-provider": () => import("@openrouter/ai-sdk-provider").then((m) => m.createOpenRouter),
|
|
16
|
+
"@ai-sdk/groq": () => import("@ai-sdk/groq").then((m) => m.createGroq),
|
|
17
|
+
"@ai-sdk/deepinfra": () => import("@ai-sdk/deepinfra").then((m) => m.createDeepInfra),
|
|
18
|
+
"@ai-sdk/gateway": () => import("@ai-sdk/gateway").then((m) => m.createGateway),
|
|
19
|
+
"@ai-sdk/alibaba": () => import("@ai-sdk/alibaba").then((m) => m.createAlibaba),
|
|
20
|
+
"@ai-sdk/cerebras": () => import("@ai-sdk/cerebras").then((m) => m.createCerebras),
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// LIGHT 티어 provider 맵 — 최소 provider만
|
|
2
|
+
import type { BundledSDK } from "../../provider/provider-types"
|
|
3
|
+
import { createSaeeol } from "@saeeol/gateway"
|
|
4
|
+
|
|
5
|
+
type L = () => Promise<(opts: any) => BundledSDK>
|
|
6
|
+
|
|
7
|
+
export const lightProviders: Record<string, L> = {
|
|
8
|
+
"@saeeol/gateway": async () => createSaeeol as any,
|
|
9
|
+
"@ai-sdk/anthropic": () => import("@ai-sdk/anthropic").then((m) => m.createAnthropic),
|
|
10
|
+
"@ai-sdk/openai": () => import("@ai-sdk/openai").then((m) => m.createOpenAI),
|
|
11
|
+
"@ai-sdk/openai-compatible": () => import("@ai-sdk/openai-compatible").then((m) => m.createOpenAICompatible),
|
|
12
|
+
"@ai-sdk/google": () => import("@ai-sdk/google").then((m) => m.createGoogleGenerativeAI),
|
|
13
|
+
"@ai-sdk/github-copilot": () => import("../sdk/copilot/copilot-provider").then((m) => m.createOpenaiCompatible),
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// MASTER 티어 provider 맵 — 전체 provider
|
|
2
|
+
import type { BundledSDK } from "../../provider/provider-types"
|
|
3
|
+
import { codeProviders } from "./code"
|
|
4
|
+
|
|
5
|
+
type L = () => Promise<(opts: any) => BundledSDK>
|
|
6
|
+
|
|
7
|
+
export const masterProviders: Record<string, L> = {
|
|
8
|
+
...codeProviders,
|
|
9
|
+
"@ai-sdk/xai": () => import("@ai-sdk/xai").then((m) => m.createXai),
|
|
10
|
+
"@ai-sdk/mistral": () => import("@ai-sdk/mistral").then((m) => m.createMistral),
|
|
11
|
+
"@ai-sdk/cohere": () => import("@ai-sdk/cohere").then((m) => m.createCohere),
|
|
12
|
+
"@ai-sdk/togetherai": () => import("@ai-sdk/togetherai").then((m) => m.createTogetherAI),
|
|
13
|
+
"@ai-sdk/perplexity": () => import("@ai-sdk/perplexity").then((m) => m.createPerplexity),
|
|
14
|
+
"@ai-sdk/vercel": () => import("@ai-sdk/vercel").then((m) => m.createVercel),
|
|
15
|
+
"gitlab-ai-provider": () => import("gitlab-ai-provider").then((m) => m.createGitLab),
|
|
16
|
+
"venice-ai-sdk-provider": () => import("venice-ai-sdk-provider").then((m) => m.createVenice),
|
|
17
|
+
}
|