build(ports): 本地开发改用 7380/7381 避开端口冲突
Some checks failed
Publish container images / Quality checks (push) Has been cancelled
Publish container images / Resolve build version (push) Has been cancelled
Publish container images / Build open-ai-canvas-backend (amd64) (push) Has been cancelled
Publish container images / Build open-ai-canvas-backend (arm64) (push) Has been cancelled
Publish container images / Build open-ai-canvas-web (multi) (push) Has been cancelled
Publish container images / Publish open-ai-canvas-backend manifest (push) Has been cancelled
Publish container images / Publish open-ai-canvas-web manifest (push) Has been cancelled
Publish container images / Publish release assets (push) Has been cancelled
Some checks failed
Publish container images / Quality checks (push) Has been cancelled
Publish container images / Resolve build version (push) Has been cancelled
Publish container images / Build open-ai-canvas-backend (amd64) (push) Has been cancelled
Publish container images / Build open-ai-canvas-backend (arm64) (push) Has been cancelled
Publish container images / Build open-ai-canvas-web (multi) (push) Has been cancelled
Publish container images / Publish open-ai-canvas-backend manifest (push) Has been cancelled
Publish container images / Publish open-ai-canvas-web manifest (push) Has been cancelled
Publish container images / Publish release assets (push) Has been cancelled
This commit is contained in:
@@ -4,7 +4,7 @@ CANVAS_REGISTRATION_ENABLED=false
|
||||
CANVAS_ALLOW_PRIVATE_UPSTREAMS=false
|
||||
# 多个主机使用英文逗号分隔,例如:gateway.internal,192.168.1.10
|
||||
CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS=
|
||||
CANVAS_CORS_ORIGINS=http://localhost:3000
|
||||
CANVAS_CORS_ORIGINS=http://localhost:7380
|
||||
# 服务器对模型上游可访问的地址:本地存储的短时签名链接(Agent 看图、生成任务参考图)由它拼出,
|
||||
# 内网部署还要把该主机放进 CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS。留空则本地存储无法签出链接。
|
||||
CANVAS_PUBLIC_BASE_URL=
|
||||
@@ -34,4 +34,5 @@ CANVAS_UPDATER_SOCKET_DIR=/run/open-ai-canvas-updater
|
||||
# REDIS_URL=redis://redis:6379/0
|
||||
# CANVAS_POSTGRES_DATA_PATH=./postgres-data
|
||||
# CANVAS_REDIS_DATA_PATH=./redis-data
|
||||
# CANVAS_HTTP_PORT=3000
|
||||
# 宿主机访问端口;本项目使用 7380 以避免与同机其它工程(默认 3000)冲突
|
||||
# CANVAS_HTTP_PORT=7380
|
||||
|
||||
70
AGENTS.md
70
AGENTS.md
@@ -138,3 +138,73 @@
|
||||
- Git 提交说明使用 `<type>(<scope>): <业务模块> - <变更摘要>`,`type` 为 `feat|fix|refactor|perf|docs|test|build|ci|chore|revert`。
|
||||
|
||||
交付前至少检查:改动是否聚焦、调用方和类型是否同步、错误/权限/数据归属是否完整、必要文档是否同步、验证是否如实说明、是否留下密钥或本地数据。
|
||||
|
||||
---
|
||||
|
||||
# 本项目附加约定
|
||||
|
||||
以上第 1–9 章继承自上游 `ddcat-ai/open-ai-canvas`。以下为本仓库(`ttstd-infinite-canvas`)在底座之上叠加的约定;**与上游冲突时以本章为准**。
|
||||
|
||||
## A. 底座与上游同步
|
||||
|
||||
本仓库以 `ddcat-ai/open-ai-canvas` 为底座,通过 Git remote 保持可追溯的上游关系:
|
||||
|
||||
- `upstream` → `https://github.com/ddcat-ai/open-ai-canvas.git`(开发机上另存有一份克隆,可作离线 fetch 源)。
|
||||
- 同步新功能:`git fetch upstream && git merge upstream/main`。冲突优先保留上游实现,本仓库的差异应集中在 B~D 三项。
|
||||
- **功能一律优先使用上游源码实现**,不要在本仓库另起一套。确需偏离上游时,先在本章登记原因再改代码。
|
||||
- `libtv.html` 与 `libtv-前端技术分析.md` 是竞品运行时快照与分析资料,属于本地参考,不要当作上游代码改动。
|
||||
- 分支:本仓库工作分支为 `master`,上游为 `main`;`git pull upstream` 后按需合并。
|
||||
|
||||
## B. 端口约定
|
||||
|
||||
**不要改回上游默认的 3000 / 8080**——同机上 `infinite-canvas`、`open-ai-canvas`、`open-canvas` 都占用 3000,会互相抢占。
|
||||
|
||||
| 场景 | 前端 | 后端 |
|
||||
| --- | --- | --- |
|
||||
| 本地开发(宿主机) | **7380** | **7381** |
|
||||
| Docker(宿主机映射) | **7380** → 容器 3000 | 不暴露(容器内仍 8080) |
|
||||
|
||||
容器内部端口保持上游原样(nginx `listen 3000`、后端 `:8080`),以减小与上游的差异面。改端口时必须同步:
|
||||
|
||||
- `web/package.json` — `dev` / `start` 的 `--port`
|
||||
- `web/vite.config.ts` — `apiProxyTarget` 默认值
|
||||
- `backend/cmd/server/main.go` — `CANVAS_BACKEND_ADDR` 默认值
|
||||
- `scripts/start-local.ps1` — 后端地址、代理目标、提示文案
|
||||
- `docker-compose.yml`、`docker-compose.local.yml` — 宿主机端口映射与 `CANVAS_CORS_ORIGINS`
|
||||
- `.env.example` — `CANVAS_CORS_ORIGINS`、`CANVAS_HTTP_PORT`
|
||||
- `README.md` 快速开始
|
||||
|
||||
`docker-compose.deploy.yml` / `docker-compose.server.yml` 与 `scripts/install-server*.sh` 面向独立服务器部署,保留上游的 3000 默认值,不做本地化改动。
|
||||
|
||||
`scripts/launch-canvas.ps1` 是上游维护者的个人脚本(硬编码 `D:\yingce\...`、`Administrator`、cloudflared 隧道),在本机不可用,**保持原样不要改**。
|
||||
|
||||
## C. 许可与商标红线
|
||||
|
||||
- 本仓库与上游均为 **MIT**。复制上游代码必须保留其版权声明与 `NOTICE`(声明 fork 自 `basketikun/infinite-canvas`,上游作者权利保留)。
|
||||
- **`tldraw` 许可非 MIT**:生产环境商用需购买 license key,否则必须保留 "Made with tldraw" 水印。上游已预留 `VITE_TLDRAW_LICENSE_KEY`(构建期)与 `tldraw_license_key`(运行时设置),对外商用前必须就此明确决策。
|
||||
- **不得新增他人 logo / 商标**:`web/public/icons/` 下的模型厂商图标、根 README 的赞助商与社群素材仅在上游语境下存在,对外分发前必须清理或替换为纯文字。
|
||||
- **禁止把带 GPL 组件的 ffmpeg 打进分发镜像**:服务端 ffmpeg 使用 LGPL 构建或由用户挂载(`CANVAS_FFMPEG_PATH`)。
|
||||
- 面向国内公众提供服务时,需处理 AI 生成内容标识、生成式 AI 服务备案与深度合成管理要求。
|
||||
|
||||
## D. 进程清理(强制)
|
||||
|
||||
验收或调试结束后清理进程时,**只允许按精确 PID 操作**,严禁用命令名、路径片段或宽正则批量匹配后终止。
|
||||
|
||||
正确做法:
|
||||
|
||||
1. `netstat -ano | Select-String 'LISTENING' | Select-String ':<端口>'` 拿到占用端口的 PID;
|
||||
2. `Get-Process -Id <pid>` 确认进程名与可执行文件路径确属本项目;
|
||||
3. `Stop-Process -Id <pid> -Force`;需要连带子进程时用 `taskkill /PID <pid> /T /F`。
|
||||
|
||||
禁止的做法(已有实际事故):
|
||||
|
||||
- ❌ `Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'server\.exe' } | Stop-Process`
|
||||
曾匹配到 IDE 的 `embeddings-server.exe`,导致误杀开发环境进程。
|
||||
- ❌ `-match 'vite'` / `-match 'node'` / `-match 'concurrently'` / `-match 'go'`
|
||||
这些字符串同样会命中编辑器本体、语言服务器,以及同机上其它工程。
|
||||
|
||||
补充要求:
|
||||
|
||||
- 需要批量清理时,**先只打印**匹配结果(PID、进程名、完整命令行)供人工确认,确认后另起一步执行终止;不要在同一条命令里「查完即杀」。
|
||||
- 无法确认归属的进程一律不动,交回用户处理。同机存在多个同类工程时尤其要区分(例如 `infinite-canvas/web/.../vite.js` 与本项目的 `vite.js`)。
|
||||
- 误杀非本项目进程时,必须立即如实告知用户,说明进程名、可能影响与恢复方式,不要轻描淡写。
|
||||
|
||||
@@ -53,7 +53,7 @@ mkdir -p .local/project-workbench-debug .local/cache/go-build .local/cache/go-mo
|
||||
|
||||
# 终端一:后端
|
||||
cd backend
|
||||
CANVAS_BACKEND_ADDR=127.0.0.1:8080 \
|
||||
CANVAS_BACKEND_ADDR=127.0.0.1:7381 \
|
||||
CANVAS_BACKEND_DATA_DIR=../.local/project-workbench-debug \
|
||||
GOCACHE=../.local/cache/go-build \
|
||||
GOMODCACHE=../.local/cache/go-mod \
|
||||
@@ -65,7 +65,9 @@ bun install --frozen-lockfile
|
||||
bun run dev
|
||||
```
|
||||
|
||||
打开 <http://localhost:3000>。首次使用时注册管理员账号,并在设置中配置模型渠道。前端默认将 `/api` 代理到 `http://127.0.0.1:8080`;如需修改代理目标,可设置 `VITE_API_PROXY_TARGET`。
|
||||
打开 <http://localhost:7380>。首次使用时注册管理员账号,并在设置中配置模型渠道。前端默认将 `/api` 代理到 `http://127.0.0.1:7381`;如需修改代理目标,可设置 `VITE_API_PROXY_TARGET`。
|
||||
|
||||
> **本项目端口约定**:本地开发使用前端 **7380** / 后端 **7381**,Docker 宿主机端口为 **7380**(容器内仍为上游默认的 3000/8080)。这样可与同机上的 `infinite-canvas`、`open-ai-canvas` 等工程并存。详见 [AGENTS.md](./AGENTS.md) 的「本项目附加约定」。
|
||||
|
||||
Windows PowerShell 用户可在仓库根目录执行:
|
||||
|
||||
|
||||
@@ -67,7 +67,8 @@ func run(ctx context.Context) error {
|
||||
}
|
||||
|
||||
repo := repository.New(db)
|
||||
addr := env("CANVAS_BACKEND_ADDR", ":8080")
|
||||
// 本项目本地开发端口 7381,避开上游默认的 8080(见 AGENTS.md「本项目附加约定」)。
|
||||
addr := env("CANVAS_BACKEND_ADDR", ":7381")
|
||||
svc := service.New(repo, dataDir)
|
||||
if updaterToken := strings.TrimSpace(os.Getenv("CANVAS_UPDATER_TOKEN")); updaterToken != "" {
|
||||
svc.ConfigureUpdateManager(updaterclient.New(env("CANVAS_UPDATER_SOCKET", "/run/open-ai-canvas-updater/updater.sock"), updaterToken))
|
||||
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
CANVAS_REGISTRATION_ENABLED: ${CANVAS_REGISTRATION_ENABLED:-false}
|
||||
CANVAS_ALLOW_PRIVATE_UPSTREAMS: ${CANVAS_ALLOW_PRIVATE_UPSTREAMS:-false}
|
||||
CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS: ${CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS:-}
|
||||
CANVAS_CORS_ORIGINS: ${CANVAS_CORS_ORIGINS:-http://localhost:3000}
|
||||
CANVAS_CORS_ORIGINS: ${CANVAS_CORS_ORIGINS:-http://localhost:7380}
|
||||
# 服务器访问地址:Agent 看图与生成参考图都靠它签发上游可取到的短时链接。
|
||||
CANVAS_PUBLIC_BASE_URL: ${CANVAS_PUBLIC_BASE_URL:-}
|
||||
GIN_MODE: debug
|
||||
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
CANVAS_REGISTRATION_ENABLED: ${CANVAS_REGISTRATION_ENABLED:-false}
|
||||
CANVAS_ALLOW_PRIVATE_UPSTREAMS: ${CANVAS_ALLOW_PRIVATE_UPSTREAMS:-false}
|
||||
CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS: ${CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS:-}
|
||||
CANVAS_CORS_ORIGINS: ${CANVAS_CORS_ORIGINS:-http://localhost:3000}
|
||||
CANVAS_CORS_ORIGINS: ${CANVAS_CORS_ORIGINS:-http://localhost:7380}
|
||||
# 服务器访问地址:Agent 看图与生成参考图都靠它签发上游可取到的短时链接。
|
||||
CANVAS_PUBLIC_BASE_URL: ${CANVAS_PUBLIC_BASE_URL:-}
|
||||
ENABLE_PROVIDER_PLUGINS: ${ENABLE_PROVIDER_PLUGINS:-false}
|
||||
@@ -40,7 +40,7 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "7380:3000"
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
CANVAS_REGISTRATION_ENABLED: ${CANVAS_REGISTRATION_ENABLED:-false}
|
||||
CANVAS_ALLOW_PRIVATE_UPSTREAMS: ${CANVAS_ALLOW_PRIVATE_UPSTREAMS:-false}
|
||||
CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS: ${CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS:-}
|
||||
CANVAS_CORS_ORIGINS: ${CANVAS_CORS_ORIGINS:-http://localhost:3000}
|
||||
CANVAS_CORS_ORIGINS: ${CANVAS_CORS_ORIGINS:-http://localhost:7380}
|
||||
# 服务器访问地址:Agent 看图与生成参考图都靠它签发上游可取到的短时链接。
|
||||
CANVAS_PUBLIC_BASE_URL: ${CANVAS_PUBLIC_BASE_URL:-}
|
||||
GIN_MODE: release
|
||||
@@ -33,7 +33,7 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "7380:3000"
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
|
||||
@@ -70,19 +70,19 @@ $dataDirLiteral = ConvertTo-PowerShellLiteral $dataDir
|
||||
$backendCommand = @"
|
||||
`$ErrorActionPreference = 'Stop'
|
||||
Set-Location -LiteralPath $backendDirLiteral
|
||||
`$env:CANVAS_BACKEND_ADDR = '127.0.0.1:8080'
|
||||
`$env:CANVAS_BACKEND_ADDR = '127.0.0.1:7381'
|
||||
`$env:CANVAS_BACKEND_DATA_DIR = $dataDirLiteral
|
||||
`$env:GOCACHE = $(ConvertTo-PowerShellLiteral $goBuildCache)
|
||||
`$env:GOMODCACHE = $(ConvertTo-PowerShellLiteral $goModuleCache)
|
||||
Write-Host '影策后端:http://127.0.0.1:8080' -ForegroundColor Cyan
|
||||
Write-Host '影策后端:http://127.0.0.1:7381' -ForegroundColor Cyan
|
||||
go run ./cmd/server
|
||||
"@
|
||||
|
||||
$webCommand = @"
|
||||
`$ErrorActionPreference = 'Stop'
|
||||
Set-Location -LiteralPath $webDirLiteral
|
||||
`$env:VITE_API_PROXY_TARGET = 'http://127.0.0.1:8080'
|
||||
Write-Host '影策前端:http://localhost:3000' -ForegroundColor Cyan
|
||||
`$env:VITE_API_PROXY_TARGET = 'http://127.0.0.1:7381'
|
||||
Write-Host '影策前端:http://localhost:7380' -ForegroundColor Cyan
|
||||
bun run dev
|
||||
"@
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host 0.0.0.0 --port 3000",
|
||||
"dev": "vite --host 0.0.0.0 --port 7380",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"pretest": "bun test test/tiptap-dependency-versions.test.ts test/admin-ui-regressions.test.ts test/announcement-prompt-regressions.test.ts test/password-reset.test.ts test/oss-settings.test.ts test/channel-model-editor-form.test.ts test/channel-model-price-tier-form.test.ts test/admin-logical-models.test.ts && bun test test/canvas-grid-viewport.test.tsx",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test:canvas": "bun test test/canvas-media-performance.test.ts test/canvas-node-title-interaction.test.ts test/canvas-spatial-index.test.ts",
|
||||
"test": "bun test",
|
||||
"test:director:e2e": "bun scripts/director-p0-chrome-e2e.mjs",
|
||||
"start": "vite preview --host 0.0.0.0 --port 3000",
|
||||
"start": "vite preview --host 0.0.0.0 --port 7380",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"lint": "eslint src test"
|
||||
|
||||
@@ -7,7 +7,9 @@ import { defineConfig } from "vite";
|
||||
const webDir = dirname(fileURLToPath(import.meta.url));
|
||||
const appVersion = process.env.CANVAS_BUILD_VERSION?.trim() || readFileSync(resolve(webDir, "../VERSION"), "utf8").trim();
|
||||
const appChangelog = readFileSync(resolve(webDir, "../CHANGELOG.md"), "utf8");
|
||||
const apiProxyTarget = process.env.VITE_API_PROXY_TARGET?.trim() || "http://127.0.0.1:8080";
|
||||
// 本项目本地开发端口:前端 7380、后端 7381(见 AGENTS.md「本项目附加约定」)。
|
||||
// 避开上游默认的 3000 / 8080,以便与 infinite-canvas、open-ai-canvas 等同机工程并存。
|
||||
const apiProxyTarget = process.env.VITE_API_PROXY_TARGET?.trim() || "http://127.0.0.1:7381";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
|
||||
Reference in New Issue
Block a user