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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**Infinite-Canvas (AI Studio)** — a monolithic AI image/video/LLM generation platform supporting multiple API providers through a unified UI. Single-developer project, Chinese-language primary audience.

## Architecture

```
main.py — FastAPI monolith (~11,700 lines): API routes, data models, all business logic
static/ — Frontend: vanilla HTML/JS/CSS (no bundler, no framework)
index.html — Main studio shell (SPA with iframe-based page routing)
canvas.html — Node-based workflow canvas for image/video generation pipelines
smart-canvas.html — Chat-like AI composer with inline image generation
gpt-chat.html — LLM chat interface
enhance.html — Image enhancement/upscaling
klein.html — Flux2-Klein model interface
zimage.html — Z-Image model interface
online.html — Online API image generation
angle.html — ModelScope angle control
api-settings.html — API provider configuration UI
asset-manager.html — Local asset library management
comfyui-settings.html — Local ComfyUI instance management
js/ — Page-specific JS modules (canvas.js, smart-canvas.js, etc.)
js/i18n/ — Internationalization (zh-CN + en), loaded by i18n.js
vendor/ — Locally mirrored third-party libs (Tailwind CSS, Lucide icons, Three.js)
system-prompts/ — Markdown prompt templates for smart-canvas
runninghub/ — Static RunningHub provider config + thumbnails
data/ — JSON file storage (api_providers, conversations, canvases, prompt libraries, etc.)
API/ — `.env` file for API keys (gitignored)
assets/ — input/output/library/uploads directories for generated/uploaded media
workflows/ — ComfyUI workflow JSON files
packages/ — Offline pip wheel cache for portable Python
python/ — Bundled portable Python runtime (Windows)
tools/ — PowerShell scripts for Jimeng CLI install/login
```

## Running the Project

```bash
# Windows — double-click run.bat or:
python\python.exe main.py

# macOS — double-click mac-启动服务.command or:
python3 main.py

# The server starts on http://127.0.0.1:3000/
```

No build step. The frontend is static HTML served by FastAPI's `StaticFiles` mount. CDN dependencies are mirrored locally in `static/vendor/` for offline use.

## Key Technical Details

### Backend (`main.py`)

- **Framework**: FastAPI with CORS middleware (allow all origins), WebSocket support for live stats
- **Data persistence**: JSON files in `data/` directory, protected by per-resource `threading.Lock` instances
- **API providers** are configured in `data/api_providers.json`, managed via `/api/providers` endpoints. Provider protocols: `openai`, `apimart`, `gemini`, `volcengine`, `runninghub`, `jimeng`
- **API keys** stored in `API/.env` (key=value format), read via `load_env_file()`
- **Image generation flow**: `/api/online-image` (single) or `/api/canvas-image-tasks` (batched, sequential queue with `QUEUE_LOCK`)
- **Video generation**: `/api/canvas-video` with provider-specific dispatch (Volcengine Ark, Jimeng/dreamina CLI, RunningHub, OpenAI-compatible)
- **LLM chat**: `/api/canvas-llm` and `/api/conversations` endpoints, conversation state stored as JSON files
- **Local ComfyUI**: Polls configurable ComfyUI instances (`COMFYUI_INSTANCES` list), proxy image viewing through `/api/view`
- **ModelScope**: API calls to `modelscope.cn` for free model access, uses repo file API (not raw web)
- **Jimeng (即梦)**: CLI-based integration — spawns `dreamina` as subprocess for login, submit, and poll
- **DashScope Qwen**: `generate_dashscope_qwen_image()` for Aliyun DashScope Qwen image generation. `is_qwen_image_model()` and `is_dashscope_image_provider()` added for provider dispatch
- **GPT Image**: `is_gpt_image_model()` generalizes the old `is_gpt_image_2_model()` to support all GPT image models. Multipart form uses `image[]` field name when multi-image
- **Auto-update**: `/api/check-update` checks GitHub/ModelScope for new VERSION; `/api/update-from-github` stages and applies updates with rollback support
- **App version** stored in `VERSION` file (format: `YYYY.MM.DD`), automatically appended as query param to static assets for cache busting

### Frontend

- **No framework** — vanilla JS with DOM manipulation
- **Tailwind CSS** loaded from local mirror (`static/vendor/js/tailwindcss-cdn.js`)
- **Icons**: Lucide (local mirror)
- **3D**: Three.js 0.160.0 (local mirror) — used in canvas for node graph visualization
- **i18n**: Custom system in `static/js/i18n/` — `StudioI18n` global, translations loaded as JS modules. `tr(key)` for translation, `langIsEn()` for language check
- **Theme**: Dark/light via CSS custom properties on `html.theme-dark`, toggled by `theme.js`
- **Inter-page communication**: `window.postMessage` for cross-iframe events (lang change, canvas updates, provider changes)
- **Version cache busting**: Static assets get `?v=<VERSION>` query strings generated by `versioned_static_html()` in Python

### Data Model

- **Canvas save/sync**: Uses optimistic concurrency — `saveCanvas()` sends `base_updated_at`, server returns 409 if stale (another tab saved first). `touchCanvasOpened()` bumps `updated_at` on open. Polling (`checkRemoteCanvasVersion()`) checks `/api/canvases/{id}/meta` every 2.5s. WebSocket broadcasts ignored when `client_id` matches own `CLIENT_ID`.
- **Event delegation**: Node hover detection uses `board mousemove` + `e.target.closest('.node')` — no per-element listeners. Drag/resize/knife modes skip hover to avoid conflicts. in `data/canvases/<id>.json`. Node types:
- `image` — reference image (paste/drag/upload)
- `prompt` — text prompt
- `generator` — API image generation (OpenAI-compatible providers)
- `msgen` — ModelScope free image generation (Z-Image, Qwen-Edit, custom models)
- `rh` — RunningHub workflow/AI app execution
- `comfy` — Local ComfyUI (text-to-image, enhance, edit, custom workflow)
- `ltxDirector` — ComfyUI LTXDirector video with multi-segment timeline
- `video` — API video generation
- `llm` — LLM chat node
- `output` — Collects generated images/videos from upstream nodes
- `group` / `promptGroup` — Logical grouping of nodes
- `loop` — Serial/parallel batch execution with configurable count
- Output nodes now display `providerLabel` and `modelLabel` tags on each image (set in `appendOutputImages()`)
- Link hover highlighting via `hoveredNodeId` in board `mousemove` event delegation (`renderLinks()` adds `link-hover` class)
- **Asset Library**: `data/asset_library.json` — metadata index for files in `assets/library/`
- **Prompt Libraries**: `data/prompt_libraries.json` — categorized prompt templates
- **History**: `history.json` — task execution log with results
- **Conversations**: `data/conversations/<id>.json` — LLM chat history

## File Size Warning

`main.py` is ~11,700 lines. When editing, use targeted search (Grep) to locate the relevant section. Major section markers (comments like `# --- 路由接口 ---`) help navigation. The file is too large to read in one operation — always use `offset`/`limit` parameters.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ https://www.fhl.mom/register?aff=86L574B4T2N9 (包含codex和GPT image 2模
3. 火山引擎调用(人脸认证还在修复bug)
4. Modelscope免费LLM模型和图像模型调用
5. 即梦CLI调用,可直接调用即梦高级会员的积分,支持文生图/图生图/文生视频/图生视频
6. 支持调用本地局域网的ComfyUI
7. 扩展图片/360全景图预览截图/视频帧抽取/循环节点等诸多功能
6. 支持阿里云百炼 DashScope 兼容模式下的 LLM 调用,并对 `qwen-image-*` 图片模型自动走千问原生图片生成/编辑接口
7. 支持调用本地局域网的ComfyUI
8. 扩展图片/360全景图预览截图/视频帧抽取/循环节点等诸多功能

--------

Expand Down
157 changes: 157 additions & 0 deletions graphify-out/GRAPH_REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Graph Report - d:/ziyong/Infinite-Canvas (2026-06-07)

## Corpus Check
- 56 files · ~953,777 words
- Verdict: corpus is large enough that graph structure adds value.

## Summary
- 5379 nodes · 14474 edges · 25 communities detected
- Extraction: 37% EXTRACTED · 63% INFERRED · 0% AMBIGUOUS · INFERRED: 9060 edges (avg confidence: 0.5)
- Token cost: 0 input · 0 output

## God Nodes (most connected - your core abstractions)
1. `tr()` - 106 edges
2. `tr()` - 92 edges
3. `Vector3` - 76 edges
4. `push()` - 62 edges
5. `render()` - 59 edges
6. `map()` - 59 edges
7. `render()` - 56 edges
8. `handleClick()` - 56 edges
9. `scheduleSave()` - 55 edges
10. `Vector2` - 55 edges

## Surprising Connections (you probably didn't know these)
- None detected - all connections are within the same source files.

## Communities

### Community 0 - "Three.js Object Helpers"
Cohesion: 0.0
Nodes (92): ArrowHelper, AxesHelper, BatchedMesh, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper (+84 more)

### Community 1 - "Smart Canvas Composer"
Cohesion: 0.01
Nodes (734): activeAssetCategory(), activeAssetLibrary(), activeComposerNode(), activeInputImagesFor(), activePromptLibrary(), activePromptTemplateGroups(), activePromptTemplateNodeId(), activeSettingsSubject() (+726 more)

### Community 2 - "Three.js Core Primitives"
Cohesion: 0.0
Nodes (267): addContour(), addUniform(), allocTexUnits(), AmbientLight, AnimationClip, AnimationLoader, AnimationObjectGroup, ArcCurve (+259 more)

### Community 3 - "Canvas Workflow Graph"
Cohesion: 0.01
Nodes (698): actionFailed(), activeCanvasAssetCategory(), activeCanvasAssetLibrary(), activeCanvasMediaCategory(), activeCanvasPromptLibrary(), activeCanvasPromptLibraryItems(), activeCanvasPromptTemplateGroups(), activeCanvasWorkflowCategory() (+690 more)

### Community 4 - "FastAPI Backend Core"
Cohesion: 0.01
Nodes (689): BaseModel, Exception, add_asset_library_item(), add_prompt_library_category(), add_prompt_library_item(), ai_config(), AIReference, api_headers() (+681 more)

### Community 5 - "Tailwind CSS Library"
Cohesion: 0.01
Nodes (510): _a(), aa(), ac(), add(), addToError(), Ae(), after(), Ah() (+502 more)

### Community 6 - "API Provider Settings"
Cohesion: 0.03
Nodes (170): addModel(), addMsLora(), addProvider(), applyDetectedProtocol(), applyModelPicker(), applyProviderOnboardingDefaults(), applyRhEditorGraphTransform(), applyRhImageSlotDefaults() (+162 more)

### Community 7 - "Asset Manager UI"
Cohesion: 0.04
Nodes (167): activeAssetCategory(), activeAssetLibrary(), activeAvatarProvider(), activeLocalFolder(), activePromptCategories(), activePromptLibrary(), activeWorkflowCategory(), activeWorkflowLibrary() (+159 more)

### Community 8 - "Three.js Animation"
Cohesion: 0.02
Nodes (11): AnimationAction, AnimationMixer, Audio, AudioAnalyser, AudioListener, CubicInterpolant, DiscreteInterpolant, Interpolant (+3 more)

### Community 9 - "ComfyUI Instance Settings"
Cohesion: 0.06
Nodes (78): addComfyInstance(), addDropdownOption(), addMiniNode(), applyActiveRandomValues(), applyGraphTransform(), applyLanguage(), attachPanZoom(), bindMiniCanvas() (+70 more)

### Community 10 - "LTX Director Timeline"
Cohesion: 0.1
Nodes (6): beforeRegisterNodeDef(), clamp(), hideWidget(), isCanvasLTXNode(), parseInitial(), TimelineEditor

### Community 11 - "Three.js Math Utils"
Cohesion: 0.06
Nodes (3): Euler, makeClipAdditive(), Quaternion

### Community 12 - "Agent HTML Builder"
Cohesion: 0.18
Nodes (18): build(), export_config(), extract_summary(), find_callout(), infer_meta(), _inline_md(), main(), md_to_html() (+10 more)

### Community 13 - "Theme System"
Cohesion: 0.23
Nodes (13): applyScale(), applyTheme(), autoScale(), broadcastScale(), currentScaleMode(), ensureScaleStyle(), isFramed(), normalizeScaleMode() (+5 more)

### Community 14 - "get-pip Bootstrap"
Cohesion: 0.31
Nodes (9): bootstrap(), determine_pip_install_arguments(), include_setuptools(), include_wheel(), main(), monkeypatch_for_cert(), Install setuptools only if absent, not excluded and when using Python <3.12., Install wheel only if absent, not excluded and when using Python <3.12. (+1 more)

### Community 15 - "Lucide Icon Library"
Cohesion: 0.36
Nodes (8): Ba(), cA(), dA(), iA(), ka(), MA(), Pa(), za()

### Community 16 - "i18n Core Engine"
Cohesion: 0.39
Nodes (7): apply(), entries(), lang(), register(), set(), t(), toggle()

### Community 17 - "Jimeng CLI Installer"
Cohesion: 0.48
Nodes (4): Convert-ToWslPath(), Invoke-WslScript(), Invoke-WslScriptCapture(), New-WslScriptFile()

### Community 18 - "History Bulk Manager"
Cohesion: 0.6
Nodes (4): attach(), fmt(), injectStyles(), tr()

### Community 19 - "Jimeng CLI Login"
Cohesion: 0.6
Nodes (3): Convert-ToWslPath(), Invoke-WslScript(), New-WslScriptFile()

### Community 20 - "Image Preview Utility"
Cohesion: 0.67
Nodes (0):

### Community 21 - "i18n Module Loader"
Cohesion: 1.0
Nodes (0):

### Community 22 - "i18n Common Strings"
Cohesion: 1.0
Nodes (0):

### Community 23 - "i18n Studio Strings"
Cohesion: 1.0
Nodes (0):

### Community 24 - "i18n Validator"
Cohesion: 1.0
Nodes (0):

## Knowledge Gaps
- **105 isolated node(s):** `Install setuptools only if absent, not excluded and when using Python <3.12.`, `Install wheel only if absent, not excluded and when using Python <3.12.`, `Patches `pip install` to provide default certificate with the lowest priority.`, `首次运行时提前创建配置目录,避免第一次保存 API Key 时才创建目录/文件。`, `保存 API 设置后,将 os.environ 里最新的值同步回模块级全局变量, 避免保存后需要重启才能生效。` (+100 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **Thin community `i18n Module Loader`** (1 nodes): `i18n.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `i18n Common Strings`** (1 nodes): `common.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `i18n Studio Strings`** (1 nodes): `studio.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `i18n Validator`** (1 nodes): `validate-i18n.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.

## Suggested Questions
_Questions this graph is uniquely positioned to answer:_

- **Why does `Vector3` connect `Three.js Object Helpers` to `Three.js Core Primitives`?**
_High betweenness centrality (0.008) - this node is a cross-community bridge._
- **Why does `Vector2` connect `Three.js Object Helpers` to `Three.js Core Primitives`?**
_High betweenness centrality (0.007) - this node is a cross-community bridge._
- **Why does `Vector4` connect `Three.js Object Helpers` to `Three.js Core Primitives`?**
_High betweenness centrality (0.006) - this node is a cross-community bridge._
- **Are the 105 inferred relationships involving `tr()` (e.g. with `performUndo()` and `trf()`) actually correct?**
_`tr()` has 105 INFERRED edges - model-reasoned connections that need verification._
- **Are the 91 inferred relationships involving `tr()` (e.g. with `trf()` and `actionFailed()`) actually correct?**
_`tr()` has 91 INFERRED edges - model-reasoned connections that need verification._
- **Are the 61 inferred relationships involving `push()` (e.g. with `warn()` and `ve()`) actually correct?**
_`push()` has 61 INFERRED edges - model-reasoned connections that need verification._
- **Are the 58 inferred relationships involving `render()` (e.g. with `performUndo()` and `renderMinimap()`) actually correct?**
_`render()` has 58 INFERRED edges - model-reasoned connections that need verification._
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"nodes": [{"id": "smart_canvas", "label": "smart-canvas.js", "file_type": "code", "source_file": "d:\\ziyong\\Infinite-Canvas\\static\\js\\i18n\\smart-canvas.js", "source_location": "L1"}], "edges": []}
Loading