diff --git a/.ai-project/state.yaml b/.ai-project/state.yaml index 9896289..66bfc26 100644 --- a/.ai-project/state.yaml +++ b/.ai-project/state.yaml @@ -1,8 +1,8 @@ 工作流: "idea-to-product" 项目: "Great Agent 2" 版本: "0.3.0" -当前阶段: "实施方案待确认" -更新时间: "2026-08-11" +当前阶段: "骨架待确认" +更新时间: "2026-08-12" 阻塞: null 阶段门: @@ -11,11 +11,11 @@ 确认人: "用户" 确认时间: "2026-08-11" 实施方案: - 状态: "待确认" - 确认人: null - 确认时间: null + 状态: "已确认" + 确认人: "用户" + 确认时间: "2026-08-12" 项目骨架: - 状态: "未开始" + 状态: "待确认" 确认人: null 确认时间: null 功能验收: diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9784111 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +HOST=127.0.0.1 +PORT=3000 +DATA_DIR=./data +DEFAULT_WORKSPACE_ROOT=./workspace +DEEPSEEK_API_KEY= +DEEPSEEK_BASE_URL=https://api.deepseek.com +DEEPSEEK_MODEL=deepseek-v4-pro +DEEPSEEK_THINKING=enabled +MODEL_TIMEOUT_MS=120000 +LOG_LEVEL=info diff --git a/.gitignore b/.gitignore index 4d05b34..f009b10 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ dist node_modules +data +workspace .env .env.local .env.*.local @@ -10,6 +12,9 @@ npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* +*.log .temp -.cache \ No newline at end of file +.cache +playwright-report/ +test-results/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bdbaca3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM oven/bun:1.3.11 AS build +WORKDIR /app +COPY package.json bun.lock bunfig.toml tsconfig.base.json biome.json ./ +COPY apps ./apps +COPY packages ./packages +COPY scripts ./scripts +RUN bun install --frozen-lockfile +RUN bun run build + +FROM oven/bun:1.3.11 AS runtime +WORKDIR /app +ENV HOST=0.0.0.0 PORT=3000 DATA_DIR=/data DEFAULT_WORKSPACE_ROOT=/workspace +COPY --from=build /app/node_modules ./node_modules +COPY --from=build /app/apps/web/dist ./apps/web/dist +COPY --from=build /app/apps/web-server/dist ./apps/web-server/dist +EXPOSE 3000 +CMD ["bun", "apps/web-server/dist/index.js"] diff --git a/apps/web-server/package.json b/apps/web-server/package.json new file mode 100644 index 0000000..e263603 --- /dev/null +++ b/apps/web-server/package.json @@ -0,0 +1,21 @@ +{ + "name": "@great-agent/web-server", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "bun --watch src/index.ts", + "typecheck": "tsc --noEmit", + "build": "bun build src/index.ts --outdir dist --target bun" + }, + "dependencies": { + "@great-agent/agent-core": "workspace:*", + "@great-agent/local-data": "workspace:*", + "@great-agent/local-files": "workspace:*", + "@great-agent/model-deepseek": "workspace:*", + "@great-agent/web-contracts": "workspace:*", + "hono": "^4.9.0", + "pino": "^9.9.0", + "zod": "^4.1.0" + } +} diff --git a/apps/web-server/src/composition/create-app.test.ts b/apps/web-server/src/composition/create-app.test.ts new file mode 100644 index 0000000..d6e7574 --- /dev/null +++ b/apps/web-server/src/composition/create-app.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, test } from "bun:test"; +import pino from "pino"; +import { healthResponseSchema } from "@great-agent/web-contracts"; +import { createApp } from "./create-app"; + +describe("Web Server 骨架", () => { + test("健康检查返回约定格式和请求标识", async () => { + const app = createApp(pino({ enabled: false })); + const response = await app.request("/api/health"); + expect(response.status).toBe(200); + expect(response.headers.get("X-Request-ID")).toBeTruthy(); + expect(healthResponseSchema.parse(await response.json()).status).toBe("ok"); + }); +}); diff --git a/apps/web-server/src/composition/create-app.ts b/apps/web-server/src/composition/create-app.ts new file mode 100644 index 0000000..a0d16be --- /dev/null +++ b/apps/web-server/src/composition/create-app.ts @@ -0,0 +1,13 @@ +import { Hono } from "hono"; +import type { Logger } from "pino"; +import { createErrorHandler } from "../http/error-handler"; +import { requestId } from "../http/request-id"; +import { createHealthRoutes } from "../routes/health"; + +export function createApp(logger: Logger): Hono { + const app = new Hono(); + app.use("*", requestId); + app.onError(createErrorHandler(logger)); + app.route("/api", createHealthRoutes()); + return app; +} diff --git a/apps/web-server/src/composition/create-logger.ts b/apps/web-server/src/composition/create-logger.ts new file mode 100644 index 0000000..fddda13 --- /dev/null +++ b/apps/web-server/src/composition/create-logger.ts @@ -0,0 +1,8 @@ +import pino, { type Logger } from "pino"; + +export function createLogger(level: string): Logger { + return pino({ + level, + redact: ["deepSeekApiKey", "req.headers.authorization"], + }); +} diff --git a/apps/web-server/src/composition/static-web.test.ts b/apps/web-server/src/composition/static-web.test.ts new file mode 100644 index 0000000..03e2016 --- /dev/null +++ b/apps/web-server/src/composition/static-web.test.ts @@ -0,0 +1,30 @@ +import { afterEach, describe, expect, test } from "bun:test"; +import { mkdtemp, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; +import { Hono } from "hono"; +import { mountStaticWeb } from "./static-web"; + +let temporaryRoot: string | undefined; + +afterEach(async () => { + if (temporaryRoot) await rm(temporaryRoot, { recursive: true, force: true }); + temporaryRoot = undefined; +}); + +describe("静态 Web 挂载", () => { + test("返回构建后的首页", async () => { + temporaryRoot = await mkdtemp(join(tmpdir(), "great-agent2-web-")); + await Bun.write(join(temporaryRoot, "assets", "app.js"), "export {};"); + await Bun.write( + join(temporaryRoot, "index.html"), + "

Great Agent 2

", + ); + const app = new Hono(); + mountStaticWeb(app, temporaryRoot); + const response = await app.request("/"); + expect(response.status).toBe(200); + expect(await response.text()).toContain("Great Agent 2"); + expect((await app.request("/assets/app.js")).status).toBe(200); + }); +}); diff --git a/apps/web-server/src/composition/static-web.ts b/apps/web-server/src/composition/static-web.ts new file mode 100644 index 0000000..c07d392 --- /dev/null +++ b/apps/web-server/src/composition/static-web.ts @@ -0,0 +1,19 @@ +import { existsSync } from "node:fs"; +import { join } from "node:path"; +import type { Hono } from "hono"; + +export function mountStaticWeb(app: Hono, webRoot: string): void { + if (!existsSync(webRoot)) return; + app.get("/assets/*", async (context) => { + const relativePath = context.req.path.slice(1); + const asset = Bun.file(join(webRoot, relativePath)); + if (!(await asset.exists())) return context.notFound(); + return new Response(asset); + }); + app.get("*", async () => { + const indexFile = Bun.file(join(webRoot, "index.html")); + return new Response(indexFile, { + headers: { "Content-Type": "text/html; charset=utf-8" }, + }); + }); +} diff --git a/apps/web-server/src/config/environment.test.ts b/apps/web-server/src/config/environment.test.ts new file mode 100644 index 0000000..3191fa7 --- /dev/null +++ b/apps/web-server/src/config/environment.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, test } from "bun:test"; +import { loadEnvironment } from "./environment"; + +describe("环境配置", () => { + test("使用安全的本机开发默认值", () => { + const environment = loadEnvironment({}); + expect(environment.host).toBe("127.0.0.1"); + expect(environment.port).toBe(3000); + expect(environment.deepSeekApiKey).toBeUndefined(); + }); +}); diff --git a/apps/web-server/src/config/environment.ts b/apps/web-server/src/config/environment.ts new file mode 100644 index 0000000..d22e5b1 --- /dev/null +++ b/apps/web-server/src/config/environment.ts @@ -0,0 +1,50 @@ +import { resolve } from "node:path"; +import { z } from "zod"; + +const environmentSchema = z.object({ + HOST: z.string().default("127.0.0.1"), + PORT: z.coerce.number().int().min(1).max(65_535).default(3000), + DATA_DIR: z.string().min(1).default("./data"), + DEFAULT_WORKSPACE_ROOT: z.string().min(1).default("./workspace"), + DEEPSEEK_API_KEY: z.string().optional(), + DEEPSEEK_BASE_URL: z.url().default("https://api.deepseek.com"), + DEEPSEEK_MODEL: z.string().min(1).default("deepseek-v4-pro"), + DEEPSEEK_THINKING: z.enum(["enabled", "disabled"]).default("enabled"), + MODEL_TIMEOUT_MS: z.coerce.number().int().positive().default(120_000), + LOG_LEVEL: z + .enum(["trace", "debug", "info", "warn", "error", "fatal"]) + .default("info"), +}); + +export type Environment = Readonly<{ + host: string; + port: number; + dataDir: string; + defaultWorkspaceRoot: string; + deepSeekApiKey?: string; + deepSeekBaseUrl: string; + deepSeekModel: string; + deepSeekThinking: "enabled" | "disabled"; + modelTimeoutMs: number; + logLevel: string; +}>; + +export function loadEnvironment( + source: Record = process.env, +): Environment { + const value = environmentSchema.parse(source); + return { + host: value.HOST, + port: value.PORT, + dataDir: resolve(value.DATA_DIR), + defaultWorkspaceRoot: resolve(value.DEFAULT_WORKSPACE_ROOT), + ...(value.DEEPSEEK_API_KEY + ? { deepSeekApiKey: value.DEEPSEEK_API_KEY } + : {}), + deepSeekBaseUrl: value.DEEPSEEK_BASE_URL, + deepSeekModel: value.DEEPSEEK_MODEL, + deepSeekThinking: value.DEEPSEEK_THINKING, + modelTimeoutMs: value.MODEL_TIMEOUT_MS, + logLevel: value.LOG_LEVEL, + }; +} diff --git a/apps/web-server/src/http/error-handler.ts b/apps/web-server/src/http/error-handler.ts new file mode 100644 index 0000000..8bf92ff --- /dev/null +++ b/apps/web-server/src/http/error-handler.ts @@ -0,0 +1,19 @@ +import type { ErrorHandler } from "hono"; +import type { Logger } from "pino"; + +export function createErrorHandler(logger: Logger): ErrorHandler { + return (error, context) => { + const requestId = context.get("requestId") ?? crypto.randomUUID(); + logger.error({ error, requestId }, "请求处理失败"); + return context.json( + { + error: { + code: "INTERNAL_ERROR", + message: "服务暂时不可用", + requestId, + }, + }, + 500, + ); + }; +} diff --git a/apps/web-server/src/http/request-id.ts b/apps/web-server/src/http/request-id.ts new file mode 100644 index 0000000..b547cc3 --- /dev/null +++ b/apps/web-server/src/http/request-id.ts @@ -0,0 +1,8 @@ +import type { MiddlewareHandler } from "hono"; + +export const requestId: MiddlewareHandler = async (context, next) => { + const id = context.req.header("X-Request-ID") ?? crypto.randomUUID(); + context.set("requestId", id); + context.header("X-Request-ID", id); + await next(); +}; diff --git a/apps/web-server/src/index.ts b/apps/web-server/src/index.ts new file mode 100644 index 0000000..4e3c316 --- /dev/null +++ b/apps/web-server/src/index.ts @@ -0,0 +1,29 @@ +import { resolve } from "node:path"; +import { createDataLayout, ensureDataLayout } from "@great-agent/local-data"; +import { createApp } from "./composition/create-app"; +import { createLogger } from "./composition/create-logger"; +import { mountStaticWeb } from "./composition/static-web"; +import { loadEnvironment } from "./config/environment"; + +const environment = loadEnvironment(); +const logger = createLogger(environment.logLevel); +const layout = createDataLayout(environment.dataDir); +await ensureDataLayout(layout); + +const app = createApp(logger); +mountStaticWeb(app, resolve(import.meta.dir, "../../web/dist")); + +logger.info( + { + host: environment.host, + port: environment.port, + dataDir: environment.dataDir, + }, + "Great Agent 2 服务启动", +); + +export default { + hostname: environment.host, + port: environment.port, + fetch: app.fetch, +}; diff --git a/apps/web-server/src/routes/health.ts b/apps/web-server/src/routes/health.ts new file mode 100644 index 0000000..52d9fdf --- /dev/null +++ b/apps/web-server/src/routes/health.ts @@ -0,0 +1,15 @@ +import { Hono } from "hono"; +import type { HealthResponse } from "@great-agent/web-contracts"; + +export function createHealthRoutes(): Hono { + const routes = new Hono(); + routes.get("/health", (context) => { + const response: HealthResponse = { + status: "ok", + service: "great-agent2", + timestamp: new Date().toISOString(), + }; + return context.json(response); + }); + return routes; +} diff --git a/apps/web-server/tsconfig.json b/apps/web-server/tsconfig.json new file mode 100644 index 0000000..68f7819 --- /dev/null +++ b/apps/web-server/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "rootDir": "src", "outDir": "dist-types" }, + "include": ["src"] +} diff --git a/apps/web/index.html b/apps/web/index.html new file mode 100644 index 0000000..327dce6 --- /dev/null +++ b/apps/web/index.html @@ -0,0 +1,12 @@ + + + + + + Great Agent 2 + + +
+ + + diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 0000000..7cdcb46 --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,18 @@ +{ + "name": "@great-agent/web", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "typecheck": "tsc --noEmit", + "build": "vite build" + }, + "dependencies": { + "@great-agent/web-contracts": "workspace:*", + "vanjs-core": "^1.5.5" + }, + "devDependencies": { + "vite": "^7.1.0" + } +} diff --git a/apps/web/src/app/app-shell.ts b/apps/web/src/app/app-shell.ts new file mode 100644 index 0000000..0a047dd --- /dev/null +++ b/apps/web/src/app/app-shell.ts @@ -0,0 +1,11 @@ +import van from "vanjs-core"; + +const { h1, main, p } = van.tags; + +export function AppShell(): HTMLElement { + return main( + { class: "app-shell" }, + h1("Great Agent 2"), + p("项目骨架运行正常,产品界面将在纵向功能阶段实现。"), + ); +} diff --git a/apps/web/src/main.ts b/apps/web/src/main.ts new file mode 100644 index 0000000..bae9ad9 --- /dev/null +++ b/apps/web/src/main.ts @@ -0,0 +1,8 @@ +import van from "vanjs-core"; +import { AppShell } from "./app/app-shell"; +import "./styles/global.css"; + +const mount = document.querySelector("#app"); +if (!mount) throw new Error("缺少应用挂载节点 #app"); + +van.add(mount, AppShell()); diff --git a/apps/web/src/styles/global.css b/apps/web/src/styles/global.css new file mode 100644 index 0000000..5552612 --- /dev/null +++ b/apps/web/src/styles/global.css @@ -0,0 +1,31 @@ +:root { + color: #272522; + background: #f7f6f2; + font-family: ui-sans-serif, system-ui, sans-serif; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; +} + +.app-shell { + display: grid; + min-height: 100vh; + place-content: center; + padding: 2rem; + text-align: center; +} + +.app-shell h1 { + margin: 0 0 0.75rem; + font-size: 2rem; +} + +.app-shell p { + margin: 0; + color: #6b6760; +} diff --git a/apps/web/src/vite-env.d.ts b/apps/web/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/apps/web/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json new file mode 100644 index 0000000..4db5d0b --- /dev/null +++ b/apps/web/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist-types", + "lib": ["ES2022", "DOM", "DOM.Iterable"] + }, + "include": ["src"] +} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..a95ae3f --- /dev/null +++ b/biome.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.8/schema.json", + "files": { + "includes": ["**", "!**/dist", "!**/node_modules", "!data"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "linter": { + "enabled": true, + "rules": { "preset": "recommended" } + }, + "javascript": { + "formatter": { "quoteStyle": "double", "semicolons": "always" } + } +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..4ddb3eb --- /dev/null +++ b/bun.lock @@ -0,0 +1,272 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "great-agent2", + "devDependencies": { + "@biomejs/biome": "^2.2.0", + "@types/bun": "^1.3.0", + "typescript": "^5.9.0", + }, + }, + "apps/web": { + "name": "@great-agent/web", + "version": "0.1.0", + "dependencies": { + "@great-agent/web-contracts": "workspace:*", + "vanjs-core": "^1.5.5", + }, + "devDependencies": { + "vite": "^7.1.0", + }, + }, + "apps/web-server": { + "name": "@great-agent/web-server", + "version": "0.1.0", + "dependencies": { + "@great-agent/agent-core": "workspace:*", + "@great-agent/local-data": "workspace:*", + "@great-agent/local-files": "workspace:*", + "@great-agent/model-deepseek": "workspace:*", + "@great-agent/web-contracts": "workspace:*", + "hono": "^4.9.0", + "pino": "^9.9.0", + "zod": "^4.1.0", + }, + }, + "packages/agent-core": { + "name": "@great-agent/agent-core", + "version": "0.1.0", + }, + "packages/local-data": { + "name": "@great-agent/local-data", + "version": "0.1.0", + }, + "packages/local-files": { + "name": "@great-agent/local-files", + "version": "0.1.0", + "dependencies": { + "@great-agent/agent-core": "workspace:*", + }, + }, + "packages/model-deepseek": { + "name": "@great-agent/model-deepseek", + "version": "0.1.0", + "dependencies": { + "@great-agent/agent-core": "workspace:*", + "openai": "^5.19.0", + }, + }, + "packages/web-contracts": { + "name": "@great-agent/web-contracts", + "version": "0.1.0", + "dependencies": { + "zod": "^4.1.0", + }, + }, + }, + "packages": { + "@biomejs/biome": ["@biomejs/biome@2.5.8", "https://registry.npmmirror.com/@biomejs/biome/-/biome-2.5.8.tgz", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.8", "@biomejs/cli-darwin-x64": "2.5.8", "@biomejs/cli-linux-arm64": "2.5.8", "@biomejs/cli-linux-arm64-musl": "2.5.8", "@biomejs/cli-linux-x64": "2.5.8", "@biomejs/cli-linux-x64-musl": "2.5.8", "@biomejs/cli-win32-arm64": "2.5.8", "@biomejs/cli-win32-x64": "2.5.8" }, "bin": { "biome": "bin/biome" } }, "sha512-aeAeeJB9fSDc7Gq+2GqpQxA0qBj6gj1k2R6L1cYqGePKP/baIq1WX8y6B+D+nRsO5ViQL22K/8IwbqERW0q1nw=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.8.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-mk1QON9PHllvvLN5gU3f4rMxeh4syK5p9OvKyWH6/W8ueh04uaC8TUXXByhGufWf/y5mQc03ZLM45zU+cmqMjA=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.8.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-bsGwFMBNyHPyiLSsQcZJxdoRrg1V4JL+d7wEsvUBczlP9U9lwM+7mzQHxI4o1mhBsTmdOBbAb6fHU3Z3snN45w=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.8.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-XmFiA0WPYFC+uiUDC8WRFzAIH9bo7vwQLav38Uoq4ETC+T/+uBi0TsYGJECkugY3r8USl3jc+Ae2/irAF6F2lQ=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.8.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-VcJNbstduTHx83NGAdhp78/JOcP45BZHXL7yNsfI1uGzdUgegAz2s+mSoT7wK6PBNzLoqG0zDOXaz/RQYVtSiw=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.8.tgz", { "os": "linux", "cpu": "x64" }, "sha512-S5wcm9OBDvLHodD4PUaN488hCpco9QD/9ZxuYJiw4euWtr/oQvLR72z2ixItH8Wd5BCm6FZaeb+YNvOoM1xHtQ=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.8.tgz", { "os": "linux", "cpu": "x64" }, "sha512-kKmiyokeISRGq2FLwvr+TzsgBusfxaZ0FZNLcOYOpCK/78tRrEjeEBLvq3xLZMpqbANgJdRPI7vZX8ZL37u9/w=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.8", "https://registry.npmmirror.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.8.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-nILH0mzm3Hi3iEdd7o7GpB8kBR/mSQwfQG/tyBqyNrY2GFtcgwfV9nV8xLmbtUpMNY/Oi0Ml1XgfR4flOdq+AA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.28.2", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz", { "os": "android", "cpu": "arm" }, "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", { "os": "android", "cpu": "arm64" }, "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz", { "os": "android", "cpu": "x64" }, "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", { "os": "linux", "cpu": "arm" }, "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", { "os": "linux", "cpu": "ia32" }, "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", { "os": "linux", "cpu": "none" }, "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", { "os": "linux", "cpu": "none" }, "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", { "os": "linux", "cpu": "none" }, "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", { "os": "linux", "cpu": "x64" }, "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", { "os": "none", "cpu": "arm64" }, "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", { "os": "none", "cpu": "x64" }, "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", { "os": "openbsd", "cpu": "arm64" }, "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", { "os": "none", "cpu": "arm64" }, "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", { "os": "sunos", "cpu": "x64" }, "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.2", "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.2", "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.2", "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", { "os": "win32", "cpu": "x64" }, "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g=="], + + "@great-agent/agent-core": ["@great-agent/agent-core@workspace:packages/agent-core"], + + "@great-agent/local-data": ["@great-agent/local-data@workspace:packages/local-data"], + + "@great-agent/local-files": ["@great-agent/local-files@workspace:packages/local-files"], + + "@great-agent/model-deepseek": ["@great-agent/model-deepseek@workspace:packages/model-deepseek"], + + "@great-agent/web": ["@great-agent/web@workspace:apps/web"], + + "@great-agent/web-contracts": ["@great-agent/web-contracts@workspace:packages/web-contracts"], + + "@great-agent/web-server": ["@great-agent/web-server@workspace:apps/web-server"], + + "@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "https://registry.npmmirror.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="], + + "@pinojs/redact": ["@pinojs/redact@0.4.0", "https://registry.npmmirror.com/@pinojs/redact/-/redact-0.4.0.tgz", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz", { "os": "android", "cpu": "arm" }, "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz", { "os": "android", "cpu": "arm64" }, "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz", { "os": "linux", "cpu": "arm" }, "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz", { "os": "linux", "cpu": "arm" }, "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz", { "os": "linux", "cpu": "none" }, "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz", { "os": "linux", "cpu": "none" }, "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz", { "os": "linux", "cpu": "none" }, "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz", { "os": "linux", "cpu": "none" }, "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz", { "os": "linux", "cpu": "x64" }, "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz", { "os": "linux", "cpu": "x64" }, "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz", { "os": "none", "cpu": "arm64" }, "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz", { "os": "win32", "cpu": "x64" }, "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.62.4", "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz", { "os": "win32", "cpu": "x64" }, "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q=="], + + "@types/bun": ["@types/bun@1.3.14", "https://registry.npmmirror.com/@types/bun/-/bun-1.3.14.tgz", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], + + "@types/estree": ["@types/estree@1.0.9", "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + + "@types/node": ["@types/node@26.2.0", "https://registry.npmmirror.com/@types/node/-/node-26.2.0.tgz", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="], + + "atomic-sleep": ["atomic-sleep@1.0.0", "https://registry.npmmirror.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], + + "bun-types": ["bun-types@1.3.14", "https://registry.npmmirror.com/bun-types/-/bun-types-1.3.14.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + + "esbuild": ["esbuild@0.28.2", "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.2.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.2", "@esbuild/android-arm": "0.28.2", "@esbuild/android-arm64": "0.28.2", "@esbuild/android-x64": "0.28.2", "@esbuild/darwin-arm64": "0.28.2", "@esbuild/darwin-x64": "0.28.2", "@esbuild/freebsd-arm64": "0.28.2", "@esbuild/freebsd-x64": "0.28.2", "@esbuild/linux-arm": "0.28.2", "@esbuild/linux-arm64": "0.28.2", "@esbuild/linux-ia32": "0.28.2", "@esbuild/linux-loong64": "0.28.2", "@esbuild/linux-mips64el": "0.28.2", "@esbuild/linux-ppc64": "0.28.2", "@esbuild/linux-riscv64": "0.28.2", "@esbuild/linux-s390x": "0.28.2", "@esbuild/linux-x64": "0.28.2", "@esbuild/netbsd-arm64": "0.28.2", "@esbuild/netbsd-x64": "0.28.2", "@esbuild/openbsd-arm64": "0.28.2", "@esbuild/openbsd-x64": "0.28.2", "@esbuild/openharmony-arm64": "0.28.2", "@esbuild/sunos-x64": "0.28.2", "@esbuild/win32-arm64": "0.28.2", "@esbuild/win32-ia32": "0.28.2", "@esbuild/win32-x64": "0.28.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA=="], + + "fdir": ["fdir@6.5.0", "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fsevents": ["fsevents@2.3.3", "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "hono": ["hono@4.13.1", "https://registry.npmmirror.com/hono/-/hono-4.13.1.tgz", {}, "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw=="], + + "nanoid": ["nanoid@3.3.18", "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.18.tgz", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="], + + "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "https://registry.npmmirror.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], + + "openai": ["openai@5.23.2", "https://registry.npmmirror.com/openai/-/openai-5.23.2.tgz", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg=="], + + "picocolors": ["picocolors@1.1.1", "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.5", "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.5.tgz", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], + + "pino": ["pino@9.14.0", "https://registry.npmmirror.com/pino/-/pino-9.14.0.tgz", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w=="], + + "pino-abstract-transport": ["pino-abstract-transport@2.0.0", "https://registry.npmmirror.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], + + "pino-std-serializers": ["pino-std-serializers@7.1.0", "https://registry.npmmirror.com/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="], + + "postcss": ["postcss@8.5.26", "https://registry.npmmirror.com/postcss/-/postcss-8.5.26.tgz", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="], + + "process-warning": ["process-warning@5.1.0", "https://registry.npmmirror.com/process-warning/-/process-warning-5.1.0.tgz", {}, "sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw=="], + + "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "https://registry.npmmirror.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], + + "real-require": ["real-require@0.2.0", "https://registry.npmmirror.com/real-require/-/real-require-0.2.0.tgz", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], + + "rollup": ["rollup@4.62.4", "https://registry.npmmirror.com/rollup/-/rollup-4.62.4.tgz", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@napi-rs/lzma-linux-x64-gnu": "1.5.1", "@rollup/rollup-android-arm-eabi": "4.62.4", "@rollup/rollup-android-arm64": "4.62.4", "@rollup/rollup-darwin-arm64": "4.62.4", "@rollup/rollup-darwin-x64": "4.62.4", "@rollup/rollup-freebsd-arm64": "4.62.4", "@rollup/rollup-freebsd-x64": "4.62.4", "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", "@rollup/rollup-linux-arm-musleabihf": "4.62.4", "@rollup/rollup-linux-arm64-gnu": "4.62.4", "@rollup/rollup-linux-arm64-musl": "4.62.4", "@rollup/rollup-linux-loong64-gnu": "4.62.4", "@rollup/rollup-linux-loong64-musl": "4.62.4", "@rollup/rollup-linux-ppc64-gnu": "4.62.4", "@rollup/rollup-linux-ppc64-musl": "4.62.4", "@rollup/rollup-linux-riscv64-gnu": "4.62.4", "@rollup/rollup-linux-riscv64-musl": "4.62.4", "@rollup/rollup-linux-s390x-gnu": "4.62.4", "@rollup/rollup-linux-x64-gnu": "4.62.4", "@rollup/rollup-linux-x64-musl": "4.62.4", "@rollup/rollup-openbsd-x64": "4.62.4", "@rollup/rollup-openharmony-arm64": "4.62.4", "@rollup/rollup-win32-arm64-msvc": "4.62.4", "@rollup/rollup-win32-ia32-msvc": "4.62.4", "@rollup/rollup-win32-x64-gnu": "4.62.4", "@rollup/rollup-win32-x64-msvc": "4.62.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg=="], + + "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "https://registry.npmmirror.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + + "sonic-boom": ["sonic-boom@4.2.1", "https://registry.npmmirror.com/sonic-boom/-/sonic-boom-4.2.1.tgz", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q=="], + + "source-map-js": ["source-map-js@1.2.1", "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "split2": ["split2@4.2.0", "https://registry.npmmirror.com/split2/-/split2-4.2.0.tgz", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + + "thread-stream": ["thread-stream@3.2.0", "https://registry.npmmirror.com/thread-stream/-/thread-stream-3.2.0.tgz", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw=="], + + "tinyglobby": ["tinyglobby@0.2.17", "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], + + "typescript": ["typescript@5.9.3", "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@8.3.0", "https://registry.npmmirror.com/undici-types/-/undici-types-8.3.0.tgz", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], + + "vanjs-core": ["vanjs-core@1.6.1", "https://registry.npmmirror.com/vanjs-core/-/vanjs-core-1.6.1.tgz", {}, "sha512-CPUteb4/iW3hB7TLTKI9A9YMRTAQFpPz5n1/+vfnPxNs2wOI9HvSg6K3B/9x+uycX8eefqopBcakr2vJeHgIgw=="], + + "vite": ["vite@7.3.6", "https://registry.npmmirror.com/vite/-/vite-7.3.6.tgz", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="], + + "zod": ["zod@4.4.3", "https://registry.npmmirror.com/zod/-/zod-4.4.3.tgz", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + } +} diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..ffe9333 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,3 @@ +[test] +root = "." +coverage = false diff --git a/docs/IMPLEMENTATION.md b/docs/IMPLEMENTATION.md index 7e22ba5..ad6dc71 100644 --- a/docs/IMPLEMENTATION.md +++ b/docs/IMPLEMENTATION.md @@ -1,10 +1,10 @@ # 实施方案 -状态:待确认 +状态:已确认,项目骨架待确认 方案版本:0.4.0 需求版本:0.3.0(已确认、已冻结) -确认人: -确认时间: +确认人:用户 +确认时间:2026-08-12 ## 1. 约束与关键默认值 @@ -833,6 +833,25 @@ bun run test:visual 骨架阶段不得提前实现会话、模型调用、本地文件工具或完整 UI。 +### 项目骨架验证记录(2026-08-12) + +骨架已按本节范围生成,实际验证环境为 Bun `1.3.11`。以下命令均在项目根目录运行: + +| 命令 | 结果 | +|---|---| +| `bun install` | 通过;安装 76 个包并生成 `bun.lock` | +| `bun run format:check` | 通过;检查 46 个文件,无需修改 | +| `bun run lint` | 通过;检查 47 个文件,无警告或错误 | +| `bun run typecheck` | 通过;7 个 Workspace 包全部通过 | +| `bun run check:file-size` | 通过;TypeScript 文件均不超过 400 行 | +| `bun run check:architecture` | 通过;Core 与 Web 依赖方向符合约束 | +| `bun test` | 通过;5 个测试、13 个断言,0 失败 | +| `bun run build` | 通过;VanJS/Vite 与 Hono/Bun 生产产物均生成成功 | + +额外生产产物冒烟验证:使用 `PORT=3137` 和临时数据目录启动 `apps/web-server/dist/index.js`,`GET /api/health`、`GET /` 和构建后的 JavaScript 静态资源均返回 `200`;健康检查包含 `X-Request-ID`,并生成 `projects`、`conversations`、`runs`、`indexes`、`recovery` 五个数据目录。 + +当前未配置真实 `DEEPSEEK_API_KEY`、正式数据目录和正式默认工作区,这是骨架阶段的预期状态。代码中尚未实现项目、会话、Agent Run、模型请求、本地文件工具或 Claude Desktop 业务界面。确认骨架后,第一个纵向功能仍为 F-001“应用外壳、首次状态与普通会话”;进入该切片前先确定视觉参考截图包。 + ## 21. 有序纵向功能切片 ### F-001 应用外壳、首次状态与普通会话 diff --git a/package.json b/package.json new file mode 100644 index 0000000..c5c1555 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "great-agent2", + "private": true, + "version": "0.1.0", + "workspaces": [ + "apps/*", + "packages/*" + ], + "scripts": { + "dev": "bun run --filter @great-agent/web --filter @great-agent/web-server dev", + "format": "biome format --write .", + "format:check": "biome format .", + "lint": "biome lint .", + "typecheck": "bun run --filter '*' typecheck", + "check:file-size": "bun run scripts/check-file-size.ts", + "check:architecture": "bun run scripts/check-architecture.ts", + "test": "bun test", + "build": "bun run --filter @great-agent/web build && bun run --filter @great-agent/web-server build", + "start": "bun apps/web-server/dist/index.js" + }, + "devDependencies": { + "@biomejs/biome": "^2.2.0", + "@types/bun": "^1.3.0", + "typescript": "^5.9.0" + } +} diff --git a/packages/agent-core/package.json b/packages/agent-core/package.json new file mode 100644 index 0000000..64b339e --- /dev/null +++ b/packages/agent-core/package.json @@ -0,0 +1,11 @@ +{ + "name": "@great-agent/agent-core", + "version": "0.1.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit" + } +} diff --git a/packages/agent-core/src/errors/core-error.ts b/packages/agent-core/src/errors/core-error.ts new file mode 100644 index 0000000..8f5e469 --- /dev/null +++ b/packages/agent-core/src/errors/core-error.ts @@ -0,0 +1,10 @@ +export class CoreError extends Error { + constructor( + readonly code: string, + message: string, + options?: ErrorOptions, + ) { + super(message, options); + this.name = "CoreError"; + } +} diff --git a/packages/agent-core/src/index.ts b/packages/agent-core/src/index.ts new file mode 100644 index 0000000..648ac12 --- /dev/null +++ b/packages/agent-core/src/index.ts @@ -0,0 +1,7 @@ +export { CoreError } from "./errors/core-error"; +export type { ModelEvent, ModelPort, ModelRequest } from "./ports/model-port"; +export type { + ClockPort, + IdPort, + WorkspaceResolverPort, +} from "./ports/system-ports"; diff --git a/packages/agent-core/src/ports/model-port.ts b/packages/agent-core/src/ports/model-port.ts new file mode 100644 index 0000000..b03728c --- /dev/null +++ b/packages/agent-core/src/ports/model-port.ts @@ -0,0 +1,13 @@ +export type ModelRequest = Readonly<{ + model: string; + messages: readonly unknown[]; +}>; + +export type ModelEvent = Readonly<{ + type: string; + payload: unknown; +}>; + +export interface ModelPort { + stream(request: ModelRequest, signal: AbortSignal): AsyncIterable; +} diff --git a/packages/agent-core/src/ports/system-ports.ts b/packages/agent-core/src/ports/system-ports.ts new file mode 100644 index 0000000..b7a2162 --- /dev/null +++ b/packages/agent-core/src/ports/system-ports.ts @@ -0,0 +1,11 @@ +export interface ClockPort { + now(): Date; +} + +export interface IdPort { + create(): string; +} + +export interface WorkspaceResolverPort { + resolve(conversationId: string): Promise; +} diff --git a/packages/agent-core/tsconfig.json b/packages/agent-core/tsconfig.json new file mode 100644 index 0000000..6fcd57f --- /dev/null +++ b/packages/agent-core/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "rootDir": "src", "outDir": "dist" }, + "include": ["src"] +} diff --git a/packages/local-data/package.json b/packages/local-data/package.json new file mode 100644 index 0000000..04db524 --- /dev/null +++ b/packages/local-data/package.json @@ -0,0 +1,11 @@ +{ + "name": "@great-agent/local-data", + "version": "0.1.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit" + } +} diff --git a/packages/local-data/src/atomic-writes/append-ndjson.ts b/packages/local-data/src/atomic-writes/append-ndjson.ts new file mode 100644 index 0000000..c0f51b8 --- /dev/null +++ b/packages/local-data/src/atomic-writes/append-ndjson.ts @@ -0,0 +1,10 @@ +import { dirname } from "node:path"; +import { appendFile, mkdir } from "node:fs/promises"; + +export async function appendNdjson( + path: string, + value: unknown, +): Promise { + await mkdir(dirname(path), { recursive: true }); + await appendFile(path, `${JSON.stringify(value)}\n`, "utf8"); +} diff --git a/packages/local-data/src/atomic-writes/write-json-atomically.ts b/packages/local-data/src/atomic-writes/write-json-atomically.ts new file mode 100644 index 0000000..475868c --- /dev/null +++ b/packages/local-data/src/atomic-writes/write-json-atomically.ts @@ -0,0 +1,12 @@ +import { dirname } from "node:path"; +import { mkdir, rename } from "node:fs/promises"; + +export async function writeJsonAtomically( + path: string, + value: unknown, +): Promise { + await mkdir(dirname(path), { recursive: true }); + const temporaryPath = `${path}.${crypto.randomUUID()}.tmp`; + await Bun.write(temporaryPath, `${JSON.stringify(value, null, 2)}\n`); + await rename(temporaryPath, path); +} diff --git a/packages/local-data/src/index.ts b/packages/local-data/src/index.ts new file mode 100644 index 0000000..885ede3 --- /dev/null +++ b/packages/local-data/src/index.ts @@ -0,0 +1,8 @@ +export { appendNdjson } from "./atomic-writes/append-ndjson"; +export { writeJsonAtomically } from "./atomic-writes/write-json-atomically"; +export { + createDataLayout, + DATA_FORMAT_VERSION, + ensureDataLayout, + type DataLayout, +} from "./layout/data-layout"; diff --git a/packages/local-data/src/layout/data-layout.ts b/packages/local-data/src/layout/data-layout.ts new file mode 100644 index 0000000..6a4f6a0 --- /dev/null +++ b/packages/local-data/src/layout/data-layout.ts @@ -0,0 +1,37 @@ +import { join } from "node:path"; +import { mkdir } from "node:fs/promises"; + +export const DATA_FORMAT_VERSION = 1; + +export type DataLayout = Readonly<{ + root: string; + projects: string; + conversations: string; + runs: string; + indexes: string; + recovery: string; +}>; + +export function createDataLayout(root: string): DataLayout { + return { + root, + projects: join(root, "projects"), + conversations: join(root, "conversations"), + runs: join(root, "runs"), + indexes: join(root, "indexes"), + recovery: join(root, "recovery"), + }; +} + +export async function ensureDataLayout(layout: DataLayout): Promise { + await Promise.all( + [ + layout.root, + layout.projects, + layout.conversations, + layout.runs, + layout.indexes, + layout.recovery, + ].map((path) => mkdir(path, { recursive: true })), + ); +} diff --git a/packages/local-data/src/local-data.test.ts b/packages/local-data/src/local-data.test.ts new file mode 100644 index 0000000..daecbf9 --- /dev/null +++ b/packages/local-data/src/local-data.test.ts @@ -0,0 +1,40 @@ +import { afterEach, describe, expect, test } from "bun:test"; +import { join } from "node:path"; +import { mkdtemp, rm, stat } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { + appendNdjson, + createDataLayout, + ensureDataLayout, + writeJsonAtomically, +} from "."; + +const temporaryRoots: string[] = []; + +afterEach(async () => { + for (const path of temporaryRoots.splice(0)) { + await rm(path, { recursive: true, force: true }); + } +}); + +describe("local-data 骨架", () => { + test("创建固定数据目录布局", async () => { + const root = await mkdtemp(join(tmpdir(), "great-agent2-data-")); + temporaryRoots.push(root); + const layout = createDataLayout(root); + await ensureDataLayout(layout); + expect((await stat(layout.projects)).isDirectory()).toBe(true); + expect((await stat(layout.recovery)).isDirectory()).toBe(true); + }); + + test("原子写入 JSON 并追加 NDJSON", async () => { + const root = await mkdtemp(join(tmpdir(), "great-agent2-write-")); + temporaryRoots.push(root); + const jsonPath = join(root, "entity.json"); + const logPath = join(root, "events.ndjson"); + await writeJsonAtomically(jsonPath, { schemaVersion: 1 }); + await appendNdjson(logPath, { sequence: 1 }); + expect(await Bun.file(jsonPath).json()).toEqual({ schemaVersion: 1 }); + expect(await Bun.file(logPath).text()).toBe('{"sequence":1}\n'); + }); +}); diff --git a/packages/local-data/tsconfig.json b/packages/local-data/tsconfig.json new file mode 100644 index 0000000..6fcd57f --- /dev/null +++ b/packages/local-data/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "rootDir": "src", "outDir": "dist" }, + "include": ["src"] +} diff --git a/packages/local-files/package.json b/packages/local-files/package.json new file mode 100644 index 0000000..c0fdc3c --- /dev/null +++ b/packages/local-files/package.json @@ -0,0 +1,14 @@ +{ + "name": "@great-agent/local-files", + "version": "0.1.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@great-agent/agent-core": "workspace:*" + } +} diff --git a/packages/local-files/src/index.ts b/packages/local-files/src/index.ts new file mode 100644 index 0000000..e226c70 --- /dev/null +++ b/packages/local-files/src/index.ts @@ -0,0 +1 @@ +export const localFilesPackage = "@great-agent/local-files"; diff --git a/packages/local-files/tsconfig.json b/packages/local-files/tsconfig.json new file mode 100644 index 0000000..6fcd57f --- /dev/null +++ b/packages/local-files/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "rootDir": "src", "outDir": "dist" }, + "include": ["src"] +} diff --git a/packages/model-deepseek/package.json b/packages/model-deepseek/package.json new file mode 100644 index 0000000..3d5f764 --- /dev/null +++ b/packages/model-deepseek/package.json @@ -0,0 +1,15 @@ +{ + "name": "@great-agent/model-deepseek", + "version": "0.1.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@great-agent/agent-core": "workspace:*", + "openai": "^5.19.0" + } +} diff --git a/packages/model-deepseek/src/index.ts b/packages/model-deepseek/src/index.ts new file mode 100644 index 0000000..8d61db6 --- /dev/null +++ b/packages/model-deepseek/src/index.ts @@ -0,0 +1 @@ +export const deepSeekAdapterPackage = "@great-agent/model-deepseek"; diff --git a/packages/model-deepseek/tsconfig.json b/packages/model-deepseek/tsconfig.json new file mode 100644 index 0000000..6fcd57f --- /dev/null +++ b/packages/model-deepseek/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "rootDir": "src", "outDir": "dist" }, + "include": ["src"] +} diff --git a/packages/web-contracts/package.json b/packages/web-contracts/package.json new file mode 100644 index 0000000..dfd1226 --- /dev/null +++ b/packages/web-contracts/package.json @@ -0,0 +1,14 @@ +{ + "name": "@great-agent/web-contracts", + "version": "0.1.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "zod": "^4.1.0" + } +} diff --git a/packages/web-contracts/src/index.ts b/packages/web-contracts/src/index.ts new file mode 100644 index 0000000..bcda54c --- /dev/null +++ b/packages/web-contracts/src/index.ts @@ -0,0 +1 @@ +export { healthResponseSchema, type HealthResponse } from "./responses/health"; diff --git a/packages/web-contracts/src/responses/health.ts b/packages/web-contracts/src/responses/health.ts new file mode 100644 index 0000000..6296124 --- /dev/null +++ b/packages/web-contracts/src/responses/health.ts @@ -0,0 +1,9 @@ +import { z } from "zod"; + +export const healthResponseSchema = z.object({ + status: z.literal("ok"), + service: z.literal("great-agent2"), + timestamp: z.iso.datetime(), +}); + +export type HealthResponse = z.infer; diff --git a/packages/web-contracts/tsconfig.json b/packages/web-contracts/tsconfig.json new file mode 100644 index 0000000..6fcd57f --- /dev/null +++ b/packages/web-contracts/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "rootDir": "src", "outDir": "dist" }, + "include": ["src"] +} diff --git a/scripts/check-architecture.ts b/scripts/check-architecture.ts new file mode 100644 index 0000000..6f7ebfa --- /dev/null +++ b/scripts/check-architecture.ts @@ -0,0 +1,48 @@ +const rules = [ + { + root: "packages/agent-core/src", + forbidden: [ + "hono", + "vanjs-core", + "openai", + "bun:", + "node:fs", + "@great-agent/", + ], + }, + { + root: "apps/web/src", + forbidden: [ + "@great-agent/agent-core", + "@great-agent/local-data", + "@great-agent/local-files", + "@great-agent/model-deepseek", + ], + }, +]; + +const violations: string[] = []; +for (const rule of rules) { + const glob = new Bun.Glob("**/*.ts"); + for await (const relative of glob.scan({ cwd: rule.root, onlyFiles: true })) { + const path = `${rule.root}/${relative}`; + const source = await Bun.file(path).text(); + for (const forbidden of rule.forbidden) { + if ( + source.includes(`from "${forbidden}`) || + source.includes(`import("${forbidden}`) + ) { + violations.push(`${path}: 禁止依赖 ${forbidden}`); + } + } + } +} + +if (violations.length > 0) { + console.error(violations.join("\n")); + process.exit(1); +} + +console.log("架构依赖检查通过。"); + +export {}; diff --git a/scripts/check-file-size.ts b/scripts/check-file-size.ts new file mode 100644 index 0000000..b1805d1 --- /dev/null +++ b/scripts/check-file-size.ts @@ -0,0 +1,21 @@ +const roots = ["apps", "packages", "scripts"]; +const limit = 400; +const oversized: string[] = []; + +for (const root of roots) { + const glob = new Bun.Glob("**/*.ts"); + for await (const relative of glob.scan({ cwd: root, onlyFiles: true })) { + const path = `${root}/${relative}`; + const lineCount = (await Bun.file(path).text()).split("\n").length; + if (lineCount > limit) oversized.push(`${path}: ${lineCount} 行`); + } +} + +if (oversized.length > 0) { + console.error(`以下文件超过 ${limit} 行:\n${oversized.join("\n")}`); + process.exit(1); +} + +console.log(`文件规模检查通过:TypeScript 文件均不超过 ${limit} 行。`); + +export {}; diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..07cbfed --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "types": ["bun"], + "declaration": true, + "declarationMap": true, + "sourceMap": true + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8f2a111 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["scripts/**/*.ts"], + "exclude": ["node_modules", "dist", "apps", "packages"] +}