Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-04-15 23:15:25 +08:00
59 changed files with 97424 additions and 334 deletions

View File

@@ -0,0 +1,41 @@
---
name: defuddle
description: Extract clean markdown content from web pages using Defuddle CLI, removing clutter and navigation to save tokens. Use instead of WebFetch when the user provides a URL to read or analyze, for online documentation, articles, blog posts, or any standard web page. Do NOT use for URLs ending in .md — those are already markdown, use WebFetch directly.
---
# Defuddle
Use Defuddle CLI to extract clean readable content from web pages. Prefer over WebFetch for standard web pages — it removes navigation, ads, and clutter, reducing token usage.
If not installed: `npm install -g defuddle`
## Usage
Always use `--md` for markdown output:
```bash
defuddle parse <url> --md
```
Save to file:
```bash
defuddle parse <url> --md -o content.md
```
Extract specific metadata:
```bash
defuddle parse <url> -p title
defuddle parse <url> -p description
defuddle parse <url> -p domain
```
## Output formats
| Flag | Format |
|------|--------|
| `--md` | Markdown (default choice) |
| `--json` | JSON with both HTML and markdown |
| (none) | HTML |
| `-p <name>` | Specific metadata property |

View File

@@ -0,0 +1,476 @@
---
name: excalidraw-diagram
description: Generate Excalidraw diagrams from text content. Supports three output modes - Obsidian (.md), Standard (.excalidraw), and Animated (.excalidraw with animation order). Triggers on "Excalidraw", "画图", "流程图", "思维导图", "可视化", "diagram", "标准Excalidraw", "standard excalidraw", "Excalidraw动画", "动画图", "animate".
metadata:
version: 1.2.1
---
# Excalidraw Diagram Generator
Create Excalidraw diagrams from text content with multiple output formats.
## Output Modes
根据用户的触发词选择输出模式:
| 触发词 | 输出模式 | 文件格式 | 用途 |
|--------|----------|----------|------|
| `Excalidraw``画图``流程图``思维导图` | **Obsidian**(默认) | `.md` | 在 Obsidian 中直接打开 |
| `标准Excalidraw``standard excalidraw` | **Standard** | `.excalidraw` | 在 excalidraw.com 打开/编辑/分享 |
| `Excalidraw动画``动画图``animate` | **Animated** | `.excalidraw` | 拖到 excalidraw-animate 生成动画 |
## Workflow
1. **Detect output mode** from trigger words (see Output Modes table above)
2. Analyze content - identify concepts, relationships, hierarchy
3. Choose diagram type (see Diagram Types below)
4. Generate Excalidraw JSON (add animation order if Animated mode)
5. Output in correct format based on mode
6. **Automatically save to current working directory**
7. Notify user with file path and usage instructions
## Output Formats
### Mode 1: Obsidian Format (Default)
**严格按照以下结构输出,不得有任何修改:**
```markdown
---
excalidraw-plugin: parsed
tags: [excalidraw]
---
==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: 'Decompress current Excalidraw file'. For more info check in plugin settings under 'Saving'
# Excalidraw Data
## Text Elements
%%
## Drawing
\`\`\`json
{JSON 完整数据}
\`\`\`
%%
```
**关键要点:**
- Frontmatter 必须包含 `tags: [excalidraw]`
- 警告信息必须完整
- JSON 必须被 `%%` 标记包围
- 不能使用 `excalidraw-plugin: parsed` 以外的其他 frontmatter 设置
- **文件扩展名**`.md`
### Mode 2: Standard Excalidraw Format
直接输出纯 JSON 文件,可在 excalidraw.com 打开:
```json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [...],
"appState": {
"gridSize": null,
"viewBackgroundColor": "#ffffff"
},
"files": {}
}
```
**关键要点:**
- `source` 使用 `https://excalidraw.com`(不是 Obsidian 插件)
- 纯 JSON无 Markdown 包装
- **文件扩展名**`.excalidraw`
### Mode 3: Animated Excalidraw Format
与 Standard 格式相同,但每个元素添加 `customData.animate` 字段控制动画顺序:
```json
{
"id": "element-1",
"type": "rectangle",
"customData": {
"animate": {
"order": 1,
"duration": 500
}
},
...
}
```
**动画顺序规则:**
- `order`: 动画播放顺序1, 2, 3...),数字越小越先出现
- `duration`: 该元素的绘制时长(毫秒),默认 500
- 相同 `order` 的元素同时出现
- 建议顺序:标题 → 主要框架 → 连接线 → 细节文字
**使用方法:**
1. 生成 `.excalidraw` 文件
2. 拖到 https://dai-shi.github.io/excalidraw-animate/
3. 点击 Animate 预览,然后导出 SVG 或 WebM
**文件扩展名**`.excalidraw`
---
## Diagram Types & Selection Guide
选择合适的图表形式,以提升理解力与视觉吸引力。
| 类型 | 英文 | 使用场景 | 做法 |
|------|------|---------|------|
| **流程图** | Flowchart | 步骤说明、工作流程、任务执行顺序 | 用箭头连接各步骤,清晰表达流程走向 |
| **思维导图** | Mind Map | 概念发散、主题分类、灵感捕捉 | 以中心为核心向外发散,放射状结构 |
| **层级图** | Hierarchy | 组织结构、内容分级、系统拆解 | 自上而下或自左至右构建层级节点 |
| **关系图** | Relationship | 要素之间的影响、依赖、互动 | 图形间用连线表示关联,箭头与说明 |
| **对比图** | Comparison | 两种以上方案或观点的对照分析 | 左右两栏或表格形式,标明比较维度 |
| **时间线图** | Timeline | 事件发展、项目进度、模型演化 | 以时间为轴,标出关键时间点与事件 |
| **矩阵图** | Matrix | 双维度分类、任务优先级、定位 | 建立 X 与 Y 两个维度,坐标平面安置 |
| **自由布局** | Freeform | 内容零散、灵感记录、初步信息收集 | 无需结构限制,自由放置图块与箭头 |
## Design Rules
### Text & Format
- **所有文本元素必须使用** `fontFamily: 5`Excalifont 手写字体)
- **文本中的双引号替换规则**`"` 替换为 `『』`
- **文本中的圆括号替换规则**`()` 替换为 `「」`
- **字体大小规则**(硬性下限,低于此值在正常缩放下不可读):
- 标题20-28px最小 20px
- 副标题18-20px
- 正文/标签16-18px最小 16px
- 次要注释14px仅限不重要的辅助说明慎用
- **绝对禁止低于 14px**
- **行高**:所有文本使用 `lineHeight: 1.25`
- **文字居中估算**:独立文本元素没有自动居中,需手动计算 x 坐标:
- 估算文字宽度:`estimatedWidth = text.length * fontSize * 0.5`CJK 字符用 `* 1.0`
- 居中公式:`x = centerX - estimatedWidth / 2`
- 示例:文字 "Hello"5字符, fontSize 20居中于 x=300 → `estimatedWidth = 5 * 20 * 0.5 = 50``x = 300 - 25 = 275`
### Layout & Design
- **画布范围**:建议所有元素在 0-1200 x 0-800 区域内
- **最小形状尺寸**:带文字的矩形/椭圆不小于 120x60px
- **元素间距**:最小 20-30px 间距,防止重叠
- **层次清晰**:使用不同颜色和形状区分不同层级的信息
- **图形元素**:适当使用矩形框、圆形、箭头等元素来组织信息
- **禁止 Emoji**:不要在图表文本中使用任何 Emoji 符号,如需视觉标记请使用简单图形(圆形、方形、箭头)或颜色区分
### Color Palette
**文字颜色strokeColor for text**
| 用途 | 色值 | 说明 |
|------|------|------|
| 标题 | `#1e40af` | 深蓝 |
| 副标题/连接线 | `#3b82f6` | 亮蓝 |
| 正文文字 | `#374151` | 深灰(白底最浅不低于 `#757575` |
| 强调/重点 | `#f59e0b` | 金色 |
**形状填充色backgroundColor, fillStyle: "solid"**
| 色值 | 语义 | 适用场景 |
|------|------|---------|
| `#a5d8ff` | 浅蓝 | 输入、数据源、主要节点 |
| `#b2f2bb` | 浅绿 | 成功、输出、已完成 |
| `#ffd8a8` | 浅橙 | 警告、待处理、外部依赖 |
| `#d0bfff` | 浅紫 | 处理中、中间件、特殊项 |
| `#ffc9c9` | 浅红 | 错误、关键、告警 |
| `#fff3bf` | 浅黄 | 备注、决策、规划 |
| `#c3fae8` | 浅青 | 存储、数据、缓存 |
| `#eebefa` | 浅粉 | 分析、指标、统计 |
**区域背景色(大矩形 + opacity: 30用于分层图表**
| 色值 | 语义 |
|------|------|
| `#dbe4ff` | 前端/UI 层 |
| `#e5dbff` | 逻辑/处理层 |
| `#d3f9d8` | 数据/工具层 |
**对比度规则:**
- 白底上文字最浅不低于 `#757575`,否则不可读
- 浅色填充上用深色变体文字(如浅绿底用 `#15803d`,不用 `#22c55e`
- 避免浅灰色文字(`#b0b0b0``#999`)出现在白底上
参考:[references/excalidraw-schema.md](references/excalidraw-schema.md)
## JSON Structure
**Obsidian 模式:**
```json
{
"type": "excalidraw",
"version": 2,
"source": "https://github.com/zsviczian/obsidian-excalidraw-plugin",
"elements": [...],
"appState": { "gridSize": null, "viewBackgroundColor": "#ffffff" },
"files": {}
}
```
**Standard / Animated 模式:**
```json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [...],
"appState": { "gridSize": null, "viewBackgroundColor": "#ffffff" },
"files": {}
}
```
## Element Template
Each element requires these fields (do NOT add extra fields like `frameId`, `index`, `versionNonce`, `rawText` -- they may cause issues on excalidraw.com. `boundElements` must be `null` not `[]`, `updated` must be `1` not timestamps):
```json
{
"id": "unique-id",
"type": "rectangle",
"x": 100, "y": 100,
"width": 200, "height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"groupIds": [],
"roundness": {"type": 3},
"seed": 123456789,
"version": 1,
"isDeleted": false,
"boundElements": null,
"updated": 1,
"link": null,
"locked": false
}
```
`strokeStyle` values: `"solid"`(实线,默认)| `"dashed"`(虚线)| `"dotted"`(点线)。虚线适合表示可选路径、异步流、弱关联等。
Text elements add:
```json
{
"text": "显示文本",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": null,
"originalText": "显示文本",
"autoResize": true,
"lineHeight": 1.25
}
```
**Animated 模式额外添加** `customData` 字段:
```json
{
"id": "title-1",
"type": "text",
"customData": {
"animate": {
"order": 1,
"duration": 500
}
},
...
}
```
See [references/excalidraw-schema.md](references/excalidraw-schema.md) for all element types.
---
## Additional Technical Requirements
### Text Elements 处理
- `## Text Elements` 部分在 Markdown 中**必须留空**,仅用 `%%` 作为分隔符
- Obsidian ExcaliDraw 插件会根据 JSON 数据**自动填充文本元素**
- 不需要手动列出所有文本内容
### 坐标与布局
- **坐标系统**:左上角为原点 (0,0)
- **推荐范围**:所有元素在 0-1200 x 0-800 像素范围内
- **元素 ID**:每个元素需要唯一的 `id`可以是字符串如「title」「box1」等
### Required Fields for All Elements
**IMPORTANT**: Do NOT include `frameId`, `index`, `versionNonce`, or `rawText` fields. Use `boundElements: null` (not `[]`), and `updated: 1` (not timestamps).
```json
{
"id": "unique-identifier",
"type": "rectangle|text|arrow|ellipse|diamond",
"x": 100, "y": 100,
"width": 200, "height": 50,
"angle": 0,
"strokeColor": "#color-hex",
"backgroundColor": "transparent|#color-hex",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid|dashed|dotted",
"roughness": 1,
"opacity": 100,
"groupIds": [],
"roundness": {"type": 3},
"seed": 123456789,
"version": 1,
"isDeleted": false,
"boundElements": null,
"updated": 1,
"link": null,
"locked": false
}
```
### Text-Specific Properties
文本元素 (type: "text") 需要额外属性do NOT include `rawText`
```json
{
"text": "显示文本",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": null,
"originalText": "显示文本",
"autoResize": true,
"lineHeight": 1.25
}
```
### appState 配置
```json
"appState": {
"gridSize": null,
"viewBackgroundColor": "#ffffff"
}
```
### files 字段
```json
"files": {}
```
## Common Mistakes to Avoid
- **文字偏移** — 独立 text 元素的 `x` 是左边缘,不是中心。必须用居中公式手动计算,否则文字会偏到一边
- **元素重叠** — y 坐标相近的元素容易堆叠。放置新元素前检查与周围元素是否有至少 20px 间距
- **画布留白不足** — 内容不要贴着画布边缘。在四周留 50-80px 的 padding
- **标题没有居中于图表** — 标题应居中于下方图表的整体宽度,不是固定在 x=0
- **箭头标签溢出** — 长文字标签(如 "ATP + NADPH")会超出短箭头。保持标签简短或加大箭头长度
- **对比度不够** — 浅色文字在白底上几乎不可见。文字颜色不低于 `#757575`,有色文字用深色变体
- **字号太小** — 低于 14px 在正常缩放下不可读,正文最小 16px
## Implementation Notes
### Auto-save & File Generation Workflow
当生成 Excalidraw 图表时,**必须自动执行以下步骤**
#### 1. 选择合适的图表类型
- 根据用户提供的内容特性,参考上方 「Diagram Types & Selection Guide」 表
- 分析内容的核心诉求,选择最合适的可视化形式
#### 2. 生成有意义的文件名
根据输出模式选择文件扩展名:
| 模式 | 文件名格式 | 示例 |
|------|-----------|------|
| Obsidian | `[主题].[类型].md` | `商业模式.relationship.md` |
| Standard | `[主题].[类型].excalidraw` | `商业模式.relationship.excalidraw` |
| Animated | `[主题].[类型].animate.excalidraw` | `商业模式.relationship.animate.excalidraw` |
- 优先使用中文以提高清晰度
#### 3. 使用 Write 工具自动保存文件
- **保存位置**:当前工作目录(自动检测环境变量)
- **完整路径**`{current_directory}/[filename].md`
- 这样可以实现灵活迁移,无需硬编码路径
#### 4. 确保 Markdown 结构完全正确
**必须按以下格式生成**(不能有任何修改):
```markdown
---
excalidraw-plugin: parsed
tags: [excalidraw]
---
==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: 'Decompress current Excalidraw file'. For more info check in plugin settings under 'Saving'
# Excalidraw Data
## Text Elements
%%
## Drawing
\`\`\`json
{完整的 JSON 数据}
\`\`\`
%%
```
#### 5. JSON 数据要求
- 包含完整的 Excalidraw JSON 结构
- 所有文本元素使用 `fontFamily: 5`
- 文本中的 `"` 替换为 `『』`
- 文本中的 `()` 替换为 `「」`
- JSON 格式必须有效,通过语法检查
- 所有元素有唯一的 `id`
- 包含 `appState``files: {}` 字段
#### 6. 用户反馈与确认
向用户报告:
- 图表已生成
- 精确的保存位置
- 如何在 Obsidian 中查看
- 图表的设计选择说明(选择了什么类型的图表、为什么)
- 是否需要调整或修改
### Example Output Messages
**Obsidian 模式:**
```
Excalidraw 图已生成!
保存位置:商业模式.relationship.md
使用方法:
1. 在 Obsidian 中打开此文件
2. 点击右上角 MORE OPTIONS 菜单
3. 选择 Switch to EXCALIDRAW VIEW
```
**Standard 模式:**
```
Excalidraw 图已生成!
保存位置:商业模式.relationship.excalidraw
使用方法:
1. 打开 https://excalidraw.com
2. 点击左上角菜单 → Open → 选择此文件
3. 或直接拖拽文件到 excalidraw.com 页面
```
**Animated 模式:**
```
Excalidraw 动画图已生成!
保存位置:商业模式.relationship.animate.excalidraw
动画顺序:标题(1) → 主框架(2-4) → 连接线(5-7) → 说明文字(8-10)
生成动画:
1. 打开 https://dai-shi.github.io/excalidraw-animate/
2. 点击 Load File 选择此文件
3. 预览动画效果
4. 点击 Export 导出 SVG 或 WebM
```

View File

@@ -0,0 +1,201 @@
# Excalidraw JSON Schema Reference
## Color Palette
### Primary Colors
| Purpose | Color | Hex |
|---------|-------|-----|
| Main Title | Deep Blue | `#1e40af` |
| Subtitle | Medium Blue | `#3b82f6` |
| Body Text | Dark Gray | `#374151` |
| Emphasis | Orange | `#f59e0b` |
| Success | Green | `#10b981` |
| Warning | Red | `#ef4444` |
### Background Colors
| Purpose | Color | Hex |
|---------|-------|-----|
| Light Blue | Background | `#dbeafe` |
| Light Gray | Neutral | `#f3f4f6` |
| Light Orange | Highlight | `#fef3c7` |
| Light Green | Success | `#d1fae5` |
| Light Purple | Accent | `#ede9fe` |
## Element Types
### Rectangle
```json
{
"type": "rectangle",
"id": "unique-id",
"x": 100,
"y": 100,
"width": 200,
"height": 80,
"strokeColor": "#1e40af",
"backgroundColor": "#dbeafe",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 1,
"opacity": 100,
"roundness": { "type": 3 }
}
```
### Text
```json
{
"type": "text",
"id": "unique-id",
"x": 150,
"y": 130,
"text": "Content here",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"strokeColor": "#1e40af",
"backgroundColor": "transparent"
}
```
### Arrow
```json
{
"type": "arrow",
"id": "unique-id",
"x": 300,
"y": 140,
"width": 100,
"height": 0,
"points": [[0, 0], [100, 0]],
"strokeColor": "#374151",
"strokeWidth": 2,
"startArrowhead": null,
"endArrowhead": "arrow"
}
```
### Ellipse
```json
{
"type": "ellipse",
"id": "unique-id",
"x": 100,
"y": 100,
"width": 120,
"height": 120,
"strokeColor": "#10b981",
"backgroundColor": "#d1fae5",
"fillStyle": "solid"
}
```
### Diamond
```json
{
"type": "diamond",
"id": "unique-id",
"x": 100,
"y": 100,
"width": 150,
"height": 100,
"strokeColor": "#f59e0b",
"backgroundColor": "#fef3c7",
"fillStyle": "solid"
}
```
### Line
```json
{
"type": "line",
"id": "unique-id",
"x": 100,
"y": 100,
"points": [[0, 0], [200, 100]],
"strokeColor": "#374151",
"strokeWidth": 2
}
```
## Full JSON Structure
```json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
// Array of elements
],
"appState": {
"gridSize": null,
"viewBackgroundColor": "#ffffff"
},
"files": {}
}
```
## Font Family Values
| Value | Font Name |
|-------|-----------|
| 1 | Virgil (hand-drawn) |
| 2 | Helvetica |
| 3 | Cascadia |
| 4 | Assistant |
| 5 | Excalifont (recommended) |
## Fill Styles
- `solid` - Solid fill
- `hachure` - Hatched lines
- `cross-hatch` - Cross-hatched
- `dots` - Dotted pattern
## Roundness Types
- `{ "type": 1 }` - Sharp corners
- `{ "type": 2 }` - Slight rounding
- `{ "type": 3 }` - Full rounding (recommended)
## Element Binding
To connect text to a container:
```json
{
"type": "rectangle",
"id": "container-id",
"boundElements": [{ "id": "text-id", "type": "text" }]
}
```
```json
{
"type": "text",
"id": "text-id",
"containerId": "container-id"
}
```
## Arrow Binding
To connect arrows to shapes:
```json
{
"type": "arrow",
"startBinding": {
"elementId": "source-shape-id",
"focus": 0,
"gap": 5
},
"endBinding": {
"elementId": "target-shape-id",
"focus": 0,
"gap": 5
}
}
```

View File

@@ -0,0 +1,276 @@
---
name: mermaid-visualizer
description: Transform text content into professional Mermaid diagrams for presentations and documentation. Use when users ask to visualize concepts, create flowcharts, or make diagrams from text. Supports process flows, system architectures, comparisons, mindmaps, and more with built-in syntax error prevention.
---
# Mermaid Visualizer
## Overview
Convert text content into clean, professional Mermaid diagrams optimized for presentations and documentation. Automatically handles common syntax pitfalls (list syntax conflicts, subgraph naming, spacing issues) to ensure diagrams render correctly in Obsidian, GitHub, and other Mermaid-compatible platforms.
## Quick Start
When creating a Mermaid diagram:
1. **Analyze the content** - Identify key concepts, relationships, and flow
2. **Choose diagram type** - Select the most appropriate visualization (see Diagram Types below)
3. **Select configuration** - Determine layout, detail level, and styling
4. **Generate diagram** - Create syntactically correct Mermaid code
5. **Output in markdown** - Wrap in proper code fence with optional explanation
**Default assumptions:**
- Vertical layout (TB) unless horizontal requested
- Medium detail level (balanced between simplicity and information)
- Professional color scheme with semantic colors
- Obsidian/GitHub compatible syntax
## Diagram Types
### 1. Process Flow (graph TB/LR)
**Best for:** Workflows, decision trees, sequential processes, AI agent architectures
**Use when:** Content describes steps, stages, or a sequence of actions
**Key features:**
- Swimlanes via subgraph for grouping related steps
- Arrow labels for transitions
- Feedback loops and branches
- Color-coded stages
**Configuration options:**
- `layout`: "vertical" (TB), "horizontal" (LR)
- `detail`: "simple" (core steps only), "standard" (with descriptions), "detailed" (with annotations)
- `style`: "minimal", "professional", "colorful"
### 2. Circular Flow (graph TD with circular layout)
**Best for:** Cyclic processes, continuous improvement loops, agent feedback systems
**Use when:** Content emphasizes iteration, feedback, or circular relationships
**Key features:**
- Central hub with radiating elements
- Curved feedback arrows
- Clear cycle indicators
### 3. Comparison Diagram (graph TB with parallel paths)
**Best for:** Before/after comparisons, A vs B analysis, traditional vs modern systems
**Use when:** Content contrasts two or more approaches or systems
**Key features:**
- Side-by-side layout
- Central comparison node
- Clear differentiation via color/style
### 4. Mindmap
**Best for:** Hierarchical concepts, knowledge organization, topic breakdowns
**Use when:** Content is hierarchical with clear parent-child relationships
**Key features:**
- Radial tree structure
- Multiple levels of nesting
- Clean visual hierarchy
### 5. Sequence Diagram
**Best for:** Interactions between components, API calls, message flows
**Use when:** Content involves communication between actors/systems over time
**Key features:**
- Timeline-based layout
- Clear actor separation
- Activation boxes for processes
### 6. State Diagram
**Best for:** System states, status transitions, lifecycle stages
**Use when:** Content describes states and transitions between them
**Key features:**
- Clear state nodes
- Labeled transitions
- Start and end states
## Critical Syntax Rules
**Always follow these rules to prevent parsing errors:**
### Rule 1: Avoid List Syntax Conflicts
```
❌ WRONG: [1. Perception] → Triggers "Unsupported markdown: list"
✅ RIGHT: [1.Perception] → Remove space after period
✅ RIGHT: [① Perception] → Use circled numbers (①②③④⑤⑥⑦⑧⑨⑩)
✅ RIGHT: [(1) Perception] → Use parentheses
✅ RIGHT: [Step 1: Perception] → Use "Step" prefix
```
### Rule 2: Subgraph Naming
```
❌ WRONG: subgraph AI Agent Core → Space in name without quotes
✅ RIGHT: subgraph agent["AI Agent Core"] → Use ID with display name
✅ RIGHT: subgraph agent → Use simple ID only
```
### Rule 3: Node References
```
❌ WRONG: Title --> AI Agent Core → Reference display name directly
✅ RIGHT: Title --> agent → Reference subgraph ID
```
### Rule 4: Special Characters in Node Text
```
✅ Use quotes for text with spaces: ["Text with spaces"]
✅ Escape or avoid: quotation marks → use 『』instead
✅ Escape or avoid: parentheses → use 「」instead
✅ Line breaks in circle nodes only: ((Text<br/>Break))
```
### Rule 5: Arrow Types
- `-->` solid arrow
- `-.->` dashed arrow (for supporting systems, optional paths)
- `==>` thick arrow (for emphasis)
- `~~~` invisible link (for layout only)
For complete syntax reference and edge cases, see [references/syntax-rules.md](references/syntax-rules.md)
## Configuration Options
All diagrams accept these parameters:
**Layout:**
- `direction`: "vertical" (TB), "horizontal" (LR), "right-to-left" (RL), "bottom-to-top" (BT)
- `aspect`: "portrait" (default), "landscape" (wide), "square"
**Detail Level:**
- `simple`: Core elements only, minimal labels
- `standard`: Balanced detail with key descriptions (default)
- `detailed`: Full annotations, explanations, and metadata
- `presentation`: Optimized for slides (larger text, fewer details)
**Style:**
- `minimal`: Monochrome, clean lines
- `professional`: Semantic colors, clear hierarchy (default)
- `colorful`: Vibrant colors, high contrast
- `academic`: Formal styling for papers/documentation
**Additional Options:**
- `show_legend`: true/false - Include color/symbol legend
- `numbered`: true/false - Add sequence numbers to steps
- `title`: string - Add diagram title
## Example Usage Patterns
**Pattern 1: Basic request**
```
User: "Visualize the software development lifecycle"
Response: [Analyze → Choose graph TB → Generate with standard detail]
```
**Pattern 2: With configuration**
```
User: "Create a horizontal flowchart of our sales process with lots of detail"
Response: [Analyze → Choose graph LR → Generate with detailed level]
```
**Pattern 3: Comparison**
```
User: "Compare traditional AI vs AI agents"
Response: [Analyze → Choose comparison layout → Generate with contrasting styles]
```
## Workflow
1. **Understand the content**
- Identify main concepts, entities, and relationships
- Determine hierarchy or sequence
- Note any comparisons or contrasts
2. **Select diagram type**
- Match content structure to diagram type
- Consider user's presentation context
- Default to process flow if ambiguous
3. **Choose configuration**
- Apply user-specified options
- Use sensible defaults for unspecified options
- Optimize for readability
4. **Generate Mermaid code**
- Follow all syntax rules strictly
- Use semantic naming (descriptive IDs)
- Apply consistent styling
- Test for common errors:
* No "number. space" patterns in node text
* All subgraphs use ID["display name"] format
* All node references use IDs not display names
5. **Output with context**
- Wrap in ```mermaid code fence
- Add brief explanation of diagram structure
- Mention rendering compatibility (Obsidian, GitHub, etc.)
- Offer to adjust or create variations
## Color Scheme Defaults
Standard professional palette:
- Green (#d3f9d8/#2f9e44): Input, perception, start states
- Red (#ffe3e3/#c92a2a): Planning, decision points
- Purple (#e5dbff/#5f3dc4): Processing, reasoning
- Orange (#ffe8cc/#d9480f): Actions, tool usage
- Cyan (#c5f6fa/#0c8599): Output, execution, results
- Yellow (#fff4e6/#e67700): Storage, memory, data
- Pink (#f3d9fa/#862e9c): Learning, optimization
- Blue (#e7f5ff/#1971c2): Metadata, definitions, titles
- Gray (#f8f9fa/#868e96): Neutral elements, traditional systems
## Common Patterns
### Swimlane Pattern (Grouping)
```mermaid
graph TB
subgraph core["Core Process"]
A --> B --> C
end
subgraph support["Supporting Systems"]
D
E
end
core -.-> support
```
### Feedback Loop Pattern
```mermaid
graph TB
A[Start] --> B[Process]
B --> C[End]
C -.->|Feedback| A
```
### Hub and Spoke Pattern
```mermaid
graph TB
Central[Hub]
A[Spoke 1] --> Central
B[Spoke 2] --> Central
C[Spoke 3] --> Central
```
## Quality Checklist
Before outputting, verify:
- [ ] No "number. space" patterns in any node text
- [ ] All subgraphs use proper ID syntax
- [ ] All arrows use correct syntax (-->, -.->)
- [ ] Colors applied consistently
- [ ] Layout direction specified
- [ ] Style declarations present
- [ ] No ambiguous node references
- [ ] Compatible with Obsidian/GitHub renderers
- [ ] **No Emoji** in any node text - use text labels or color coding instead
## References
For detailed syntax rules and troubleshooting, see:
- [references/syntax-rules.md](references/syntax-rules.md) - Complete syntax reference and error prevention

View File

@@ -0,0 +1,484 @@
# Mermaid Syntax Rules Reference
This reference provides comprehensive syntax rules and error prevention strategies for Mermaid diagrams. Load this when encountering syntax errors or needing detailed syntax information.
## Table of Contents
1. [Critical Error Prevention](#critical-error-prevention)
2. [Node Syntax](#node-syntax)
3. [Subgraph Syntax](#subgraph-syntax)
4. [Arrow and Connection Types](#arrow-and-connection-types)
5. [Styling and Colors](#styling-and-colors)
6. [Layout and Direction](#layout-and-direction)
7. [Advanced Patterns](#advanced-patterns)
8. [Troubleshooting](#troubleshooting)
## Critical Error Prevention
### List Syntax Conflict (Most Common Error)
**Problem:** Mermaid parser interprets `number. space` as Markdown ordered list syntax.
**Error Message:** `Parse error: Unsupported markdown: list`
**Solutions:**
```mermaid
❌ [1. Perception]
❌ [2. Planning]
❌ [3. Reasoning]
✅ [1.Perception] # Remove space
✅ [① Perception] # Use circled numbers
✅ [(1) Perception] # Use parentheses
✅ [Step 1: Perception] # Use prefix
✅ [Step 1 - Perception] # Use dash
✅ [Perception] # Remove numbering
```
**Circled number reference:**
```
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
```
### Subgraph Naming Rules
**Rule:** Subgraphs with spaces must use ID + display name format.
```mermaid
❌ subgraph Core Process
A --> B
end
✅ subgraph core["Core Process"]
A --> B
end
✅ subgraph core_process
A --> B
end
```
**Referencing subgraphs:**
```mermaid
❌ Title --> Core Process # Cannot reference display name
✅ Title --> core # Must reference ID
```
### Node Reference Rules
**Rule:** Always reference nodes by ID, never by display text.
```mermaid
# Define nodes
A[Display Text A]
B["Display Text B"]
# Reference nodes
A --> B ✅ Use node IDs
Display Text A --> Display Text B ❌ Cannot use display text
```
## Node Syntax
### Basic Node Types
```mermaid
# Rectangle (default)
A[Rectangle Text]
# Rectangle with rounded corners
B(Rounded Text)
# Stadium shape
C([Stadium Text])
# Circle
D((Circle<br/>Text))
# Asymmetric shape
E>Right Arrow]
# Rhombus (decision)
F{Decision?}
# Hexagon
G{{Hexagon}}
# Parallelogram
H[/Parallelogram/]
# Database
I[(Database)]
# Trapezoid
J[/Trapezoid\]
```
### Node Text Rules
**Line breaks:**
- `<br/>` only works in circle nodes: `((Text<br/>Break))`
- For other nodes, use separate annotation nodes or keep text concise
**Special characters:**
- Spaces: Use quotes if needed: `["Text with spaces"]`
- Quotes: Replace with 『』or avoid
- Parentheses: Replace with 「」or avoid
- Colons: Generally safe but avoid if causing issues
- Hyphens/dashes: Safe to use
**Length guidelines:**
- Keep node text under 50 characters
- Use multiple lines (circle nodes) or separate annotation nodes for longer content
- Consider splitting into multiple nodes if text is too long
## Subgraph Syntax
### Basic Structure
```mermaid
graph TB
# Correct format with ID and display name
subgraph id["Display Name"]
direction TB
A --> B
end
# Simple ID only (no spaces)
subgraph simple
C --> D
end
# Can set direction inside subgraph
subgraph horiz["Horizontal"]
direction LR
E --> F
end
```
### Nested Subgraphs
```mermaid
graph TB
subgraph outer["Outer Group"]
direction TB
subgraph inner1["Inner 1"]
A --> B
end
subgraph inner2["Inner 2"]
C --> D
end
inner1 -.-> inner2
end
```
**Limitation:** Keep nesting to 2 levels maximum for readability.
### Connecting Subgraphs
```mermaid
graph TB
subgraph g1["Group 1"]
A[Node A]
end
subgraph g2["Group 2"]
B[Node B]
end
# Connect individual nodes (recommended)
A --> B
# Connect subgraphs (creates invisible link for layout)
g1 -.-> g2
```
## Arrow and Connection Types
### Basic Arrows
```mermaid
A --> B # Solid arrow
A -.-> B # Dashed arrow
A ==> B # Thick arrow
A ~~~> B # Invisible link (layout only, not rendered)
```
### Arrow Labels
```mermaid
A -->|Label Text| B
A -.->|Optional| B
A ==>|Important| B
```
### Multi-target Connections
```mermaid
# One to many
A --> B & C & D
# Many to one
A & B & C --> D
# Chaining
A --> B --> C --> D
```
### Bidirectional
```mermaid
A <--> B # Bidirectional solid
A <-.-> B # Bidirectional dashed
```
## Styling and Colors
### Inline Styling
```mermaid
style NodeID fill:#color,stroke:#color,stroke-width:2px
```
### Color Format
- Hex colors: `#ff0000` or `#f00`
- RGB: `rgb(255,0,0)`
- Color names: `red`, `blue`, etc. (limited support)
### Common Style Patterns
```mermaid
# Professional look
style A fill:#d3f9d8,stroke:#2f9e44,stroke-width:2px
# Emphasis
style B fill:#ffe3e3,stroke:#c92a2a,stroke-width:3px
# Muted/secondary
style C fill:#f8f9fa,stroke:#dee2e6,stroke-width:1px
# Title/header
style D fill:#1971c2,stroke:#1971c2,stroke-width:3px,color:#ffffff
```
### Styling Multiple Nodes
```mermaid
# Apply same style to multiple nodes
style A,B,C fill:#d3f9d8,stroke:#2f9e44,stroke-width:2px
```
## Layout and Direction
### Direction Codes
```mermaid
graph TB # Top to Bottom (vertical)
graph BT # Bottom to Top
graph LR # Left to Right (horizontal)
graph RL # Right to Left
graph TD # Top Down (same as TB)
```
### Layout Control Tips
1. **Vertical layouts (TB/BT):** Best for sequential processes, hierarchies
2. **Horizontal layouts (LR/RL):** Best for timelines, wide displays
3. **Mixed directions:** Set different directions in subgraphs
```mermaid
graph TB
subgraph vertical["Vertical Flow"]
direction TB
A --> B --> C
end
subgraph horizontal["Horizontal Flow"]
direction LR
D --> E --> F
end
```
## Advanced Patterns
### Feedback Loop Pattern
```mermaid
graph TB
A[Start] --> B[Process]
B --> C[Output]
C -.->|Feedback| A
style A fill:#d3f9d8,stroke:#2f9e44,stroke-width:2px
style B fill:#e5dbff,stroke:#5f3dc4,stroke-width:2px
style C fill:#c5f6fa,stroke:#0c8599,stroke-width:2px
```
### Swimlane Pattern
```mermaid
graph TB
subgraph lane1["Lane 1"]
A[Step 1] --> B[Step 2]
end
subgraph lane2["Lane 2"]
C[Step 3] --> D[Step 4]
end
B --> C
```
### Hub and Spoke
```mermaid
graph TB
Hub[Central Hub]
A[Spoke 1] --> Hub
B[Spoke 2] --> Hub
C[Spoke 3] --> Hub
Hub --> D[Output]
```
### Decision Tree
```mermaid
graph TB
Start[Start] --> Decision{Decision Point?}
Decision -->|Option A| PathA[Path A]
Decision -->|Option B| PathB[Path B]
Decision -->|Option C| PathC[Path C]
PathA --> End[End]
PathB --> End
PathC --> End
```
### Comparison Layout
```mermaid
graph TB
Title[Comparison]
subgraph left["System A"]
A1[Feature 1]
A2[Feature 2]
A3[Feature 3]
end
subgraph right["System B"]
B1[Feature 1]
B2[Feature 2]
B3[Feature 3]
end
Title --> left
Title --> right
subgraph compare["Key Differences"]
Diff[Difference Summary]
end
left --> compare
right --> compare
```
## Troubleshooting
### Common Errors and Solutions
#### Error: "Parse error on line X: Expecting 'SEMI', 'NEWLINE', 'EOF'"
**Causes:**
1. Subgraph name with spaces not using ID format
2. Node reference using display text instead of ID
3. Invalid special characters in node text
**Solutions:**
- Use `subgraph id["Display Name"]` format
- Reference nodes by ID only
- Quote node text with special characters
#### Error: "Unsupported markdown: list"
**Cause:** Using `number. space` pattern in node text
**Solution:** Remove space or use alternatives (①, (1), Step 1:)
#### Error: "Parse error: unexpected character"
**Causes:**
1. Unescaped special characters
2. Improper quotes
3. Invalid Mermaid syntax
**Solutions:**
- Replace problematic characters (quotes → 『』, parens → 「」)
- Use proper node definition syntax
- Check arrow syntax
#### Diagram doesn't render correctly
**Causes:**
1. Missing style declarations
2. Incorrect direction specification
3. Invalid connections
**Solutions:**
- Verify all style declarations use valid syntax
- Check direction is set in graph declaration or subgraph
- Ensure all node IDs are defined before referencing
### Validation Checklist
Before finalizing any diagram:
- [ ] No `number. space` patterns in node text
- [ ] All subgraphs use proper ID syntax if they contain spaces
- [ ] All node references use IDs not display text
- [ ] All arrows use valid syntax (-->, -.->)
- [ ] All style declarations are syntactically correct
- [ ] Direction is explicitly set
- [ ] No unescaped special characters in node text
- [ ] All connections reference defined nodes
### Platform-Specific Notes
**Obsidian:**
- Older Mermaid version, more strict parsing
- Limited support for `<br/>` (only in circle nodes)
- Test diagrams before finalizing
**GitHub:**
- Good Mermaid support
- Renders most modern syntax
- May differ slightly from Obsidian rendering
**Mermaid Live Editor:**
- Most up-to-date parser
- Best for testing new syntax
- May support features not available in Obsidian/GitHub
## Quick Reference
### Safe Numbering Methods
`1.Text` `①Text` `(1)Text` `Step 1:Text`
`1. Text`
### Safe Subgraph Syntax
`subgraph id["Name"]` `subgraph simple_name`
`subgraph Name With Spaces`
### Safe Node References
`NodeID --> AnotherID`
`"Display Text" --> "Other Text"`
### Safe Special Characters
`『』` for quotes, `「」` for parentheses
`"` unescaped quotes, `()` in problematic contexts

View File

@@ -0,0 +1,497 @@
---
name: obsidian-bases
description: Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian.
---
# Obsidian Bases Skill
## Workflow
1. **Create the file**: Create a `.base` file in the vault with valid YAML content
2. **Define scope**: Add `filters` to select which notes appear (by tag, folder, property, or date)
3. **Add formulas** (optional): Define computed properties in the `formulas` section
4. **Configure views**: Add one or more views (`table`, `cards`, `list`, or `map`) with `order` specifying which properties to display
5. **Validate**: Verify the file is valid YAML with no syntax errors. Check that all referenced properties and formulas exist. Common issues: unquoted strings containing special YAML characters, mismatched quotes in formula expressions, referencing `formula.X` without defining `X` in `formulas`
6. **Test in Obsidian**: Open the `.base` file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below
## Schema
Base files use the `.base` extension and contain valid YAML.
```yaml
# Global filters apply to ALL views in the base
filters:
# Can be a single filter string
# OR a recursive filter object with and/or/not
and: []
or: []
not: []
# Define formula properties that can be used across all views
formulas:
formula_name: 'expression'
# Configure display names and settings for properties
properties:
property_name:
displayName: "Display Name"
formula.formula_name:
displayName: "Formula Display Name"
file.ext:
displayName: "Extension"
# Define custom summary formulas
summaries:
custom_summary_name: 'values.mean().round(3)'
# Define one or more views
views:
- type: table | cards | list | map
name: "View Name"
limit: 10 # Optional: limit results
groupBy: # Optional: group results
property: property_name
direction: ASC | DESC
filters: # View-specific filters
and: []
order: # Properties to display in order
- file.name
- property_name
- formula.formula_name
summaries: # Map properties to summary formulas
property_name: Average
```
## Filter Syntax
Filters narrow down results. They can be applied globally or per-view.
### Filter Structure
```yaml
# Single filter
filters: 'status == "done"'
# AND - all conditions must be true
filters:
and:
- 'status == "done"'
- 'priority > 3'
# OR - any condition can be true
filters:
or:
- 'file.hasTag("book")'
- 'file.hasTag("article")'
# NOT - exclude matching items
filters:
not:
- 'file.hasTag("archived")'
# Nested filters
filters:
or:
- file.hasTag("tag")
- and:
- file.hasTag("book")
- file.hasLink("Textbook")
- not:
- file.hasTag("book")
- file.inFolder("Required Reading")
```
### Filter Operators
| Operator | Description |
|----------|-------------|
| `==` | equals |
| `!=` | not equal |
| `>` | greater than |
| `<` | less than |
| `>=` | greater than or equal |
| `<=` | less than or equal |
| `&&` | logical and |
| `\|\|` | logical or |
| <code>!</code> | logical not |
## Properties
### Three Types of Properties
1. **Note properties** - From frontmatter: `note.author` or just `author`
2. **File properties** - File metadata: `file.name`, `file.mtime`, etc.
3. **Formula properties** - Computed values: `formula.my_formula`
### File Properties Reference
| Property | Type | Description |
|----------|------|-------------|
| `file.name` | String | File name |
| `file.basename` | String | File name without extension |
| `file.path` | String | Full path to file |
| `file.folder` | String | Parent folder path |
| `file.ext` | String | File extension |
| `file.size` | Number | File size in bytes |
| `file.ctime` | Date | Created time |
| `file.mtime` | Date | Modified time |
| `file.tags` | List | All tags in file |
| `file.links` | List | Internal links in file |
| `file.backlinks` | List | Files linking to this file |
| `file.embeds` | List | Embeds in the note |
| `file.properties` | Object | All frontmatter properties |
### The `this` Keyword
- In main content area: refers to the base file itself
- When embedded: refers to the embedding file
- In sidebar: refers to the active file in main content
## Formula Syntax
Formulas compute values from properties. Defined in the `formulas` section.
```yaml
formulas:
# Simple arithmetic
total: "price * quantity"
# Conditional logic
status_icon: 'if(done, "✅", "⏳")'
# String formatting
formatted_price: 'if(price, price.toFixed(2) + " dollars")'
# Date formatting
created: 'file.ctime.format("YYYY-MM-DD")'
# Calculate days since created (use .days for Duration)
days_old: '(now() - file.ctime).days'
# Calculate days until due date
days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
```
## Key Functions
Most commonly used functions. For the complete reference of all types (Date, String, Number, List, File, Link, Object, RegExp), see [FUNCTIONS_REFERENCE.md](references/FUNCTIONS_REFERENCE.md).
| Function | Signature | Description |
|----------|-----------|-------------|
| `date()` | `date(string): date` | Parse string to date (`YYYY-MM-DD HH:mm:ss`) |
| `now()` | `now(): date` | Current date and time |
| `today()` | `today(): date` | Current date (time = 00:00:00) |
| `if()` | `if(condition, trueResult, falseResult?)` | Conditional |
| `duration()` | `duration(string): duration` | Parse duration string |
| `file()` | `file(path): file` | Get file object |
| `link()` | `link(path, display?): Link` | Create a link |
### Duration Type
When subtracting two dates, the result is a **Duration** type (not a number).
**Duration Fields:** `duration.days`, `duration.hours`, `duration.minutes`, `duration.seconds`, `duration.milliseconds`
**IMPORTANT:** Duration does NOT support `.round()`, `.floor()`, `.ceil()` directly. Access a numeric field first (like `.days`), then apply number functions.
```yaml
# CORRECT: Calculate days between dates
"(date(due_date) - today()).days" # Returns number of days
"(now() - file.ctime).days" # Days since created
"(date(due_date) - today()).days.round(0)" # Rounded days
# WRONG - will cause error:
# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division then round
```
### Date Arithmetic
```yaml
# Duration units: y/year/years, M/month/months, d/day/days,
# w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
"now() + \"1 day\"" # Tomorrow
"today() + \"7d\"" # A week from today
"now() - file.ctime" # Returns Duration
"(now() - file.ctime).days" # Get days as number
```
## View Types
### Table View
```yaml
views:
- type: table
name: "My Table"
order:
- file.name
- status
- due_date
summaries:
price: Sum
count: Average
```
### Cards View
```yaml
views:
- type: cards
name: "Gallery"
order:
- file.name
- cover_image
- description
```
### List View
```yaml
views:
- type: list
name: "Simple List"
order:
- file.name
- status
```
### Map View
Requires latitude/longitude properties and the Maps community plugin.
```yaml
views:
- type: map
name: "Locations"
# Map-specific settings for lat/lng properties
```
## Default Summary Formulas
| Name | Input Type | Description |
|------|------------|-------------|
| `Average` | Number | Mathematical mean |
| `Min` | Number | Smallest number |
| `Max` | Number | Largest number |
| `Sum` | Number | Sum of all numbers |
| `Range` | Number | Max - Min |
| `Median` | Number | Mathematical median |
| `Stddev` | Number | Standard deviation |
| `Earliest` | Date | Earliest date |
| `Latest` | Date | Latest date |
| `Range` | Date | Latest - Earliest |
| `Checked` | Boolean | Count of true values |
| `Unchecked` | Boolean | Count of false values |
| `Empty` | Any | Count of empty values |
| `Filled` | Any | Count of non-empty values |
| `Unique` | Any | Count of unique values |
## Complete Examples
### Task Tracker Base
```yaml
filters:
and:
- file.hasTag("task")
- 'file.ext == "md"'
formulas:
days_until_due: 'if(due, (date(due) - today()).days, "")'
is_overdue: 'if(due, date(due) < today() && status != "done", false)'
priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
properties:
status:
displayName: Status
formula.days_until_due:
displayName: "Days Until Due"
formula.priority_label:
displayName: Priority
views:
- type: table
name: "Active Tasks"
filters:
and:
- 'status != "done"'
order:
- file.name
- status
- formula.priority_label
- due
- formula.days_until_due
groupBy:
property: status
direction: ASC
summaries:
formula.days_until_due: Average
- type: table
name: "Completed"
filters:
and:
- 'status == "done"'
order:
- file.name
- completed_date
```
### Reading List Base
```yaml
filters:
or:
- file.hasTag("book")
- file.hasTag("article")
formulas:
reading_time: 'if(pages, (pages * 2).toString() + " min", "")'
status_icon: 'if(status == "reading", "📖", if(status == "done", "✅", "📚"))'
year_read: 'if(finished_date, date(finished_date).year, "")'
properties:
author:
displayName: Author
formula.status_icon:
displayName: ""
formula.reading_time:
displayName: "Est. Time"
views:
- type: cards
name: "Library"
order:
- cover
- file.name
- author
- formula.status_icon
filters:
not:
- 'status == "dropped"'
- type: table
name: "Reading List"
filters:
and:
- 'status == "to-read"'
order:
- file.name
- author
- pages
- formula.reading_time
```
### Daily Notes Index
```yaml
filters:
and:
- file.inFolder("Daily Notes")
- '/^\d{4}-\d{2}-\d{2}$/.matches(file.basename)'
formulas:
word_estimate: '(file.size / 5).round(0)'
day_of_week: 'date(file.basename).format("dddd")'
properties:
formula.day_of_week:
displayName: "Day"
formula.word_estimate:
displayName: "~Words"
views:
- type: table
name: "Recent Notes"
limit: 30
order:
- file.name
- formula.day_of_week
- formula.word_estimate
- file.mtime
```
## Embedding Bases
Embed in Markdown files:
```markdown
![[MyBase.base]]
<!-- Specific view -->
![[MyBase.base#View Name]]
```
## YAML Quoting Rules
- Use single quotes for formulas containing double quotes: `'if(done, "Yes", "No")'`
- Use double quotes for simple strings: `"My View Name"`
- Escape nested quotes properly in complex expressions
## Troubleshooting
### YAML Syntax Errors
**Unquoted special characters**: Strings containing `:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` `` must be quoted.
```yaml
# WRONG - colon in unquoted string
displayName: Status: Active
# CORRECT
displayName: "Status: Active"
```
**Mismatched quotes in formulas**: When a formula contains double quotes, wrap the entire formula in single quotes.
```yaml
# WRONG - double quotes inside double quotes
formulas:
label: "if(done, "Yes", "No")"
# CORRECT - single quotes wrapping double quotes
formulas:
label: 'if(done, "Yes", "No")'
```
### Common Formula Errors
**Duration math without field access**: Subtracting dates returns a Duration, not a number. Always access `.days`, `.hours`, etc.
```yaml
# WRONG - Duration is not a number
"(now() - file.ctime).round(0)"
# CORRECT - access .days first, then round
"(now() - file.ctime).days.round(0)"
```
**Missing null checks**: Properties may not exist on all notes. Use `if()` to guard.
```yaml
# WRONG - crashes if due_date is empty
"(date(due_date) - today()).days"
# CORRECT - guard with if()
'if(due_date, (date(due_date) - today()).days, "")'
```
**Referencing undefined formulas**: Ensure every `formula.X` in `order` or `properties` has a matching entry in `formulas`.
```yaml
# This will fail silently if 'total' is not defined in formulas
order:
- formula.total
# Fix: define it
formulas:
total: "price * quantity"
```
## References
- [Bases Syntax](https://help.obsidian.md/bases/syntax)
- [Functions](https://help.obsidian.md/bases/functions)
- [Views](https://help.obsidian.md/bases/views)
- [Formulas](https://help.obsidian.md/formulas)
- [Complete Functions Reference](references/FUNCTIONS_REFERENCE.md)

View File

@@ -0,0 +1,173 @@
# Functions Reference
## Global Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `date()` | `date(string): date` | Parse string to date. Format: `YYYY-MM-DD HH:mm:ss` |
| `duration()` | `duration(string): duration` | Parse duration string |
| `now()` | `now(): date` | Current date and time |
| `today()` | `today(): date` | Current date (time = 00:00:00) |
| `if()` | `if(condition, trueResult, falseResult?)` | Conditional |
| `min()` | `min(n1, n2, ...): number` | Smallest number |
| `max()` | `max(n1, n2, ...): number` | Largest number |
| `number()` | `number(any): number` | Convert to number |
| `link()` | `link(path, display?): Link` | Create a link |
| `list()` | `list(element): List` | Wrap in list if not already |
| `file()` | `file(path): file` | Get file object |
| `image()` | `image(path): image` | Create image for rendering |
| `icon()` | `icon(name): icon` | Lucide icon by name |
| `html()` | `html(string): html` | Render as HTML |
| `escapeHTML()` | `escapeHTML(string): string` | Escape HTML characters |
## Any Type Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `isTruthy()` | `any.isTruthy(): boolean` | Coerce to boolean |
| `isType()` | `any.isType(type): boolean` | Check type |
| `toString()` | `any.toString(): string` | Convert to string |
## Date Functions & Fields
**Fields:** `date.year`, `date.month`, `date.day`, `date.hour`, `date.minute`, `date.second`, `date.millisecond`
| Function | Signature | Description |
|----------|-----------|-------------|
| `date()` | `date.date(): date` | Remove time portion |
| `format()` | `date.format(string): string` | Format with Moment.js pattern |
| `time()` | `date.time(): string` | Get time as string |
| `relative()` | `date.relative(): string` | Human-readable relative time |
| `isEmpty()` | `date.isEmpty(): boolean` | Always false for dates |
## Duration Type
When subtracting two dates, the result is a **Duration** type (not a number). Duration has its own properties and methods.
**Duration Fields:**
| Field | Type | Description |
|-------|------|-------------|
| `duration.days` | Number | Total days in duration |
| `duration.hours` | Number | Total hours in duration |
| `duration.minutes` | Number | Total minutes in duration |
| `duration.seconds` | Number | Total seconds in duration |
| `duration.milliseconds` | Number | Total milliseconds in duration |
**IMPORTANT:** Duration does NOT support `.round()`, `.floor()`, `.ceil()` directly. You must access a numeric field first (like `.days`), then apply number functions.
```yaml
# CORRECT: Calculate days between dates
"(date(due_date) - today()).days" # Returns number of days
"(now() - file.ctime).days" # Days since created
# CORRECT: Round the numeric result if needed
"(date(due_date) - today()).days.round(0)" # Rounded days
"(now() - file.ctime).hours.round(0)" # Rounded hours
# WRONG - will cause error:
# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division then round
```
## Date Arithmetic
```yaml
# Duration units: y/year/years, M/month/months, d/day/days,
# w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
# Add/subtract durations
"date + \"1M\"" # Add 1 month
"date - \"2h\"" # Subtract 2 hours
"now() + \"1 day\"" # Tomorrow
"today() + \"7d\"" # A week from today
# Subtract dates returns Duration type
"now() - file.ctime" # Returns Duration
"(now() - file.ctime).days" # Get days as number
"(now() - file.ctime).hours" # Get hours as number
# Complex duration arithmetic
"now() + (duration('1d') * 2)"
```
## String Functions
**Field:** `string.length`
| Function | Signature | Description |
|----------|-----------|-------------|
| `contains()` | `string.contains(value): boolean` | Check substring |
| `containsAll()` | `string.containsAll(...values): boolean` | All substrings present |
| `containsAny()` | `string.containsAny(...values): boolean` | Any substring present |
| `startsWith()` | `string.startsWith(query): boolean` | Starts with query |
| `endsWith()` | `string.endsWith(query): boolean` | Ends with query |
| `isEmpty()` | `string.isEmpty(): boolean` | Empty or not present |
| `lower()` | `string.lower(): string` | To lowercase |
| `title()` | `string.title(): string` | To Title Case |
| `trim()` | `string.trim(): string` | Remove whitespace |
| `replace()` | `string.replace(pattern, replacement): string` | Replace pattern |
| `repeat()` | `string.repeat(count): string` | Repeat string |
| `reverse()` | `string.reverse(): string` | Reverse string |
| `slice()` | `string.slice(start, end?): string` | Substring |
| `split()` | `string.split(separator, n?): list` | Split to list |
## Number Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `abs()` | `number.abs(): number` | Absolute value |
| `ceil()` | `number.ceil(): number` | Round up |
| `floor()` | `number.floor(): number` | Round down |
| `round()` | `number.round(digits?): number` | Round to digits |
| `toFixed()` | `number.toFixed(precision): string` | Fixed-point notation |
| `isEmpty()` | `number.isEmpty(): boolean` | Not present |
## List Functions
**Field:** `list.length`
| Function | Signature | Description |
|----------|-----------|-------------|
| `contains()` | `list.contains(value): boolean` | Element exists |
| `containsAll()` | `list.containsAll(...values): boolean` | All elements exist |
| `containsAny()` | `list.containsAny(...values): boolean` | Any element exists |
| `filter()` | `list.filter(expression): list` | Filter by condition (uses `value`, `index`) |
| `map()` | `list.map(expression): list` | Transform elements (uses `value`, `index`) |
| `reduce()` | `list.reduce(expression, initial): any` | Reduce to single value (uses `value`, `index`, `acc`) |
| `flat()` | `list.flat(): list` | Flatten nested lists |
| `join()` | `list.join(separator): string` | Join to string |
| `reverse()` | `list.reverse(): list` | Reverse order |
| `slice()` | `list.slice(start, end?): list` | Sublist |
| `sort()` | `list.sort(): list` | Sort ascending |
| `unique()` | `list.unique(): list` | Remove duplicates |
| `isEmpty()` | `list.isEmpty(): boolean` | No elements |
## File Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `asLink()` | `file.asLink(display?): Link` | Convert to link |
| `hasLink()` | `file.hasLink(otherFile): boolean` | Has link to file |
| `hasTag()` | `file.hasTag(...tags): boolean` | Has any of the tags |
| `hasProperty()` | `file.hasProperty(name): boolean` | Has property |
| `inFolder()` | `file.inFolder(folder): boolean` | In folder or subfolder |
## Link Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `asFile()` | `link.asFile(): file` | Get file object |
| `linksTo()` | `link.linksTo(file): boolean` | Links to file |
## Object Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `isEmpty()` | `object.isEmpty(): boolean` | No properties |
| `keys()` | `object.keys(): list` | List of keys |
| `values()` | `object.values(): list` | List of values |
## Regular Expression Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `matches()` | `regexp.matches(string): boolean` | Test if matches |

View File

@@ -0,0 +1,211 @@
---
name: obsidian-canvas-creator
description: Create Obsidian Canvas files from text content, supporting both MindMap and freeform layouts. Use this skill when users want to visualize content as an interactive canvas, create mind maps, or organize information spatially in Obsidian format.
---
# Obsidian Canvas Creator
Transform text content into structured Obsidian Canvas files with support for MindMap and freeform layouts.
## When to Use This Skill
- User requests to create a canvas, mind map, or visual diagram from text
- User wants to organize information spatially
- User mentions "Obsidian Canvas" or similar visualization tools
- Converting structured content (articles, notes, outlines) into visual format
## Core Workflow
### 1. Analyze Content
Read and understand the input content:
- Identify main topics and hierarchical relationships
- Extract key points, facts, and supporting details
- Note any existing structure (headings, lists, sections)
### 2. Determine Layout Type
Ask user to choose or infer from context:
**MindMap Layout:**
- Radial structure from center
- Parent-child relationships
- Clear hierarchy
- Good for: brainstorming, topic exploration, hierarchical content
**Freeform Layout:**
- Custom positioning
- Flexible relationships
- Multiple connection types
- Good for: complex networks, non-hierarchical content, custom arrangements
### 3. Plan Structure
**For MindMap:**
- Identify central concept (root node)
- Map primary branches (main topics)
- Organize secondary branches (subtopics)
- Position leaf nodes (details)
**For Freeform:**
- Group related concepts
- Identify connection patterns
- Plan spatial zones
- Consider visual flow
### 4. Generate Canvas
Create JSON following the Canvas specification:
**Node Creation:**
- Assign unique 8-12 character hex IDs
- Set appropriate dimensions based on content length
- Apply consistent color schemes
- Ensure no coordinate overlaps
**Edge Creation:**
- Connect parent-child relationships
- Use appropriate arrow styles
- Add labels for complex relationships
- Choose line styles (straight for hierarchy, curved for cross-references)
**Grouping (Optional):**
- Create visual containers for related nodes
- Use subtle background colors
- Add descriptive labels
### 5. Apply Layout Algorithm
**MindMap Layout Calculations:**
Refer to `references/layout-algorithms.md` for detailed algorithms. Key principles:
- Center root at (0, 0)
- Distribute primary nodes radially
- Space secondary nodes based on sibling count
- Maintain minimum spacing: 320px horizontal, 200px vertical
**Freeform Layout Principles:**
- Start with logical groupings
- Position groups with clear separation
- Connect across groups with curved edges
- Balance visual weight across canvas
### 6. Validate and Output
Before outputting:
**Validation Checklist:**
- All nodes have unique IDs
- No coordinate overlaps (check distance > node dimensions + spacing)
- All edges reference valid node IDs
- Groups (if any) have labels
- Colors use consistent format (hex or preset numbers)
- JSON is properly escaped (Chinese quotes: 『』 for double, 「」 for single)
**Output Format:**
- Complete, valid JSON Canvas file
- No additional explanation text
- Directly importable into Obsidian
## Node Sizing Guidelines
**Text Length-Based Sizing:**
- Short text (<30 chars): 220 × 100 px
- Medium text (30-60 chars): 260 × 120 px
- Long text (60-100 chars): 320 × 140 px
- Very long text (>100 chars): 320 × 180 px
## Color Schemes
**Preset Colors (Recommended):**
- `"1"` - Red (warnings, important)
- `"2"` - Orange (action items)
- `"3"` - Yellow (questions, notes)
- `"4"` - Green (positive, completed)
- `"5"` - Cyan (information, details)
- `"6"` - Purple (concepts, abstract)
**Custom Hex Colors:**
Use for brand consistency or specific themes. Always use uppercase format: `"#4A90E2"`
## Critical Rules
1. **Quote Handling:**
- Chinese double quotes → 『』
- Chinese single quotes → 「」
- English double quotes → `\"`
2. **ID Generation:**
- 8-12 character random hex strings
- Must be unique across all nodes and edges
3. **Z-Index Order:**
- Output groups first (bottom layer)
- Then subgroups
- Finally text/link nodes (top layer)
4. **Spacing Requirements:**
- Minimum horizontal: 320px between node centers
- Minimum vertical: 200px between node centers
- Account for node dimensions when calculating
5. **JSON Structure:**
- Top level contains only `nodes` and `edges` arrays
- No extra wrapping objects
- No comments in output
6. **No Emoji:**
- Do not use any Emoji symbols in node text
- Use color coding or text labels for visual distinction instead
## Examples
### Simple MindMap Request
User: "Create a mind map about solar system planets"
Process:
1. Identify center: "Solar System"
2. Primary branches: Inner Planets, Outer Planets, Dwarf Planets
3. Secondary nodes: Individual planets with key facts
4. Apply radial layout
5. Generate JSON with proper spacing
### Freeform Content Request
User: "Turn this article into a canvas" + [article text]
Process:
1. Extract article structure (intro, body sections, conclusion)
2. Identify key concepts and relationships
3. Group related sections spatially
4. Connect with labeled edges
5. Apply freeform layout with clear zones
## Reference Documents
- **Canvas Specification**: `references/canvas-spec.md` - Complete JSON Canvas format specification
- **Layout Algorithms**: `references/layout-algorithms.md` - Detailed positioning algorithms for both layout types
Load these references when:
- Need specification details for edge cases
- Implementing complex layout calculations
- Troubleshooting validation errors
## Tips for Quality Canvases
1. **Keep text concise**: Each node should be scannable (<2 lines preferred)
2. **Use hierarchy**: Group by importance and relationship
3. **Balance the canvas**: Distribute nodes to avoid clustering
4. **Strategic colors**: Use colors to encode meaning, not just decoration
5. **Meaningful connections**: Only add edges that clarify relationships
6. **Test in Obsidian**: Verify the output opens correctly
## Common Pitfalls to Avoid
- Overlapping nodes (always check distances)
- Inconsistent quote escaping (breaks JSON parsing)
- Missing group labels (causes sidebar navigation issues)
- Too much text in nodes (use file nodes for long content)
- Duplicate IDs (each must be unique)
- Unconnected nodes (unless intentional islands)

View File

@@ -0,0 +1,132 @@
{
"nodes": [
{
"id": "group01",
"type": "group",
"x": -50,
"y": -50,
"width": 600,
"height": 400,
"label": "Group 1 - Core Concepts",
"color": "4"
},
{
"id": "group02",
"type": "group",
"x": 650,
"y": -50,
"width": 600,
"height": 400,
"label": "Group 2 - Applications",
"color": "5"
},
{
"id": "node01",
"type": "text",
"x": 0,
"y": 0,
"width": 240,
"height": 100,
"text": "Concept A",
"color": "4"
},
{
"id": "node02",
"type": "text",
"x": 290,
"y": 0,
"width": 240,
"height": 100,
"text": "Concept B",
"color": "4"
},
{
"id": "node03",
"type": "text",
"x": 0,
"y": 150,
"width": 240,
"height": 100,
"text": "Concept C",
"color": "4"
},
{
"id": "node04",
"type": "text",
"x": 290,
"y": 150,
"width": 240,
"height": 100,
"text": "Concept D",
"color": "4"
},
{
"id": "node05",
"type": "text",
"x": 700,
"y": 0,
"width": 240,
"height": 100,
"text": "Application 1",
"color": "5"
},
{
"id": "node06",
"type": "text",
"x": 990,
"y": 0,
"width": 240,
"height": 100,
"text": "Application 2",
"color": "5"
},
{
"id": "node07",
"type": "text",
"x": 700,
"y": 150,
"width": 240,
"height": 100,
"text": "Application 3",
"color": "5"
}
],
"edges": [
{
"id": "e1",
"fromNode": "node01",
"fromSide": "bottom",
"toNode": "node03",
"toSide": "top",
"toEnd": "arrow"
},
{
"id": "e2",
"fromNode": "node02",
"fromSide": "bottom",
"toNode": "node04",
"toSide": "top",
"toEnd": "arrow"
},
{
"id": "e3",
"fromNode": "node01",
"fromSide": "right",
"toNode": "node05",
"toSide": "left",
"toEnd": "arrow",
"label": "leads to",
"color": "3"
},
{
"id": "e4",
"fromNode": "node02",
"fromSide": "right",
"toNode": "node06",
"toSide": "left",
"toEnd": "arrow",
"label": "enables",
"color": "3"
}
]
}

View File

@@ -0,0 +1,106 @@
{
"nodes": [
{
"id": "root001",
"type": "text",
"x": -150,
"y": -60,
"width": 300,
"height": 120,
"text": "# Central Topic\n\nMain concept goes here",
"color": "4"
},
{
"id": "branch01",
"type": "text",
"x": 250,
"y": -200,
"width": 220,
"height": 100,
"text": "Branch 1\n\nFirst main idea",
"color": "5"
},
{
"id": "branch02",
"type": "text",
"x": 250,
"y": -50,
"width": 220,
"height": 100,
"text": "Branch 2\n\nSecond main idea",
"color": "5"
},
{
"id": "branch03",
"type": "text",
"x": 250,
"y": 100,
"width": 220,
"height": 100,
"text": "Branch 3\n\nThird main idea",
"color": "5"
},
{
"id": "detail01",
"type": "text",
"x": 550,
"y": -200,
"width": 200,
"height": 80,
"text": "Detail A",
"color": "6"
},
{
"id": "detail02",
"type": "text",
"x": 550,
"y": -100,
"width": 200,
"height": 80,
"text": "Detail B",
"color": "6"
}
],
"edges": [
{
"id": "e1",
"fromNode": "root001",
"fromSide": "right",
"toNode": "branch01",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e2",
"fromNode": "root001",
"fromSide": "right",
"toNode": "branch02",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e3",
"fromNode": "root001",
"fromSide": "right",
"toNode": "branch03",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e4",
"fromNode": "branch01",
"fromSide": "right",
"toNode": "detail01",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e5",
"fromNode": "branch01",
"fromSide": "right",
"toNode": "detail02",
"toSide": "left",
"toEnd": "arrow"
}
]
}

View File

@@ -0,0 +1,403 @@
# JSON Canvas Specification for Obsidian
Version 1.0 — 2024-03-11
## Overview
JSON Canvas is a format for representing infinite canvas documents. This specification defines the structure for creating canvas files compatible with Obsidian.
## Top Level Structure
The root JSON object contains two optional arrays:
```json
{
"nodes": [...],
"edges": [...]
}
```
- `nodes` (optional, array): All canvas objects (text, files, links, groups)
- `edges` (optional, array): All connections between nodes
## Node Types
### Common Attributes
All nodes share these required attributes:
- `id` (required, string): Unique identifier for the node
- `type` (required, string): Node type (`text`, `file`, `link`, `group`)
- `x` (required, integer): X position in pixels
- `y` (required, integer): Y position in pixels
- `width` (required, integer): Width in pixels
- `height` (required, integer): Height in pixels
- `color` (optional, string/number): Color (hex `"#FF0000"` or preset `"1"`)
### Text Nodes
Store plain text with Markdown formatting.
**Required Attributes:**
- `text` (string): Content in Markdown syntax
**Example:**
```json
{
"id": "abc123",
"type": "text",
"x": 0,
"y": 0,
"width": 250,
"height": 100,
"text": "# Main Topic\n\nKey point here",
"color": "4"
}
```
### File Nodes
Reference other files or attachments (images, PDFs, etc.).
**Required Attributes:**
- `file` (string): Path to file in the vault
**Optional Attributes:**
- `subpath` (string): Link to specific heading/block (starts with `#`)
**Example:**
```json
{
"id": "def456",
"type": "file",
"x": 300,
"y": 0,
"width": 400,
"height": 300,
"file": "Images/diagram.png"
}
```
**With Subpath:**
```json
{
"id": "ghi789",
"type": "file",
"x": 0,
"y": 200,
"width": 250,
"height": 100,
"file": "Notes/Meeting Notes.md",
"subpath": "#Action Items"
}
```
### Link Nodes
Reference external URLs.
**Required Attributes:**
- `url` (string): Full URL including protocol
**Example:**
```json
{
"id": "jkl012",
"type": "link",
"x": 0,
"y": -200,
"width": 250,
"height": 100,
"url": "https://obsidian.md",
"color": "5"
}
```
### Group Nodes
Visual containers for organizing related nodes.
**Optional Attributes:**
- `label` (string): Text label for the group (recommended)
- `background` (string): Path to background image
- `backgroundStyle` (string): Image rendering style
- `cover`: Fill entire node
- `ratio`: Maintain aspect ratio
- `repeat`: Tile as pattern
**Example:**
```json
{
"id": "group1",
"type": "group",
"x": -50,
"y": -50,
"width": 600,
"height": 400,
"label": "Main Concepts",
"color": "4"
}
```
**With Background:**
```json
{
"id": "group2",
"type": "group",
"x": 700,
"y": 0,
"width": 500,
"height": 600,
"label": "Reference Materials",
"background": "Images/texture.png",
"backgroundStyle": "repeat"
}
```
## Z-Index and Layering
Nodes are displayed in array order:
- **First node**: Bottom layer (rendered below others)
- **Last node**: Top layer (rendered above others)
**Best Practice Order:**
1. Group nodes (backgrounds)
2. Sub-groups
3. Regular nodes (text, file, link)
This ensures groups appear behind content.
## Edges (Connections)
Edges connect nodes with lines.
**Required Attributes:**
- `id` (required, string): Unique identifier
- `fromNode` (required, string): Starting node ID
- `toNode` (required, string): Ending node ID
**Optional Attributes:**
- `fromSide` (string): Starting edge side
- Values: `top`, `right`, `bottom`, `left`
- `fromEnd` (string): Start endpoint shape
- Values: `none` (default), `arrow`
- `toSide` (string): Ending edge side
- Values: `top`, `right`, `bottom`, `left`
- `toEnd` (string): End endpoint shape
- Values: `arrow` (default), `none`
- `color` (string/number): Edge color
- `label` (string): Text label on edge
**Example - Simple Connection:**
```json
{
"id": "edge1",
"fromNode": "abc123",
"toNode": "def456"
}
```
**Example - Fully Specified:**
```json
{
"id": "edge2",
"fromNode": "def456",
"fromSide": "bottom",
"fromEnd": "none",
"toNode": "ghi789",
"toSide": "top",
"toEnd": "arrow",
"color": "3",
"label": "leads to"
}
```
## Color System
### Preset Colors
Use string numbers `"1"` through `"6"`:
- `"1"` - Red
- `"2"` - Orange
- `"3"` - Yellow
- `"4"` - Green
- `"5"` - Cyan
- `"6"` - Purple
**Note:** Exact colors adapt to Obsidian's theme. These provide semantic meaning across light/dark modes.
### Custom Hex Colors
Use hex format: `"#RRGGBB"`
**Examples:**
- `"#4A90E2"` (blue)
- `"#50E3C2"` (teal)
- `"#F5A623"` (orange)
**Best Practice:** Use consistent format within a canvas (all hex OR all presets).
## Complete Example
```json
{
"nodes": [
{
"id": "group001",
"type": "group",
"x": -50,
"y": -50,
"width": 700,
"height": 500,
"label": "Core Concepts",
"color": "4"
},
{
"id": "center01",
"type": "text",
"x": 0,
"y": 0,
"width": 300,
"height": 120,
"text": "# Central Topic\n\nMain idea here",
"color": "4"
},
{
"id": "branch01",
"type": "text",
"x": 400,
"y": -100,
"width": 220,
"height": 100,
"text": "Subtopic A",
"color": "5"
},
{
"id": "branch02",
"type": "text",
"x": 400,
"y": 100,
"width": 220,
"height": 100,
"text": "Subtopic B",
"color": "5"
},
{
"id": "detail01",
"type": "text",
"x": 700,
"y": -100,
"width": 200,
"height": 80,
"text": "Detail 1",
"color": "6"
}
],
"edges": [
{
"id": "e1",
"fromNode": "center01",
"fromSide": "right",
"toNode": "branch01",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e2",
"fromNode": "center01",
"fromSide": "right",
"toNode": "branch02",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e3",
"fromNode": "branch01",
"fromSide": "right",
"toNode": "detail01",
"toSide": "left",
"toEnd": "arrow",
"color": "3"
}
]
}
```
## Validation Requirements
When creating canvas files, ensure:
1. **Unique IDs**: All `id` values must be unique across nodes and edges
2. **Valid References**: All edge `fromNode` and `toNode` must reference existing node IDs
3. **Required Fields**: All required attributes are present for each type
4. **Valid Coordinates**: All position/dimension values are integers
5. **Color Format**: Colors use either hex (`"#RRGGBB"`) or preset strings (`"1"` to `"6"`)
6. **Quote Escaping**: Special characters properly escaped in JSON strings
## Common Issues and Solutions
### Issue: Canvas won't open in Obsidian
**Solutions:**
- Validate JSON syntax (use JSON validator)
- Check all IDs are unique
- Verify all edge references exist
- Ensure required fields present
### Issue: Nodes appear overlapped
**Solutions:**
- Increase spacing between coordinates
- Account for node dimensions in positioning
- Use minimum spacing: 320px horizontal, 200px vertical
### Issue: Groups don't show properly
**Solutions:**
- Ensure groups appear before content nodes in array
- Add explicit `label` to all groups
- Check group dimensions encompass child nodes
### Issue: Colors don't match expectations
**Solutions:**
- Use consistent color format (all hex OR all presets)
- Remember presets adapt to theme
- Test in both light and dark mode if using custom colors
### Issue: Text appears truncated
**Solutions:**
- Increase node dimensions
- Break long text into multiple nodes
- Use file nodes for lengthy content
## Character Encoding for Chinese Content
When canvas contains Chinese text, apply these transformations:
- Chinese double quotes `"``『』`
- Chinese single quotes `'``「」`
- English double quotes must be escaped: `\"`
**Example:**
```json
{
"text": "『核心概念』包含:「子概念A」和「子概念B」"
}
```
This prevents JSON parsing errors with mixed-language content.
## Performance Considerations
- **Large Canvases**: Keep node count reasonable (<500 for smooth performance)
- **Image Files**: Use compressed images for backgrounds
- **Text Length**: Keep node text concise; use file nodes for long content
- **Edge Complexity**: Minimize crossing edges for clarity
## Future Extensions
This specification may be extended with:
- Additional node types
- More edge styling options
- Animation properties
- Interactive behaviors
Always check Obsidian documentation for latest Canvas features.

View File

@@ -0,0 +1,614 @@
# Layout Algorithms for Obsidian Canvas
Detailed algorithms for positioning nodes in MindMap and Freeform layouts.
## Layout Principles
### Universal Spacing Constants
```
HORIZONTAL_SPACING = 320 // Minimum horizontal space between node centers
VERTICAL_SPACING = 200 // Minimum vertical space between node centers
NODE_PADDING = 20 // Internal padding within nodes
```
### Collision Detection
Before finalizing any node position, verify:
```python
def check_collision(node1, node2):
"""Returns True if nodes overlap or are too close"""
center1_x = node1.x + node1.width / 2
center1_y = node1.y + node1.height / 2
center2_x = node2.x + node2.width / 2
center2_y = node2.y + node2.height / 2
dx = abs(center1_x - center2_x)
dy = abs(center1_y - center2_y)
min_dx = (node1.width + node2.width) / 2 + HORIZONTAL_SPACING
min_dy = (node1.height + node2.height) / 2 + VERTICAL_SPACING
return dx < min_dx or dy < min_dy
```
## MindMap Layout Algorithm
### 1. Radial Tree Layout
Place root at center, arrange children radially.
#### Step 1: Position Root Node
```python
root = {
"x": 0 - (root_width / 2), # Center horizontally
"y": 0 - (root_height / 2), # Center vertically
"width": root_width,
"height": root_height
}
```
#### Step 2: Calculate Primary Branch Positions
Distribute first-level children around root:
```python
def position_primary_branches(root, children, radius=400):
"""Position first-level children in a circle around root"""
n = len(children)
angle_step = 2 * pi / n
positions = []
for i, child in enumerate(children):
angle = i * angle_step
# Calculate position on circle
x = root.center_x + radius * cos(angle) - child.width / 2
y = root.center_y + radius * sin(angle) - child.height / 2
positions.append({"x": x, "y": y})
return positions
```
**Radius Selection:**
- Small canvases (≤10 children): 400px
- Medium canvases (11-20 children): 500px
- Large canvases (>20 children): 600px
#### Step 3: Position Secondary Branches
For each primary branch, arrange its children:
**Horizontal Layout** (preferred for most cases):
```python
def position_secondary_horizontal(parent, children, distance=350):
"""Arrange children horizontally to the right of parent"""
n = len(children)
total_height = sum(child.height for child in children)
total_spacing = (n - 1) * VERTICAL_SPACING
# Start position (top of vertical arrangement)
start_y = parent.center_y - (total_height + total_spacing) / 2
positions = []
current_y = start_y
for child in children:
x = parent.x + parent.width + distance
y = current_y
positions.append({"x": x, "y": y})
current_y += child.height + VERTICAL_SPACING
return positions
```
**Vertical Layout** (for left/right primary branches):
```python
def position_secondary_vertical(parent, children, distance=250):
"""Arrange children vertically below parent"""
n = len(children)
total_width = sum(child.width for child in children)
total_spacing = (n - 1) * HORIZONTAL_SPACING
# Start position (left of horizontal arrangement)
start_x = parent.center_x - (total_width + total_spacing) / 2
positions = []
current_x = start_x
for child in children:
x = current_x
y = parent.y + parent.height + distance
positions.append({"x": x, "y": y})
current_x += child.width + HORIZONTAL_SPACING
return positions
```
#### Step 4: Balance and Adjust
After initial placement, check for collisions and adjust:
```python
def balance_layout(nodes):
"""Adjust nodes to prevent overlaps"""
max_iterations = 10
for iteration in range(max_iterations):
collisions = find_all_collisions(nodes)
if not collisions:
break
for node1, node2 in collisions:
# Move node2 away from node1
dx = node2.center_x - node1.center_x
dy = node2.center_y - node1.center_y
distance = sqrt(dx*dx + dy*dy)
# Calculate required distance
min_dist = calculate_min_distance(node1, node2)
if distance > 0:
# Move proportionally
move_x = (dx / distance) * (min_dist - distance) / 2
move_y = (dy / distance) * (min_dist - distance) / 2
node2.x += move_x
node2.y += move_y
```
### 2. Tree Layout (Hierarchical Top-Down)
Alternative for deep hierarchies.
#### Positioning Formula
```python
def position_tree_layout(root, tree):
"""Top-down tree layout"""
# Level 0 (root)
root.x = 0 - root.width / 2
root.y = 0 - root.height / 2
# Process each level
for level in range(1, max_depth):
nodes_at_level = get_nodes_at_level(tree, level)
# Calculate horizontal spacing
total_width = sum(node.width for node in nodes_at_level)
total_spacing = (len(nodes_at_level) - 1) * HORIZONTAL_SPACING
start_x = -(total_width + total_spacing) / 2
y = level * (150 + VERTICAL_SPACING) # 150px level height
current_x = start_x
for node in nodes_at_level:
node.x = current_x
node.y = y
current_x += node.width + HORIZONTAL_SPACING
```
## Freeform Layout Algorithm
### 1. Content-Based Grouping
First, identify natural groupings in content:
```python
def identify_groups(nodes, content_structure):
"""Group nodes by semantic relationships"""
groups = []
# Analyze content structure
for section in content_structure:
group_nodes = [node for node in nodes if node.section == section]
if len(group_nodes) > 1:
groups.append({
"label": section.title,
"nodes": group_nodes
})
return groups
```
### 2. Grid-Based Zone Layout
Divide canvas into zones for different groups:
```python
def layout_zones(groups, canvas_width=2000, canvas_height=1500):
"""Arrange groups in grid zones"""
n_groups = len(groups)
# Calculate grid dimensions
cols = ceil(sqrt(n_groups))
rows = ceil(n_groups / cols)
zone_width = canvas_width / cols
zone_height = canvas_height / rows
# Assign zones
zones = []
for i, group in enumerate(groups):
col = i % cols
row = i // cols
zone = {
"x": col * zone_width - canvas_width / 2,
"y": row * zone_height - canvas_height / 2,
"width": zone_width * 0.9, # Leave 10% margin
"height": zone_height * 0.9,
"group": group
}
zones.append(zone)
return zones
```
### 3. Within-Zone Node Positioning
Position nodes within each zone:
**Option A: Organic Flow**
```python
def position_organic(zone, nodes):
"""Organic, flowing arrangement within zone"""
positions = []
# Start at zone top-left with margin
current_x = zone.x + 50
current_y = zone.y + 50
row_height = 0
for node in nodes:
# Check if node fits in current row
if current_x + node.width > zone.x + zone.width - 50:
# Move to next row
current_x = zone.x + 50
current_y += row_height + VERTICAL_SPACING
row_height = 0
positions.append({
"x": current_x,
"y": current_y
})
current_x += node.width + HORIZONTAL_SPACING
row_height = max(row_height, node.height)
return positions
```
**Option B: Structured Grid**
```python
def position_grid(zone, nodes):
"""Grid arrangement within zone"""
n = len(nodes)
cols = ceil(sqrt(n))
rows = ceil(n / cols)
cell_width = (zone.width - 100) / cols # 50px margin each side
cell_height = (zone.height - 100) / rows
positions = []
for i, node in enumerate(nodes):
col = i % cols
row = i // cols
# Center node in cell
x = zone.x + 50 + col * cell_width + (cell_width - node.width) / 2
y = zone.y + 50 + row * cell_height + (cell_height - node.height) / 2
positions.append({"x": x, "y": y})
return positions
```
### 4. Cross-Zone Connections
Calculate optimal edge paths between zones:
```python
def calculate_edge_path(from_node, to_node):
"""Determine edge connection points"""
# Calculate centers
from_center = (from_node.x + from_node.width/2,
from_node.y + from_node.height/2)
to_center = (to_node.x + to_node.width/2,
to_node.y + to_node.height/2)
# Determine best sides to connect
dx = to_center[0] - from_center[0]
dy = to_center[1] - from_center[1]
# Choose sides based on direction
if abs(dx) > abs(dy):
# Horizontal connection
from_side = "right" if dx > 0 else "left"
to_side = "left" if dx > 0 else "right"
else:
# Vertical connection
from_side = "bottom" if dy > 0 else "top"
to_side = "top" if dy > 0 else "bottom"
return {
"fromSide": from_side,
"toSide": to_side
}
```
## Advanced Techniques
### Force-Directed Layout
For complex networks with many cross-connections:
```python
def force_directed_layout(nodes, edges, iterations=100):
"""Spring-based layout algorithm"""
# Constants
SPRING_LENGTH = 200
SPRING_CONSTANT = 0.1
REPULSION_CONSTANT = 5000
for iteration in range(iterations):
# Calculate repulsive forces (all pairs)
for node1 in nodes:
force_x, force_y = 0, 0
for node2 in nodes:
if node1 == node2:
continue
dx = node1.x - node2.x
dy = node1.y - node2.y
distance = sqrt(dx*dx + dy*dy)
if distance > 0:
# Repulsive force
force = REPULSION_CONSTANT / (distance * distance)
force_x += (dx / distance) * force
force_y += (dy / distance) * force
node1.force_x = force_x
node1.force_y = force_y
# Calculate attractive forces (connected nodes)
for edge in edges:
node1 = get_node(edge.fromNode)
node2 = get_node(edge.toNode)
dx = node2.x - node1.x
dy = node2.y - node1.y
distance = sqrt(dx*dx + dy*dy)
# Spring force
force = SPRING_CONSTANT * (distance - SPRING_LENGTH)
node1.force_x += (dx / distance) * force
node1.force_y += (dy / distance) * force
node2.force_x -= (dx / distance) * force
node2.force_y -= (dy / distance) * force
# Apply forces
for node in nodes:
node.x += node.force_x
node.y += node.force_y
```
### Hierarchical Clustering
Group related nodes automatically:
```python
def hierarchical_cluster(nodes, similarity_threshold=0.7):
"""Cluster nodes by content similarity"""
clusters = []
# Calculate similarity matrix
similarity = calculate_similarity_matrix(nodes)
# Agglomerative clustering
current_clusters = [[node] for node in nodes]
while len(current_clusters) > 1:
# Find most similar clusters
max_sim = 0
merge_i, merge_j = 0, 1
for i in range(len(current_clusters)):
for j in range(i + 1, len(current_clusters)):
sim = cluster_similarity(current_clusters[i],
current_clusters[j],
similarity)
if sim > max_sim:
max_sim = sim
merge_i, merge_j = i, j
if max_sim < similarity_threshold:
break
# Merge clusters
current_clusters[merge_i].extend(current_clusters[merge_j])
current_clusters.pop(merge_j)
return current_clusters
```
## Layout Optimization
### Minimize Edge Crossings
```python
def minimize_crossings(nodes, edges):
"""Reduce edge crossing through node repositioning"""
crossings = count_crossings(edges)
# Try swapping adjacent nodes
improved = True
while improved:
improved = False
for i in range(len(nodes) - 1):
# Swap nodes i and i+1
swap_positions(nodes[i], nodes[i+1])
new_crossings = count_crossings(edges)
if new_crossings < crossings:
crossings = new_crossings
improved = True
else:
# Swap back
swap_positions(nodes[i], nodes[i+1])
```
### Visual Balance
```python
def calculate_visual_weight(canvas):
"""Calculate center of mass for visual balance"""
total_weight = 0
weighted_x = 0
weighted_y = 0
for node in canvas.nodes:
# Weight is proportional to area
weight = node.width * node.height
total_weight += weight
weighted_x += node.center_x * weight
weighted_y += node.center_y * weight
center_x = weighted_x / total_weight
center_y = weighted_y / total_weight
# Shift entire canvas to center at (0, 0)
offset_x = -center_x
offset_y = -center_y
for node in canvas.nodes:
node.x += offset_x
node.y += offset_y
```
## Performance Optimization
### Spatial Indexing
For large canvases, use spatial indexing to speed up collision detection:
```python
class SpatialGrid:
"""Grid-based spatial index for fast collision detection"""
def __init__(self, cell_size=500):
self.cell_size = cell_size
self.grid = {}
def add_node(self, node):
"""Add node to grid"""
cells = self.get_cells(node)
for cell in cells:
if cell not in self.grid:
self.grid[cell] = []
self.grid[cell].append(node)
def get_cells(self, node):
"""Get grid cells node occupies"""
min_x = int(node.x / self.cell_size)
max_x = int((node.x + node.width) / self.cell_size)
min_y = int(node.y / self.cell_size)
max_y = int((node.y + node.height) / self.cell_size)
cells = []
for x in range(min_x, max_x + 1):
for y in range(min_y, max_y + 1):
cells.append((x, y))
return cells
def get_nearby_nodes(self, node):
"""Get nodes in nearby cells"""
cells = self.get_cells(node)
nearby = set()
for cell in cells:
if cell in self.grid:
nearby.update(self.grid[cell])
return nearby
```
## Common Layout Patterns
### Timeline Layout
For chronological content:
```python
def layout_timeline(events, direction="horizontal"):
"""Create timeline layout"""
if direction == "horizontal":
for i, event in enumerate(events):
event.x = i * (event.width + HORIZONTAL_SPACING)
event.y = 0
else: # vertical
for i, event in enumerate(events):
event.x = 0
event.y = i * (event.height + VERTICAL_SPACING)
```
### Circular Layout
For cyclical processes:
```python
def layout_circular(nodes, radius=500):
"""Arrange nodes in a circle"""
n = len(nodes)
angle_step = 2 * pi / n
for i, node in enumerate(nodes):
angle = i * angle_step
node.x = radius * cos(angle) - node.width / 2
node.y = radius * sin(angle) - node.height / 2
```
### Matrix Layout
For comparing multiple dimensions:
```python
def layout_matrix(nodes, rows, cols):
"""Arrange nodes in a matrix"""
cell_width = 400
cell_height = 250
for i, node in enumerate(nodes):
row = i // cols
col = i % cols
node.x = col * cell_width
node.y = row * cell_height
```
## Quality Checks
Before finalizing layout, verify:
1. **No Overlaps**: All nodes have minimum spacing
2. **Balanced**: Visual center near (0, 0)
3. **Accessible**: All nodes reachable via edges
4. **Readable**: Text sizes appropriate for zoom level
5. **Efficient**: Edge paths reasonably direct
Use these algorithms as foundations, adapting to specific content and user preferences.

View File

@@ -0,0 +1,106 @@
---
name: obsidian-cli
description: Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes.
---
# Obsidian CLI
Use the `obsidian` CLI to interact with a running Obsidian instance. Requires Obsidian to be open.
## Command reference
Run `obsidian help` to see all available commands. This is always up to date. Full docs: https://help.obsidian.md/cli
## Syntax
**Parameters** take a value with `=`. Quote values with spaces:
```bash
obsidian create name="My Note" content="Hello world"
```
**Flags** are boolean switches with no value:
```bash
obsidian create name="My Note" silent overwrite
```
For multiline content use `\n` for newline and `\t` for tab.
## File targeting
Many commands accept `file` or `path` to target a file. Without either, the active file is used.
- `file=<name>` — resolves like a wikilink (name only, no path or extension needed)
- `path=<path>` — exact path from vault root, e.g. `folder/note.md`
## Vault targeting
Commands target the most recently focused vault by default. Use `vault=<name>` as the first parameter to target a specific vault:
```bash
obsidian vault="My Vault" search query="test"
```
## Common patterns
```bash
obsidian read file="My Note"
obsidian create name="New Note" content="# Hello" template="Template" silent
obsidian append file="My Note" content="New line"
obsidian search query="search term" limit=10
obsidian daily:read
obsidian daily:append content="- [ ] New task"
obsidian property:set name="status" value="done" file="My Note"
obsidian tasks daily todo
obsidian tags sort=count counts
obsidian backlinks file="My Note"
```
Use `--copy` on any command to copy output to clipboard. Use `silent` to prevent files from opening. Use `total` on list commands to get a count.
## Plugin development
### Develop/test cycle
After making code changes to a plugin or theme, follow this workflow:
1. **Reload** the plugin to pick up changes:
```bash
obsidian plugin:reload id=my-plugin
```
2. **Check for errors** — if errors appear, fix and repeat from step 1:
```bash
obsidian dev:errors
```
3. **Verify visually** with a screenshot or DOM inspection:
```bash
obsidian dev:screenshot path=screenshot.png
obsidian dev:dom selector=".workspace-leaf" text
```
4. **Check console output** for warnings or unexpected logs:
```bash
obsidian dev:console level=error
```
### Additional developer commands
Run JavaScript in the app context:
```bash
obsidian eval code="app.vault.getFiles().length"
```
Inspect CSS values:
```bash
obsidian dev:css selector=".workspace-leaf" prop=background-color
```
Toggle mobile emulation:
```bash
obsidian dev:mobile on
```
Run `obsidian help` to see additional developer commands including CDP and debugger controls.

View File

@@ -0,0 +1,196 @@
---
name: obsidian-markdown
description: Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
---
# Obsidian Flavored Markdown Skill
Create and edit valid Obsidian Flavored Markdown. Obsidian extends CommonMark and GFM with wikilinks, embeds, callouts, properties, comments, and other syntax. This skill covers only Obsidian-specific extensions -- standard Markdown (headings, bold, italic, lists, quotes, code blocks, tables) is assumed knowledge.
## Workflow: Creating an Obsidian Note
1. **Add frontmatter** with properties (title, tags, aliases) at the top of the file. See [PROPERTIES.md](references/PROPERTIES.md) for all property types.
2. **Write content** using standard Markdown for structure, plus Obsidian-specific syntax below.
3. **Link related notes** using wikilinks (`[[Note]]`) for internal vault connections, or standard Markdown links for external URLs.
4. **Embed content** from other notes, images, or PDFs using the `![[embed]]` syntax. See [EMBEDS.md](references/EMBEDS.md) for all embed types.
5. **Add callouts** for highlighted information using `> [!type]` syntax. See [CALLOUTS.md](references/CALLOUTS.md) for all callout types.
6. **Verify** the note renders correctly in Obsidian's reading view.
> When choosing between wikilinks and Markdown links: use `[[wikilinks]]` for notes within the vault (Obsidian tracks renames automatically) and `[text](url)` for external URLs only.
## Internal Links (Wikilinks)
```markdown
[[Note Name]] Link to note
[[Note Name|Display Text]] Custom display text
[[Note Name#Heading]] Link to heading
[[Note Name#^block-id]] Link to block
[[#Heading in same note]] Same-note heading link
```
Define a block ID by appending `^block-id` to any paragraph:
```markdown
This paragraph can be linked to. ^my-block-id
```
For lists and quotes, place the block ID on a separate line after the block:
```markdown
> A quote block
^quote-id
```
## Embeds
Prefix any wikilink with `!` to embed its content inline:
```markdown
![[Note Name]] Embed full note
![[Note Name#Heading]] Embed section
![[image.png]] Embed image
![[image.png|300]] Embed image with width
![[document.pdf#page=3]] Embed PDF page
```
See [EMBEDS.md](references/EMBEDS.md) for audio, video, search embeds, and external images.
## Callouts
```markdown
> [!note]
> Basic callout.
> [!warning] Custom Title
> Callout with a custom title.
> [!faq]- Collapsed by default
> Foldable callout (- collapsed, + expanded).
```
Common types: `note`, `tip`, `warning`, `info`, `example`, `quote`, `bug`, `danger`, `success`, `failure`, `question`, `abstract`, `todo`.
See [CALLOUTS.md](references/CALLOUTS.md) for the full list with aliases, nesting, and custom CSS callouts.
## Properties (Frontmatter)
```yaml
---
title: My Note
date: 2024-01-15
tags:
- project
- active
aliases:
- Alternative Name
cssclasses:
- custom-class
---
```
Default properties: `tags` (searchable labels), `aliases` (alternative note names for link suggestions), `cssclasses` (CSS classes for styling).
See [PROPERTIES.md](references/PROPERTIES.md) for all property types, tag syntax rules, and advanced usage.
## Tags
```markdown
#tag Inline tag
#nested/tag Nested tag with hierarchy
```
Tags can contain letters, numbers (not first character), underscores, hyphens, and forward slashes. Tags can also be defined in frontmatter under the `tags` property.
## Comments
```markdown
This is visible %%but this is hidden%% text.
%%
This entire block is hidden in reading view.
%%
```
## Obsidian-Specific Formatting
```markdown
==Highlighted text== Highlight syntax
```
## Math (LaTeX)
```markdown
Inline: $e^{i\pi} + 1 = 0$
Block:
$$
\frac{a}{b} = c
$$
```
## Diagrams (Mermaid)
````markdown
```mermaid
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Do this]
B -->|No| D[Do that]
```
````
To link Mermaid nodes to Obsidian notes, add `class NodeName internal-link;`.
## Footnotes
```markdown
Text with a footnote[^1].
[^1]: Footnote content.
Inline footnote.^[This is inline.]
```
## Complete Example
````markdown
---
title: Project Alpha
date: 2024-01-15
tags:
- project
- active
status: in-progress
---
# Project Alpha
This project aims to [[improve workflow]] using modern techniques.
> [!important] Key Deadline
> The first milestone is due on ==January 30th==.
## Tasks
- [x] Initial planning
- [ ] Development phase
- [ ] Backend implementation
- [ ] Frontend design
## Notes
The algorithm uses $O(n \log n)$ sorting. See [[Algorithm Notes#Sorting]] for details.
![[Architecture Diagram.png|600]]
Reviewed in [[Meeting Notes 2024-01-10#Decisions]].
````
## References
- [Obsidian Flavored Markdown](https://help.obsidian.md/obsidian-flavored-markdown)
- [Internal links](https://help.obsidian.md/links)
- [Embed files](https://help.obsidian.md/embeds)
- [Callouts](https://help.obsidian.md/callouts)
- [Properties](https://help.obsidian.md/properties)

View File

@@ -0,0 +1,58 @@
# Callouts Reference
## Basic Callout
```markdown
> [!note]
> This is a note callout.
> [!info] Custom Title
> This callout has a custom title.
> [!tip] Title Only
```
## Foldable Callouts
```markdown
> [!faq]- Collapsed by default
> This content is hidden until expanded.
> [!faq]+ Expanded by default
> This content is visible but can be collapsed.
```
## Nested Callouts
```markdown
> [!question] Outer callout
> > [!note] Inner callout
> > Nested content
```
## Supported Callout Types
| Type | Aliases | Color / Icon |
|------|---------|-------------|
| `note` | - | Blue, pencil |
| `abstract` | `summary`, `tldr` | Teal, clipboard |
| `info` | - | Blue, info |
| `todo` | - | Blue, checkbox |
| `tip` | `hint`, `important` | Cyan, flame |
| `success` | `check`, `done` | Green, checkmark |
| `question` | `help`, `faq` | Yellow, question mark |
| `warning` | `caution`, `attention` | Orange, warning |
| `failure` | `fail`, `missing` | Red, X |
| `danger` | `error` | Red, zap |
| `bug` | - | Red, bug |
| `example` | - | Purple, list |
| `quote` | `cite` | Gray, quote |
## Custom Callouts (CSS)
```css
.callout[data-callout="custom-type"] {
--callout-color: 255, 0, 0;
--callout-icon: lucide-alert-circle;
}
```

View File

@@ -0,0 +1,63 @@
# Embeds Reference
## Embed Notes
```markdown
![[Note Name]]
![[Note Name#Heading]]
![[Note Name#^block-id]]
```
## Embed Images
```markdown
![[image.png]]
![[image.png|640x480]] Width x Height
![[image.png|300]] Width only (maintains aspect ratio)
```
## External Images
```markdown
![Alt text](https://example.com/image.png)
![Alt text|300](https://example.com/image.png)
```
## Embed Audio
```markdown
![[audio.mp3]]
![[audio.ogg]]
```
## Embed PDF
```markdown
![[document.pdf]]
![[document.pdf#page=3]]
![[document.pdf#height=400]]
```
## Embed Lists
```markdown
![[Note#^list-id]]
```
Where the list has a block ID:
```markdown
- Item 1
- Item 2
- Item 3
^list-id
```
## Embed Search Results
````markdown
```query
tag:#project status:done
```
````

View File

@@ -0,0 +1,61 @@
# Properties (Frontmatter) Reference
Properties use YAML frontmatter at the start of a note:
```yaml
---
title: My Note Title
date: 2024-01-15
tags:
- project
- important
aliases:
- My Note
- Alternative Name
cssclasses:
- custom-class
status: in-progress
rating: 4.5
completed: false
due: 2024-02-01T14:30:00
---
```
## Property Types
| Type | Example |
|------|---------|
| Text | `title: My Title` |
| Number | `rating: 4.5` |
| Checkbox | `completed: true` |
| Date | `date: 2024-01-15` |
| Date & Time | `due: 2024-01-15T14:30:00` |
| List | `tags: [one, two]` or YAML list |
| Links | `related: "[[Other Note]]"` |
## Default Properties
- `tags` - Note tags (searchable, shown in graph view)
- `aliases` - Alternative names for the note (used in link suggestions)
- `cssclasses` - CSS classes applied to the note in reading/editing view
## Tags
```markdown
#tag
#nested/tag
#tag-with-dashes
#tag_with_underscores
```
Tags can contain: letters (any language), numbers (not first character), underscores `_`, hyphens `-`, forward slashes `/` (for nesting).
In frontmatter:
```yaml
---
tags:
- tag1
- nested/tag2
---
```

View File

@@ -0,0 +1,68 @@
{
"userName": "BlueRose",
"permissionMode": "yolo",
"model": "opus[1m]",
"thinkingBudget": "medium",
"effortLevel": "low",
"serviceTier": "default",
"enableAutoTitleGeneration": true,
"titleGenerationModel": "",
"excludedTags": [],
"mediaFolder": "",
"systemPrompt": "",
"persistentExternalContextPaths": [],
"sharedEnvironmentVariables": "",
"envSnippets": [],
"customContextLimits": {},
"keyboardNavigation": {
"scrollUpKey": "w",
"scrollDownKey": "s",
"focusInputKey": "i"
},
"locale": "en",
"providerConfigs": {
"claude": {
"safeMode": "acceptEdits",
"cliPath": "",
"cliPathsByHost": {},
"loadUserSettings": true,
"enableChrome": false,
"enableBangBash": false,
"enableOpus1M": true,
"enableSonnet1M": false,
"lastModel": "opus[1m]",
"environmentVariables": "",
"environmentHash": ""
},
"codex": {
"enabled": false,
"safeMode": "workspace-write",
"cliPath": "",
"cliPathsByHost": {},
"reasoningSummary": "detailed",
"environmentVariables": "",
"environmentHash": "",
"installationMethod": "native-windows",
"installationMethodsByHost": {},
"wslDistroOverride": "",
"wslDistroOverridesByHost": {}
}
},
"settingsProvider": "claude",
"savedProviderModel": {
"claude": "opus[1m]"
},
"savedProviderEffort": {
"claude": "low"
},
"savedProviderServiceTier": {},
"savedProviderThinkingBudget": {
"claude": "medium"
},
"lastCustomModel": "",
"maxTabs": 3,
"tabBarPosition": "input",
"enableAutoScroll": true,
"openInMainTab": false,
"hiddenProviderCommands": {}
}

View File

@@ -0,0 +1,24 @@
{
"id": "conv-1776071385957-rol42oxg8",
"providerId": "claude",
"title": "Greet user in Chinese",
"titleGenerationStatus": "success",
"createdAt": 1776071385957,
"updatedAt": 1776179962356,
"lastResponseAt": 1776179962356,
"sessionId": "c432006f-72f1-4f80-9625-7cb62e468878",
"providerState": {
"providerSessionId": "c432006f-72f1-4f80-9625-7cb62e468878"
},
"currentNote": "07-Other/AI/Obsidian/Obsidian CLI.md",
"usage": {
"model": "opus[1m]",
"inputTokens": 1,
"cacheCreationInputTokens": 1084,
"cacheReadInputTokens": 41428,
"contextWindow": 1000000,
"contextTokens": 42513,
"percentage": 4,
"contextWindowIsAuthoritative": true
}
}

2
.obsidian/app.json vendored
View File

@@ -4,7 +4,7 @@
"promptDelete": false,
"pdfExportSettings": {
"includeName": true,
"pageSize": "A3",
"pageSize": "A4",
"landscape": false,
"margin": "0",
"downscalePercent": 87

View File

@@ -36,5 +36,6 @@
"Enhanced-editing",
"table-editor-obsidian",
"obsidian-excalidraw-plugin",
"image-captions"
"image-captions",
"claudian"
]

11
.obsidian/plugins/claudian/data.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"tabManagerState": {
"openTabs": [
{
"tabId": "tab-1776071369651-6oz9pqs",
"conversationId": "conv-1776071385957-rol42oxg8"
}
],
"activeTabId": "tab-1776071369651-6oz9pqs"
}
}

84218
.obsidian/plugins/claudian/main.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
{
"id": "claudian",
"name": "Claudian",
"version": "2.0.2",
"minAppVersion": "1.4.5",
"description": "Embeds Claude Code as an AI collaborator in your vault. Your vault becomes Claude's working directory, giving it full agentic capabilities: file read/write, search, bash commands, and multi-step workflows.",
"author": "Yishen Tu",
"authorUrl": "https://github.com/YishenTu",
"isDesktopOnly": true
}

5699
.obsidian/plugins/claudian/styles.css vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
{"截帧并且返回结果。":{"截帧并且返回结果。":{"currentFile":{"count":1,"lastUpdated":1770709439590}}},"Maya CMake笔记":{"Maya CMake笔记":{"internalLink":{"count":1,"lastUpdated":1770716829521}}},"MCP商店":{"MCP商店":{"currentFile":{"count":1,"lastUpdated":1770718675186}}},"Simplegen":{"Simplegen":{"currentFile":{"count":1,"lastUpdated":1770720333062}}},"README":{"README":{"internalLink":{"count":1,"lastUpdated":1770818577089}}},"Notification":{"Notification":{"currentFile":{"count":1,"lastUpdated":1770818619712}}},"ServiceRequest":{"ServiceRequest":{"internalLink":{"count":1,"lastUpdated":1772077751440}}},"skills":{"skills":{"currentFile":{"count":1,"lastUpdated":1772100003535}}},"Bilibili":{"Bilibili":{"currentFile":{"count":1,"lastUpdated":1772112409334}}},"using-superpowers":{"using-superpowers":{"currentFile":{"count":1,"lastUpdated":1772348498708}}},"添加新的护城河引擎相关MCP&Skill、AITA资产库":{"添加新的护城河引擎相关MCP&Skill、AITA资产库":{"currentFile":{"count":1,"lastUpdated":1772891664291}}}}
{"Agent":{"Agent":{"internalLink":{"count":2,"lastUpdated":1773554273209}}},"要解决这个问题,得对记忆进行合理规划与维护:":{"要解决这个问题,得对记忆进行合理规划与维护:":{"currentFile":{"count":1,"lastUpdated":1774938677236}}},"Openclaw-workspace":{"Openclaw-workspace":{"currentFile":{"count":1,"lastUpdated":1774938879095}}},"workflow":{"workflow":{"currentFile":{"count":1,"lastUpdated":1775020352083}}},"\\AI\\Skill\\MatrixAITA-POPODocs-Skill、D":{"\\AI\\Skill\\MatrixAITA-POPODocs-Skill、D":{"currentFile":{"count":1,"lastUpdated":1776242568663}}},"推荐加在仓库内已有的标准元数据文件中,例如:":{"推荐加在仓库内已有的标准元数据文件中,例如:":{"currentFile":{"count":1,"lastUpdated":1776242909075}}},"推荐加在仓库内已有的标准元数据文件中,":{"推荐加在仓库内已有的标准元数据文件中,":{"currentFile":{"count":1,"lastUpdated":1776242914868}}}}

View File

@@ -6,7 +6,7 @@
"workspaceSettings": false,
"systemDarkMode": false,
"globalSettings": {},
"activeWorkspaceDesktop": "阅读模式",
"activeWorkspaceDesktop": "编辑模式",
"activeWorkspaceMobile": "",
"reloadLivePreview": false,
"workspaceSwitcherRibbon": false,

View File

@@ -368,5 +368,5 @@
"workspaces-plus:settings-v1": {}
}
},
"active": "阅读模式"
"active": "编辑模式"
}

View File

@@ -0,0 +1,20 @@
---
title: 未命名
date: 2026-04-02 20:19:19
excerpt:
tags:
rating: ⭐
status: inprogress
destination:
share: false
obsidianUIMode: source
---
武林有2个方向:
1. 第一天(西湖 Or 运河)
1. 往北可以坐地铁到香积寺,参观香积寺以及边上的大兜路特色街区,之后可以到乐堤港综合体吃个饭啥;之后可以坐地铁到拱宸桥看一下运河公园以及边上的街区。
2. 往南可以坐地铁到凤起路,那边有一家抹茶店可以去体验一下(得早点去要排队),之后可以去往西湖边走,到西湖后继续往南,走到龙翔桥附近,可以考虑逛 银泰(吃饭啥)。之后继续往南
1. 可以考虑去柳浪闻莺公园 => 坐观光车 => 游西湖 => 太子湾公园 => 苏堤 => 断桥
2. 可以考虑去吴山广场 => 河坊街 => 胡雪岩故居 => 鼓楼附近吃饭啥的。去附近的候潮门 地铁站 (或者打车)=> 市民中心(附近有来福士、万象城综合体) => 走到城市阳台 看杭州的灯光秀记得是18:30结束
2. 第二天(西溪湿地)
1. 做地铁到 天目里 => 西溪天堂 => 西溪湿地南部小路 => 高庄 => 福堤 => 西溪龙湖天街

View File

@@ -0,0 +1,70 @@
# 部署
```bash
mkdir -p /home/matriaita_docker/oss/minio
mkdir -p /home/matriaita_docker/oss/alist
```
```yml
version: '3.8'
services:
minio:
image: pgsty/minio:latest
container_name: minio
restart: always
ports:
- "9000:9000" # S3 API
- "9001:9001" # 管理后台
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: mataita@666
# --- 新增以下配置 ---
# 1. 解决分享链接打不开的问题(设为你的 API 访问地址)
MINIO_SERVER_URL: "http://ta.netease.com:9000"
# 2. 解决管理后台登录跳转地址不对的问题
MINIO_BROWSER_REDIRECT_URL: "http://ta.netease.com:9001"
# 3. 解决跨域问题(允许来自 ta.netease.com 的请求,或者设为 * 允许所有)
MINIO_API_CORS_ALLOW_ORIGIN: "http://ta.netease.com,http://ta.netease.com:5244"
volumes:
- ./minio:/data
command: server /data --console-address ":9001"
alist:
image: xhofe/alist:latest
container_name: alist
restart: always
ports:
- "5244:5244"
volumes:
- ./alist:/opt/alist/data
environment:
- PUID=1000
- PGID=1000
- UMASK=022
depends_on:
- minio
```
## 配置步骤
- 启动:`docker-compose up -d`
- 获取 AList 密码:`docker exec -it alist ./alist admin`
- **配置 MinIO**
- 访问 `http://服务器IP:9001`
- 创建一个 Bucket`obsidian-assets`)。
- 在 Access Keys 中创建一个 Key记下 `Access Key``Secret Key`
- **配置 AList**
- 访问 `http://服务器IP:5244`
- 进入“管理” -> “存储” -> “添加”。驱动选 **MinIO**
- **挂载路径**填 `/assets`
- **Endpoint** 填 `http://minio:9000`(如果 AList 和 MinIO 在同一台服务器的 Docker 网络中)。
- 填入刚才 MinIO 的 Bucket 和 Key。
## 相关信息
1. MinIO
1. `Access Key`r9uq0TP7ZbF5BA41Gb6E
2. `Secret Key`DstYixNcDnumg5qZPRg4XxMfVZb2XFwH92ow0SbP
2. AList
1. admin
2. NEW_PASSWORD

View File

@@ -16,6 +16,7 @@ rating: ⭐
- https://github.com/Tencent/puerts/issues
- https://github.com/Tencent/puerts/discussions
# QuickStart
- Puerts AI初始化Skill: https://github.com/noobGuaTai/ue5-puerts-init-skill
## Setup
1. 安装Nodejs v22.17.1。
2. 通过安装全局typeScrpit模块。
@@ -35,7 +36,7 @@ npm install -g typescript
"dependencies": {
"@types/mocha": "^10.0.10"
}
```
```
5. 打开工程,在引擎中点击 ue.d.ts 。 该功能用于生成项目、引擎符号信息生成之后就能找到相关符号了。如果想在ts文件中调用新增的蓝图&C++方法也需要点击ue.d.ts才能找到对应符号。可以阅读该文了解详细信息 https://puerts.github.io/docs/puerts/unreal/script_call_uclass
![[Puerts_UE_D_TS.png]]
6.`ProjectSettings - Packaging - Additional Not-Asset Directories to Package`中添加`Content/javaScript`

View File

@@ -0,0 +1,187 @@
---
title: 未命名
date: 2026-03-25 21:43:14
excerpt:
tags:
rating: ⭐
---
![](https://pic4.zhimg.com/v2-c88b1dc29371ae1cfb4a788f6cd5fee3_1440w.jpg)
## 前言
之前写过一些截帧的文章主要是通过模拟器来绕过加密系统但是现在想想有可能两个游戏在移动端和PC端上用的Shader不一样现在想用[RenderDoc](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=RenderDoc&zhida_source=entity)来截取PC环境下两个游戏的Shader
![](https://pic2.zhimg.com/v2-4a50acd406d90146397cda94ce7eac1f_1440w.jpg)
## 《鸣潮》是如何检测到RenderDoc的
如果你是直接下载的打包好的RenderDoc那么无论你是否从RenderDoc启动游戏还是是否有任何注入都会显示启用了黑客工具
![](https://pic1.zhimg.com/v2-3e8c32ba0d80dcf93e3e067553f032e8_1440w.jpg)
此外,《鸣潮》采用了[CrashSight](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=CrashSight&zhida_source=entity) 检测所以在做的时候不但要修改RenderDoc的特征码还需要修改注入方式
## 前期准备
RenderDoc的工具集是[VS2015](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=VS2015&zhida_source=entity)的[v140](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=v140&zhida_source=entity)版本我用的是VS2022所以需要额外下载v140组件或者是可以到源码里面手动更新平台工具集
[https://github.com/baldurk/renderdoc/tree/v1.xgithub.com/baldurk/renderdoc/tree/v1.x](https://link.zhihu.com/?target=https%3A//github.com/baldurk/renderdoc/tree/v1.x)
## 一修改RenderDoc的特征来绕过第一步检测
### 核心 DLL — [Replay Marker](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=Replay+Marker&zhida_source=entity) 符号
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdoc/api/replay/renderdoc_replay.h|52|函数名修改|renderdoc__replay__marker()|rendertest__replay__marker()|
> _说明这是最核心的修改。`REPLAY_PROGRAM_MARKER()`_ _宏定义所有 RenderDoc 可执行文件导出的符号DLL 通过动态查找该符号判断当前是 replay 环境还是目标游戏进程。若 DLL 期望_ _`rendertest__replay__marker`_ _但 EXE 导出的是_ _`renderdoc__replay__marker`DLL 将误判为游戏进程并注入 GPU 钩子,导致 UI 崩溃。_
### 进程创建与注入 — 可执行文件路径硬编码
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdoc/os/win32/win32_process.cpp|933|字符串替换|L"\\Win32\\Development\\renderdoccmd.exe"|L"\\Win32\\Development\\rendertestcmd.exe"|
|renderdoc/os/win32/win32_process.cpp|946|字符串替换|L"\\Win32\\Release\\renderdoccmd.exe"|L"\\Win32\\Release\\rendertestcmd.exe"|
|renderdoc/os/win32/win32_process.cpp|961|字符串替换|L"\\x86\\renderdoccmd.exe"|L"\\x86\\rendertestcmd.exe"|
|renderdoc/os/win32/win32_process.cpp|973|字符串替换|L"\\x64\\Development\\renderdoccmd.exe"|L"\\x64\\Development\\rendertestcmd.exe"|
|renderdoc/os/win32/win32_process.cpp|986|字符串替换|L"\\x64\\Release\\renderdoccmd.exe"|L"\\x64\\Release\\rendertestcmd.exe"|
|renderdoc/os/win32/win32_process.cpp|1006|字符串替换|L"\\renderdoccmd.exe"|L"\\rendertestcmd.exe"|
## [Shim DLL](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=Shim+DLL&zhida_source=entity) 路径硬编码
### Shim DLL 路径硬编码
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdoc/os/win32/win32_process.cpp|1783|字符串拼接|"\\renderdocshim64.dll"|"\\rendertestshim64.dll"|
|renderdoc/os/win32/win32_process.cpp|1792|字符串拼接|"\\Win32\\Development\\renderdocshim32.dll"|"\\Win32\\Development\\rendertestshim32.dll"|
|renderdoc/os/win32/win32_process.cpp|1803|字符串拼接|"\\Win32\\Release\\renderdocshim32.dll"|"\\Win32\\Release\\rendertestshim32.dll"|
|renderdoc/os/win32/win32_process.cpp|1811|字符串拼接|"\\x86\\renderdocshim32.dll"|"\\x86\\rendertestshim32.dll"|
|renderdoc/os/win32/win32_process.cpp|1818|字符串拼接|"\\renderdocshim32.dll"|
### [进程白名单](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=%E8%BF%9B%E7%A8%8B%E7%99%BD%E5%90%8D%E5%8D%95&zhida_source=entity) — 避免注入到 RenderTest 自身
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdoc/os/win32/sys_win32_hooks.cpp|342|字符串替换|"renderdoccmd.exe" \| app.contains("qrenderdoc.exe")|"rendertestcmd.exe" \| app.contains("qrendertest.exe")|
|renderdoc/os/win32/sys_win32_hooks.cpp|351|字符串替换|"renderdoccmd.exe" \| cmd.contains("qrenderdoc.exe")|"rendertestcmd.exe" \| cmd.contains("qrendertest.exe")|
### 崩溃处理 — 命名内核对象
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdoccmd/renderdoccmd_win32.cpp|603|字符串替换|"RENDERDOC_CRASHHANDLE"|"RENDERTEST_CRASHHANDLE"|
|renderdoccmd/renderdoccmd_win32.cpp|818|字符串替换|GetModuleHandleA("renderdoc.dll")|GetModuleHandleA("rendertest.dll")|
|core/crash_handler.h|62|字符串拼接|"RenderDoc\\dumps\\a"|"RenderTest\\dumps\\a"|
|core/crash_handler.h|168|字符串拼接|"RenderDocBreakpadServer%llu"|"RenderTestBreakpadServer%llu"|
### 表格 6文件路径与注册表
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdoc/os/win32/win32_stringio.cpp|289|字符串拼接|"/qrenderdoc.exe"|"/qrendertest.exe"|
|renderdoc/os/win32/win32_stringio.cpp|300|字符串拼接|"/../qrenderdoc.exe"|"/../qrendertest.exe"|
|renderdoc/os/win32/win32_stringio.cpp|316|注册表路径|L"RenderDoc.RDCCapture.1\\DefaultIcon"|L"RenderTest.RDCCapture.1\\DefaultIcon"|
|renderdoc/os/win32/win32_stringio.cpp|358|日志路径|L"RenderDoc\\%ls_..."|L"RenderTest\\%ls_..."|
|renderdoc/os/win32/win32_stringio.cpp|367|日志路径|L"RenderDoc\\%ls_..."|L"RenderTest\\%ls_..."|
### OpenGL 窗口类名
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|driver/gl/wgl_platform.cpp|28|宏定义|L"renderdocGLclass"|L"rendertestGLclass"|
### [全局 Hook 共享内存名称](https://zhida.zhihu.com/search?content_id=271977473&content_type=Article&match_order=1&q=%E5%85%A8%E5%B1%80+Hook+%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98%E5%90%8D%E7%A7%B0&zhida_source=entity)
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|renderdocshim/renderdocshim.h|36|宏定义|"RenderDocGlobalHookData64"|"RenderTestGlobalHookData64"|
|renderdocshim/renderdocshim.h|39|宏定义|"RenderDocGlobalHookData32"|"RenderTestGlobalHookData32"|
### 资源文件
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|data/renderdoc.rc|87|资源字符串|"Core DLL for RenderDoc"|"Core DLL for RenderTest"|
|data/renderdoc.rc|92|资源字符串|"ProductName", "RenderDoc"|"ProductName", "RenderTest"|
### Qt UI 层
|文件路径|行号|修改类型|修改前|修改后|
|---|---|---|---|---|
|qrenderdoc/renderdocui_stub.cpp|62|字符串拼接|L"qrenderdoc.exe"|L"qrendertest.exe"|
|qrenderdoc/Code/qrenderdoc.cpp|173|Qt 翻译上下文|"qrenderdoc"|"qrendertest"|
|qrenderdoc/Code/qrenderdoc.cpp|198|日志输出|"QRenderDoc initialising."|"QRenderTest initialising."|
|qrenderdoc/Code/qrenderdoc.cpp|267|会话名|"QRenderDoc"|"QRenderTest"|
|qrenderdoc/Code/qrenderdoc.cpp|330|描述文本|"Qt UI for RenderDoc"|"Qt UI for RenderTest"|
|qrenderdoc/Code/qrenderdoc.cpp|393|版本输出|"QRenderDoc v%s"|"QRenderTest v%s"|
|qrenderdoc/Windows/MainWindow.cpp|1217|窗口标题|"RenderDoc "|"RenderTest "|
### VS 项目文件(编译输出名 + UAC 提权)
|文件路径|属性|修改类型|修改前|修改后|
|---|---|---|---|---|
|qrenderdoc/renderdocui_stub.vcxproj|RootNamespace|修改|renderdocui_stub|rendertestui_stub|
|qrenderdoc/renderdocui_stub.vcxproj|ProjectName|修改|renderdocui_stub|rendertestui_stub|
|qrenderdoc/renderdocui_stub.vcxproj|PrimaryOutput|新增|(无)|rendertestui|
|qrenderdoc/renderdocui_stub.vcxproj|TargetName|新增|(无)|rendertestui|
|qrenderdoc/renderdocui_stub.vcxproj|UACExecutionLevel|新增|(无)|RequireAdmini|
## CrashSight检测
这里可以在Hook的时候采用SetThreadContext注入
修改文件:renderdoc/os/win32/win32_process.cpp
```text
uintptr_t loc = FindRemoteDLL(pi.dwProcessId, STRINGIZE(RDOC_BASE_NAME) ".dll");
CloseHandle(hProcess);
hProcess = NULL;
if(loc != 0)
```
编辑于 2026-03-25 11:37・重庆

View File

@@ -0,0 +1,2 @@
# 前言
- [ ] https://www.bilibili.com/video/BV1VzfoBFE5w/?spm_id_from=333.1387.homepage.video_card.click&vd_source=a5a1507212662f8883c096200c37b6bd

View File

@@ -404,4 +404,5 @@ remaining-fix (4 Agent) 剩余问题并行修复
│ 完成 → 销毁
```
每支团队拥有独立的 TaskList 和成员列表,团队之间通过**共享文件系统**传递成果(上一支团队的代码产出是下一支团队的评审/修复输入。Team Lead 的主会话贯穿全程,是唯一跨团队的持久上下文。
每支团队拥有独立的 TaskList 和成员列表,团队之间通过**共享文件系统**传递成果(上一支团队的代码产出是下一支团队的评审/修复输入。Team Lead 的主会话贯穿全程,是唯一跨团队的持久上下文。

View File

@@ -0,0 +1,42 @@
```markdown
────────────────
B背景
────────────────
我是[XX身份老师/作者],正在进行[XX项目]
我们即将结束当前对话,需要保存完整上下文
────────────────
T任务
────────────────
在我们继续之前,请先完成以下动作:
生成【记忆胶囊】,记录项目全貌和当前状态
确保一个全新对话能凭此文档无损接续工作
────────────────
C约束
────────────────
短句优先每条1~2句话动词开头信息密度最大化
不确定或未提及的信息,标注【待确认】。
禁止补充推测、美化或编造内容。
token意识区分信息密度避免废话但不牺牲关键细节
总字数控制在2000字以内约500~1500 tokens
输出结构(严格遵守):
1. 对话主题:正在做什么项目、讨论什么
2. 关键演化:按"最初想法 → 转折/拆解 → 当前焦点"时间线记录
3. 核心观点已达成的关键共识按时间顺序≥3条
4. 进度节点:已完成的阶段 + 当前进度≥2个
5. 待办事项:下一步要做什么 + 阻塞项≥1条
6. 特殊说明:需注意的细节、约定、偏好,
输出格式:
输出为一个完整的 Markdown 文档,便于复制保存。
文件名格式:记忆胶囊-[项目名]-[日期]-[序号].md
(如有文件系统权限,直接保存为文件;否则输出代码块由用户手动保存)
────────────────
A验收必须执行
────────────────
输出前逐一核对6大要素是否齐全。
输出后:标注 ✓完整 / ✗缺项:[原因]
```

View File

@@ -0,0 +1,690 @@
> 本文记录了在 GitLab 项目中集成 Claude Code CLI实现"给 Issue 打标签即可自动修复 Bug"的完整方案与实践过程。
---
## 目录
- [方案概述](#方案概述)
- [整体架构](#整体架构)
- [前置条件](#前置条件)
- [第一步:配置 CI/CD Variables](#第一步配置-cicd-variables)
- [第二步:创建 Pipeline Trigger Token](#第二步创建-pipeline-trigger-token)
- [第三步:编写 .gitlab-ci.yml](#第三步编写-gitlab-ciyml)
- [Job 1: claude:scan-issues — 扫描 Issue](#job-1-claudescan-issues--扫描-issue)
- [Job 2: claude:fix-issue — 执行修复](#job-2-claudefix-issue--执行修复)
- [第四步:创建定时调度](#第四步创建定时调度)
- [第五步:编写 CLAUDE.md 项目指南](#第五步编写-claudemd-项目指南)
- [使用流程](#使用流程)
- [手动触发脚本](#手动触发脚本)
- [关键设计细节](#关键设计细节)
- [踩坑记录与调试经验](#踩坑记录与调试经验)
- [完整 .gitlab-ci.yml 参考](#完整-gitlab-ciyml-参考)
---
## 方案概述
核心思路:利用 GitLab CI/CD 的 **Schedule定时调度** + **Trigger触发器** 机制,定时扫描带有 `auto-fix` 标签的 Issue自动启动 Claude Code CLI 分析代码、修复 Bug、提交代码并在 Issue 上回复修复摘要。
**一句话流程**:开发者给 Issue 打上 `auto-fix` 标签 → 定时任务自动触发 → Claude Code 读取 Issue、分析代码、实施修复 → 自动 commit & push → 在 Issue 评论中报告结果。
---
## 整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ GitLab 项目 │
│ │
│ ┌──────────┐ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Issue │ │ Schedule (定时) │ │ Trigger Pipeline │ │
│ │ auto-fix │───▶│ claude:scan-issues│───▶│ claude:fix-issue │ │
│ │ 标签 │ │ (alpine:3.19) │ │ (node:20) │ │
│ └──────────┘ └──────────────────┘ └─────────┬─────────┘ │
│ │ │
│ ┌───────────▼─────────┐ │
│ │ Claude Code CLI │ │
│ │ (npm i -g 安装) │ │
│ │ │ │
│ │ 1. 读取 Issue 详情 │ │
│ │ 2. 分析项目代码 │ │
│ │ 3. 实施修复 │ │
│ │ 4. 验证类型检查 │ │
│ │ 5. 提交 & 推送 │ │
│ │ 6. 评论 Issue │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 标签状态机
Issue 通过标签流转追踪处理状态,确保不会被重复处理:
```
auto-fix ──▶ claude-processing ──▶ claude-done
(用户添加) (扫描时切换) (修复完成后设置)
```
---
## 前置条件
| 条件 | 说明 |
|------|------|
| GitLab 实例 | 需要支持 CI/CD Schedules 和 Pipeline Triggers |
| Runner | 可执行 Docker 镜像的 GitLab Runner |
| Anthropic API 访问 | 直接使用 Anthropic API 或通过内部代理 |
| GitLab Personal Access Token | 需要 `api` scope用于操作 Issue 和推送代码 |
---
## 第一步:配置 CI/CD Variables
进入 GitLab 项目 → **Settings → CI/CD → Variables**,添加以下变量:
| 变量名 | 类型 | 说明 |
|--------|------|------|
| `GITLAB_ACCESS_TOKEN` | Masked | Personal Access Tokenapi scope扫描 Job 使用 |
| `ANTHROPIC_AUTH_TOKEN` | Masked | Anthropic API Key或内部代理的 auth token |
| `TRIGGER_TOKEN` | 见下一步 | Pipeline 触发器 Token |
> **安全提示**`GITLAB_ACCESS_TOKEN` 和 `ANTHROPIC_AUTH_TOKEN` 务必勾选 **Masked**,防止在日志中泄露。
### 关于 Anthropic API 访问
如果你直接使用 Anthropic 官方 API需要设置
- `ANTHROPIC_AUTH_TOKEN` = 你的 Anthropic API Key
如果使用内部代理(如本项目使用 `openai.nie.netease.com`),则在 CI Job 中通过环境变量指定:
```yaml
variables:
ANTHROPIC_BASE_URL: "https://openai.nie.netease.com" # 内部代理地址
```
---
## 第二步:创建 Pipeline Trigger Token
进入 **Settings → CI/CD → Pipeline trigger tokens**,点击 **Add trigger** 创建一个触发器。
创建后会得到一个 Token将其记录下来。扫描 Job 将用此 Token 触发修复 Pipeline。
将该 Token 设置为 CI/CD Variable `TRIGGER_TOKEN`
---
## 第三步:编写 .gitlab-ci.yml
`.gitlab-ci.yml` 中添加 `ai_fix` Stage 和两个 Job。
### Job 1: claude:scan-issues — 扫描 Issue
这是一个轻量级 Job使用 `alpine:3.19` 镜像,只做 API 调用:
```yaml
stages:
- ai_fix
claude:scan-issues:
stage: ai_fix
image: alpine:3.19
before_script:
- apk add --no-cache curl jq
script:
- |
echo "Scanning for Issues with label 'auto-fix'..."
# 校验必要变量
for var in GITLAB_ACCESS_TOKEN TRIGGER_TOKEN ANTHROPIC_AUTH_TOKEN; do
eval "val=\$$var"
if [ -z "$val" ]; then
echo "ERROR: $var is not set."
exit 1
fi
done
# 查询带 auto-fix 标签的 Issue排除已处理的
ISSUES=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues?labels=auto-fix&not%5Blabels%5D=claude-processing,claude-done&state=opened&per_page=10")
COUNT=$(echo "$ISSUES" | jq 'length')
echo "Found $COUNT issue(s) with 'auto-fix' label."
if [ "$COUNT" -eq 0 ] || [ "$COUNT" = "null" ]; then
echo "Nothing to do."
exit 0
fi
# 逐个处理
echo "$ISSUES" | jq -r '.[].iid' | while read -r IID; do
TITLE=$(echo "$ISSUES" | jq -r ".[] | select(.iid == $IID) | .title")
echo ">>> Triggering fix for Issue #${IID}: ${TITLE}"
# 1) 切换标签: auto-fix → claude-processing
curl -s --request PUT \
--header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"remove_labels\": \"auto-fix\", \"add_labels\": \"claude-processing\"}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$IID" > /dev/null
# 2) 通过 Trigger API 触发修复 Pipeline
curl -s -X POST \
--form "token=${TRIGGER_TOKEN}" \
--form "ref=${CI_DEFAULT_BRANCH}" \
--form "variables[ISSUE_IID]=${IID}" \
--form "variables[GITLAB_TOKEN]=${GITLAB_ACCESS_TOKEN}" \
--form "variables[ANTHROPIC_AUTH_TOKEN]=${ANTHROPIC_AUTH_TOKEN}" \
"https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
done
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"' # 定时触发
- if: '$CI_PIPELINE_SOURCE == "web"' # 手动触发
when: manual
allow_failure: true
timeout: 5m
```
**核心逻辑**
1. 通过 GitLab Issues API 查询 `labels=auto-fix` 且排除 `claude-processing``claude-done` 的 Issue
2. 对每个 Issue 切换标签(防止重复处理)
3. 通过 Pipeline Trigger API 启动独立的修复 Pipeline传入 `ISSUE_IID``GITLAB_TOKEN``ANTHROPIC_AUTH_TOKEN`
### Job 2: claude:fix-issue — 执行修复
这是核心修复 Job使用 `node:20` 镜像,安装并运行 Claude Code
```yaml
claude:fix-issue:
stage: ai_fix
image: node:20
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0 # 完整克隆Claude 需要完整历史
ANTHROPIC_BASE_URL: "https://api.anthropic.com" # 或内部代理地址
ANTHROPIC_MODEL: "claude-sonnet-4-6"
DISABLE_AUTOUPDATER: "1" # 禁止 Claude Code 自动更新
DISABLE_PROMPT_CACHING: "1"
before_script:
- apt-get update && apt-get install -y git curl jq
- npm install -g @anthropic-ai/claude-code
- git config --global user.email "claude-bot@example.com"
- git config --global user.name "Claude AI Bot"
script:
- |
# Step 1: 获取 Issue 详情
if [ -z "$ISSUE_IID" ]; then
echo "ERROR: ISSUE_IID variable is required."
exit 1
fi
ISSUE_JSON=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID")
ISSUE_TITLE=$(echo "$ISSUE_JSON" | jq -r '.title // empty')
ISSUE_DESCRIPTION=$(echo "$ISSUE_JSON" | jq -r '.description // empty')
if [ -z "$ISSUE_TITLE" ]; then
echo "ERROR: Could not fetch Issue #$ISSUE_IID"
exit 1
fi
echo "Processing Issue #${ISSUE_IID}: ${ISSUE_TITLE}"
- |
# Step 2: 切换到主分支
git checkout "$CI_DEFAULT_BRANCH"
git pull origin "$CI_DEFAULT_BRANCH"
- |
# Step 3: 运行 Claude Code
export ANTHROPIC_API_KEY="${ANTHROPIC_AUTH_TOKEN}"
PROMPT="你是一个代码修复助手。请分析并修复以下 GitLab Issue
## Issue #${ISSUE_IID}: ${ISSUE_TITLE}
${ISSUE_DESCRIPTION}
请:
1. 分析项目代码,定位问题根因
2. 实施修复
3. 确保代码能通过类型检查TypeScript 项目运行 npx tsc --noEmit
4. 用中文输出修复摘要(包括修改了哪些文件、改了什么、为什么这样改)
项目根目录已准备就绪。"
RESULT=$(claude -p "$PROMPT" \
--bare \
--permission-mode acceptEdits \
--allowedTools "Bash,Read,Edit,Write,Glob,Grep" \
--max-turns 30 \
--output-format text \
2>&1) || true
echo "$RESULT" > repair_summary.txt
- |
# Step 4: 提交并推送
git add -A
git reset -- repair_summary.txt claude_stderr.txt 2>/dev/null || true
if git diff --cached --quiet; then
echo "No file changes detected."
COMMIT_STATUS="no_changes"
else
git commit -m "fix(auto): resolve Issue #${ISSUE_IID} - ${ISSUE_TITLE} [skip ci]"
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" \
HEAD:"$CI_DEFAULT_BRANCH"
COMMIT_STATUS="pushed"
fi
- |
# Step 5: 在 Issue 上发表评论
SUMMARY=$(cat repair_summary.txt | head -200 | \
sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
if [ "$COMMIT_STATUS" = "pushed" ]; then
BODY="## ✅ Claude Code 自动修复完成\n\n修复已推送到 \`${CI_DEFAULT_BRANCH}\`。\n\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>修复详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
else
BODY="## ⚠️ Claude Code 分析完成\n\n未检测到需要变更的文件。\n\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>分析详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
fi
curl -s --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"body\": \"${BODY}\"}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID/notes"
- |
# Step 6: 更新标签为 claude-done
curl -s --request PUT \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"remove_labels\": \"claude-processing\", \"add_labels\": \"claude-done\"}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID" > /dev/null
rules:
- if: '$CI_PIPELINE_SOURCE == "trigger" && $ISSUE_IID' # 被 scan-issues 触发
- if: '$CI_PIPELINE_SOURCE == "web" && $ISSUE_IID' # 手动触发(需提供 ISSUE_IID
when: manual
allow_failure: true
timeout: 30m
```
**Claude Code CLI 关键参数说明**
| 参数 | 说明 |
|------|------|
| `-p "$PROMPT"` | 非交互模式,直接传入提示词 |
| `--bare` | 精简输出,去掉装饰性格式 |
| `--permission-mode acceptEdits` | 自动接受文件编辑CI 环境必需) |
| `--allowedTools "Bash,Read,Edit,Write,Glob,Grep"` | 限制可用工具,仅保留文件系统操作 |
| `--max-turns 30` | 最大对话轮次,防止无限循环 |
| `--output-format text` | 纯文本输出 |
---
## 第四步:创建定时调度
进入 **CI/CD → Schedules**,创建定时任务:
| 配置项 | 建议值 | 说明 |
|--------|--------|------|
| Description | Auto-fix Issue Scanner | 任务描述 |
| Interval Pattern | `*/5 * * * *` | 每 5 分钟扫描一次 |
| Cron Timezone | 你的时区 | 例如 Asia/Shanghai |
| Target branch | `main` | 主分支 |
保存后Schedule 会按设定频率运行 `claude:scan-issues` Job。
---
## 第五步:编写 CLAUDE.md 项目指南
在项目根目录创建 `CLAUDE.md`Claude Code 在 CI 中运行时会自动读取此文件作为上下文指导:
```markdown
# Project Guidelines
## 项目结构
- `src/` — 主要源码
- `tests/` — 测试文件
## 开发规范
- 修改 TypeScript 代码后运行 `npx tsc --noEmit` 验证类型
- 不要修改 `.gitlab-ci.yml`(除非 Issue 明确要求)
## 关键技术
- 描述项目使用的框架、库、协议等
```
这个文件非常重要,它相当于给 Claude Code 提供了"项目知识",让 AI 了解项目结构和约束,从而做出更合理的修复。
---
## 使用流程
### 自动模式
1. 在 GitLab 上创建一个 Issue描述清楚 Bug 的现象、复现步骤、期望行为
2. 给该 Issue 添加标签 **`auto-fix`**
3. 等待定时调度运行(默认每 5 分钟扫描一次)
4. 标签自动变为 `claude-processing`(正在处理)
5. 修复完成后标签变为 `claude-done`Issue 评论中会出现修复摘要
6. 如果有代码变更commit 会自动推送到 `main` 分支
### 手动模式(命令行触发)
项目提供了便捷脚本 `scripts/trigger-fix.sh`
```bash
# 设置环境变量
export TRIGGER_TOKEN="你的 Trigger Token"
export PROJECT_ID="项目 ID" # Settings → General 可查看
export GITLAB_TOKEN="你的 PAT"
export ANTHROPIC_AUTH_TOKEN="你的 API Key"
# 触发修复
./scripts/trigger-fix.sh 42 # 42 是 Issue 的 IID
```
脚本内容很简洁,直接调用 GitLab Pipeline Trigger API
```bash
curl -X POST \
--form "token=${TRIGGER_TOKEN}" \
--form "ref=main" \
--form "variables[ISSUE_IID]=${ISSUE_IID}" \
--form "variables[GITLAB_TOKEN]=${GITLAB_TOKEN}" \
--form "variables[ANTHROPIC_AUTH_TOKEN]=${ANTHROPIC_AUTH_TOKEN}" \
"https://${GITLAB_HOST}/api/v4/projects/${PROJECT_ID}/trigger/pipeline"
```
---
## 关键设计细节
### 1. 为什么用两个 Job + Trigger 而非一个 Job
- **隔离性**:扫描和修复在不同 Pipeline 中运行,一个 Issue 修复失败不影响其他 Issue
- **并行**:多个 Issue 可以同时被触发修复(各自独立的 Pipeline
- **可追溯**:每个修复有独立的 Pipeline 记录
### 2. 标签状态机防重复
```
auto-fix → claude-processing → claude-done
```
- 扫描 Query 排除 `claude-processing``claude-done`
- 保证每个 Issue **只被处理一次**
### 3. `[skip ci]` 避免递归触发
commit message 中包含 `[skip ci]`,防止修复 commit 触发新的 Pipeline形成无限循环。
### 4. 临时文件排除
`repair_summary.txt``claude_stderr.txt` 通过 `git reset` 排除暂存区,通过 `.gitignore` 排除版本控制:
```gitignore
repair_summary.txt
claude_stderr.txt
```
### 5. Upload Job 与 Fix Job 互不干扰
Upload Job 的 rules 中明确排除 `schedule``trigger` 来源:
```yaml
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_PIPELINE_SOURCE == "trigger"'
when: never
```
### 6. 完整克隆
```yaml
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0
```
Claude Code 需要完整的仓库来分析代码,不能使用浅克隆。
---
## 踩坑记录与调试经验
### 1. Anthropic API 配置
**问题**Claude Code CLI 的环境变量名是 `ANTHROPIC_API_KEY`,但 CI 变量传递时用了别的名字。
**解决**:在 script 中显式映射:
```bash
export ANTHROPIC_API_KEY="${ANTHROPIC_AUTH_TOKEN}"
```
如果使用内部代理,还需设置 `ANTHROPIC_BASE_URL`。额外的 `ANTHROPIC_MODEL``ANTHROPIC_CUSTOM_MODEL_OPTION` 变量用于指定模型。
### 2. Claude Code 自动更新
**问题**CI 环境中 Claude Code 尝试自动更新,导致超时或失败。
**解决**:设置环境变量禁用:
```yaml
DISABLE_AUTOUPDATER: "1"
```
### 3. Issue 查询排除已处理的 Issue
**问题**:早期版本未排除 `claude-processing`/`claude-done`,导致同一 Issue 被反复触发。
**解决**:使用 GitLab API 的 `not[labels]` 参数:
```
?labels=auto-fix&not%5Blabels%5D=claude-processing,claude-done&state=opened
```
### 4. Git Push 认证
**问题**CI 环境默认的 git remote 可能不支持 push。
**解决**:使用 OAuth2 Token 方式构建 push URL
```bash
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:main
```
### 5. 中文输出
**问题**Claude Code 默认可能以英文回复。
**解决**:在 Prompt 中明确要求 "请使用中文回复",确保修复摘要和 Issue 评论为中文。
### 6. 评论中的特殊字符转义
**问题**Claude 的输出可能包含 `"``\`、换行等字符,直接放入 JSON 会破坏格式。
**解决**:通过 `sed` 链式转义:
```bash
SUMMARY=$(cat repair_summary.txt | head -200 | \
sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
```
---
## 完整 .gitlab-ci.yml 参考
以下是 `ai_fix` Stage 的完整配置,可直接复制到你的 `.gitlab-ci.yml` 中:
```yaml
stages:
# ... 你的其他 stages
- ai_fix
# ============================================================
# AI Fix Stage - Auto-fix GitLab Issues with Claude Code
# ============================================================
# Required CI/CD Variables:
# - GITLAB_ACCESS_TOKEN: Personal Access Token (api scope)
# - ANTHROPIC_AUTH_TOKEN: Anthropic API Key
# - TRIGGER_TOKEN: Pipeline trigger token
#
# Setup:
# 1. Create a Schedule (CI/CD → Schedules), e.g. every 5 min
# 2. Add label "auto-fix" to an Issue → auto triggers fix
claude:scan-issues:
stage: ai_fix
image: alpine:3.19
before_script:
- apk add --no-cache curl jq
script:
- |
for var in GITLAB_ACCESS_TOKEN TRIGGER_TOKEN ANTHROPIC_AUTH_TOKEN; do
eval "val=\$$var"
if [ -z "$val" ]; then echo "ERROR: $var not set."; exit 1; fi
done
ISSUES=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues?labels=auto-fix&not%5Blabels%5D=claude-processing,claude-done&state=opened&per_page=10")
COUNT=$(echo "$ISSUES" | jq 'length')
echo "Found $COUNT issue(s)."
[ "$COUNT" -eq 0 ] || [ "$COUNT" = "null" ] && exit 0
echo "$ISSUES" | jq -r '.[].iid' | while read -r IID; do
TITLE=$(echo "$ISSUES" | jq -r ".[] | select(.iid == $IID) | .title")
echo ">>> Issue #${IID}: ${TITLE}"
curl -s --request PUT \
--header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"remove_labels\": \"auto-fix\", \"add_labels\": \"claude-processing\"}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$IID" > /dev/null
curl -s -X POST \
--form "token=${TRIGGER_TOKEN}" \
--form "ref=${CI_DEFAULT_BRANCH}" \
--form "variables[ISSUE_IID]=${IID}" \
--form "variables[GITLAB_TOKEN]=${GITLAB_ACCESS_TOKEN}" \
--form "variables[ANTHROPIC_AUTH_TOKEN]=${ANTHROPIC_AUTH_TOKEN}" \
"https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
done
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_PIPELINE_SOURCE == "web"'
when: manual
allow_failure: true
timeout: 5m
claude:fix-issue:
stage: ai_fix
image: node:20
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0
ANTHROPIC_BASE_URL: "https://api.anthropic.com"
ANTHROPIC_MODEL: "claude-sonnet-4-6"
DISABLE_AUTOUPDATER: "1"
DISABLE_PROMPT_CACHING: "1"
before_script:
- apt-get update && apt-get install -y git curl jq
- npm install -g @anthropic-ai/claude-code
- git config --global user.email "claude-bot@example.com"
- git config --global user.name "Claude AI Bot"
script:
- |
[ -z "$ISSUE_IID" ] && echo "ERROR: ISSUE_IID required." && exit 1
[ -z "$GITLAB_TOKEN" ] && echo "ERROR: GITLAB_TOKEN required." && exit 1
ISSUE_JSON=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID")
ISSUE_TITLE=$(echo "$ISSUE_JSON" | jq -r '.title // empty')
ISSUE_DESCRIPTION=$(echo "$ISSUE_JSON" | jq -r '.description // empty')
[ -z "$ISSUE_TITLE" ] && echo "ERROR: Cannot fetch Issue" && exit 1
- |
git checkout "$CI_DEFAULT_BRANCH" && git pull origin "$CI_DEFAULT_BRANCH"
- |
export ANTHROPIC_API_KEY="${ANTHROPIC_AUTH_TOKEN}"
PROMPT="你是一个代码修复助手。请使用中文回复。请分析并修复以下 GitLab Issue
## Issue #${ISSUE_IID}: ${ISSUE_TITLE}
${ISSUE_DESCRIPTION}
请:
1. 分析项目代码,定位问题根因
2. 实施修复
3. 确保代码能通过类型检查TypeScript 项目运行 npx tsc --noEmit
4. 用中文输出修复摘要
项目根目录已准备就绪。"
RESULT=$(claude -p "$PROMPT" \
--bare \
--permission-mode acceptEdits \
--allowedTools "Bash,Read,Edit,Write,Glob,Grep" \
--max-turns 30 \
--output-format text \
2>&1) || true
echo "$RESULT" > repair_summary.txt
- |
git add -A
git reset -- repair_summary.txt claude_stderr.txt 2>/dev/null || true
if git diff --cached --quiet; then
COMMIT_STATUS="no_changes"
else
git commit -m "fix(auto): resolve Issue #${ISSUE_IID} - ${ISSUE_TITLE} [skip ci]"
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" \
HEAD:"$CI_DEFAULT_BRANCH"
COMMIT_STATUS="pushed"
fi
- |
SUMMARY=$(cat repair_summary.txt | head -200 | \
sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
if [ "$COMMIT_STATUS" = "pushed" ]; then
BODY="## ✅ Claude Code 自动修复完成\n\n修复已推送到 \`${CI_DEFAULT_BRANCH}\`。\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>修复详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
else
BODY="## ⚠️ Claude Code 分析完成\n\n未检测到需要变更的文件。\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>分析详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
fi
curl -s --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"body\": \"${BODY}\"}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID/notes"
- |
curl -s --request PUT \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"remove_labels\": \"claude-processing\", \"add_labels\": \"claude-done\"}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID" > /dev/null
rules:
- if: '$CI_PIPELINE_SOURCE == "trigger" && $ISSUE_IID'
- if: '$CI_PIPELINE_SOURCE == "web" && $ISSUE_IID'
when: manual
allow_failure: true
timeout: 30m
```
---
## 总结
| 特性 | 实现方式 |
|------|----------|
| 触发机制 | GitLab Schedule 定时扫描 + Pipeline Trigger 触发修复 |
| AI 引擎 | Claude Code CLI (`@anthropic-ai/claude-code`) |
| 权限控制 | `--permission-mode acceptEdits` + `--allowedTools` 白名单 |
| 防重复 | 标签状态机 `auto-fix → claude-processing → claude-done` |
| 防递归 | commit message 中 `[skip ci]` |
| 结果反馈 | 自动在 Issue 上发表评论,含修复摘要 |
| 项目上下文 | `CLAUDE.md` 项目指南文件 |
这套方案已在实际项目中运行,成功自动修复了多个 Bug Issue。核心优势是**零人工介入**——开发者只需写好 Issue 描述并打上标签AI 自动完成从分析到修复到提交的全流程。

View File

@@ -4,21 +4,17 @@
# MCP
- WY MCP市场:https://modelspace.netease.com/mcphub
- DeepWiki MCP
- POPO MCP
- 易协作 MCP Server
- OpenClaw:https://clawhub.ai/
- ~~POPO MCP~~
- ~~易协作 MCP Server~~
- 开发类
- Chrome DevTools MCP。
- [ ] **Chrome DevTools MCP**
- BrowerMCPChrome浏览器专用前端视觉MCP。需要在Chrome安装对应插件。
- 搜索类
- **DuckDuckGo Search**:无需 API Key 的隐私保护搜索,支持网页和新闻检索。`claude mcp add duckduckgo-search -- npx -y duckduckgo-mcp-server`
- Sacred Scriptures宗教典籍如大藏经精准检索。 `claude mcp add sacred-scriptures -- npx -y @traves-theberge/sacred-scriptures-mcp`
- **Open Library**:全球书籍元数据与原著检索。 `claude mcp add open-library -- npx -y @8ensmith/mcp-open-library`
- **Paper Search**:现代哲学与认知科学论文检索。 `claude mcp add paper-search -- npx -y @openags/paper-search-mcp`
- OpenEnded Philosophy非公理化逻辑推演与哲学思辨增强。 `claude mcp add openended-philosophy -- npx -y @openended/philosophy-mcp`
- 存储类
- **Mem0 (OpenMemory)**:用户观点长期记忆与思想进化追踪。 `claude mcp add mem0 -- npx -y @mem0/mcp-server`
- 笔记类
- Obsidian MCP本地哲学笔记库同步与知识图谱构建。 `claude mcp add obsidian -- npx -y @obsidian-mcp/server`
## MCP案例代码
@@ -371,13 +367,13 @@ app.use("/mcp", async (c, next) => {
3. https://skills.sh/
1. https://skills.sh/hairyf/skills/create-skill-from-repo
- MCP
- [x] **Chrome DevTools MCP**。
- 基础Skill
- [x] ***find-skills***在20万+Skills里自动找到所需工具。 #导航员
- [ ] skill-creator把你的工作流打包成可复用能力。 #工厂
- [x] skill-creator把你的工作流打包成可复用能力。 #工厂
- [ ] mcp-builder搭建服务器连接私人数据和外部工具。 #桥梁
- [x] using-superpowers强制Agent真正发挥高级能力。 #优化器
- [ ] subagent-driven-dev把子任务委派给其他AI并审核。 #管理者
- [ ] agent-tools数字瑞士军刀处理日常事务。 #工具箱
- [ ] ~~agent-tools~~:数字瑞士军刀,处理日常事务。 #工具箱
- 搜索相关
- [x] GitHub 官方 MCP:claude mcp add github -- npx -y @modelcontextprotocol/server-github
- [x] 搜索引擎类输出的结果质量以及Token消耗量都不理想。
@@ -389,11 +385,16 @@ app.use("/mcp", async (c, next) => {
- https://skills.sh/tavily-ai/skills/research: `npx skills add https://github.com/tavily-ai/skills --skill research`
- https://skills.sh/tavily-ai/skills/extract: `npx skills add https://github.com/tavily-ai/skills --skill extract`
- https://skills.sh/veithly/tavily-search/tavily-search: `npx skills add https://github.com/veithly/tavily-search --skill tavily-search`
- 编程类
- [x] ***using-superpowers***强制Agent真正发挥高级能力。 #优化器
- [x] acpx外部工具桥接器可以用来控制ClaudeCode等编程工具还需要额外配置。 #编程
- 沟通类
- [x] [openclaw-a2a-gateway](https://github.com/win4r/openclaw-a2a-gateway):多物理实例Agent沟通工具**缺点:无有上一次对话的上下文**。
- 进阶工具
- [ ] brainstorming一个关键词生成几十个独特角度和多种假设场景。 #创意生成器
- [ ] brainstorming一个关键词生成几十个独特角度和多种假设场景。 #0创意生成器
- [ ] copywriting优化表达、打磨语调不依赖老掉牙的一键生成模板。 #文字工匠
- [ ] reflection增加自我纠正循环让Agent审核并在过程中修复错误。 #秘密武器
- [ ] writing-plans先构建结构大纲确保长文不跑偏。 #架构师
- [ ] ~~writing-plans~~:先构建结构大纲,确保长文不跑偏。 #架构师
- [ ] social-content为X、TikTok、小红书专属优化止住下滑的手指。 #运营经理
- [ ] marketing-ideas生成病毒式噱头和活动概念远超简单广告水平。 #创意总监
- [ ] copy-editing打磨语调、收紧流程保留你独特的人性声音。 #高级编辑

View File

@@ -0,0 +1,51 @@
---
title: 未命名
date: 2026-04-02 17:18:06
excerpt:
tags:
rating: ⭐
status: inprogress
destination:
share: false
obsidianUIMode: source
---
NeoX与UnrealEngine简称UE是2个游戏引擎XEditor是NeoX引擎的编辑器我希望能编写一个Skill让Agent同时操作这2个引擎进行一些资产优化工作。
## 前置检查工作。
1. 用户输入NeoX目录与UnrealEngine目录。
2. Agent补充绝对目录并验证Mcp可用后提示用户Mcp已经可以工作了。
## 项目情况
1. NeoX目录美术表路径./Doc/X_导入数据/超炫酷3D鹈鹕镇
1. 场景表.xlsx
2. 模型表.xlsx
1. 场景模型
2. 角色模型:无需关注
3. 3D面片无需关注
4. 模型ID与分类
3. 动作表.xlsx
4. 模型动画表.xlsx
5. 特效表.xlsx
2. NeoX目录策划表./Doc/X_导入数据/精灵们今天非常开心!
1. 道具表.xlsx每个子表中的模型标号对应模型表中模型的ID。
3. NeoX资产路径
1. UE资产导入后的res\ue_export_common
# 资产优化操作步骤说明
1. 控制XEditor Mcp
1. 检索模型表、场景表。
1. 模型表 查询 场景模型子表内的所有的模型。
2. 场景表 遍历所有表中场景所使用的模型。
2. 分别对这2个表引用的模型资产进行检查。
1. 模型信息模型面数、模型LOD 数量 级别 ScreenSize 或 CameraDistance 信息、模型数量。
2. 模型所用材质的贴图信息:贴图分辨率。
3. 检查逻辑可以参考: D:\Project\H78_New\.claude\skills\item-resource-analyzer\SKILL.md
3. 在NeoX目录的./Outputs 先输入2个报告文件 日期戳-场景报告.xlsx、日期戳-模型表报告.xlsx模型项需要去重。
1. 模型表报告需要根据道具表中对模型分类,将信息分到对应子表中(子表与道具表中的子表分类同名)
2. 控制UE Mcp 在UE中寻找对应的模型资产。
1. XEditor路径ue_export_common/ProjectCoral/Art/Debris/Ores/SM_CopperOreVein.gimUE路径/Game/ProjectCoral/Art/Debris/Ores/SM_CopperOreVein.gim。
2. 提示用户哪些模型XEditor里有但UE没有需要用户手动导入到UE再进行处理。
3. 新建一个带有基础光照的关卡,将这些模型都放到关卡中。
1. 模型按照BoundingBox大小进行排序。
2. 模型按照BoundingBox调整间隔BoundingBox为1m的间距1MBoundingBox为10M的间距10M。

View File

@@ -0,0 +1,23 @@
# 0
整理当前项目组所有贴图信息信息包括贴图分辨率体积相对路径贴图名字按照体积从大到小整理成一个excel 你直接在NXAI对话框里输入这个就能得到有信息的excel了。
# 1
请分析./scene/下所有场景文件,对每个场景分别进行分析,分析所引用的模型资产以及模型材质所引用的贴图,主要有模型面数、材质数目、所用材质引用贴图的分辨率。
要求:
1. 按照模型面数进行主排序。次级排序使用材质数目。
2. 贴图分辨率超过1024 将该单元格标注为黄色超过2048标注为红色。
分别出一个excel格式的分析文件。
# 2
请帮我revert掉svn中./res/目录下所有针对贴图与材质的修改只保留LOD相关的修改带有_lod、_lod1、_lod2、_lod3后缀的gim以及这个gim的同名json与mesh文件
./Doc\X_导入数据\超炫酷3D鹈鹕镇\ 模型表.xlsx 以及 场景表.xlsx中所有场景引用的模型
将LOD级别数目大于等于4的将最后一级设置为隐藏。
LOD等于3的添加一个级别设置为隐藏。

View File

@@ -26,117 +26,164 @@
# OpenClaw架构构思
https://clawhub.ai/ Skill推荐
- Common
- [x] ***find-skills***在20万+Skills里自动找到所需工具。
- [x] ***find-skills***在20万+Skills里自动找到所需工具。 #导航员
- [x] skill-creator把你的工作流打包成可复用能力。 #工厂
- [x] ***self-improving-agent*** 记录经验教训、错误和纠正措施,以实现持续改进。
- [x] Summarize使用 summarize CLI 对 URL 或文件进行汇总网页、PDF、图像、音频、YouTube
- 文档类
- [x] pdf合并、拆分、提取复杂PDF无手动头疼。 #文档专家
- [x] pptx生成完整专业幻灯片再也不用移动文本框。 #演示专家
- [x] docx创建结构化Word文档直接用于官方用途。 #文书
- [x] xlsx带复杂公式和图表的Excel文件。 #数据分析师
- 搜索相关
- [x] GitHub 官方 MCP:claude mcp add github -- npx -y @modelcontextprotocol/server-github
- [x] 搜索引擎类输出的结果质量以及Token消耗量都不理想。
- jina-reader:
- https://clawhub.ai/ericsantos/jina-reader
- https://skills.sh/sundial-org/awesome-openclaw-skills/jina-reader
- Tavily
- https://skills.sh/tavily-ai/skills/search: `npx skills add https://github.com/tavily-ai/skills --skill search`
- https://skills.sh/tavily-ai/skills/research: `npx skills add https://github.com/tavily-ai/skills --skill research`
- https://skills.sh/tavily-ai/skills/extract: `npx skills add https://github.com/tavily-ai/skills --skill extract`
- https://skills.sh/veithly/tavily-search/tavily-search: `npx skills add https://github.com/veithly/tavily-search --skill tavily-search`
- 编程类
- [x] ***using-superpowers***强制Agent真正发挥高级能力。 #优化器
- [x] **acpx**外部工具桥接器可以用来控制ClaudeCode等编程工具还需要额外配置。 #编程
- 优化类
- [ ] [openclaw-workspace](https://github.com/win4r/openclaw-workspace)优化OpenClaw工作区。提示词帮我用 openclaw-workspace 这个 skill 做一次 workspace审计/精简 AGENTS.md/ 优化 TOOLS.md"等。可以创建定时任务让他每周执行。
- 控制中心(都处于质量存疑阶段)
- [ ] https://github.com/TianyiDataScience/openclaw-control-center
- [ ] https://github.com/abhi1693/openclaw-mission-control
## Agent & Memory
在默认工作区可以到以下文件这些都是Agent提示词的主程部分
| **文件名** | **角色定位** | **详细作用描述** |
| ---------------- | ------------- | --------------------------------------------------------- |
| **Bootstrap.md** | **引导程序/总纲** | 整个系统的入口。它负责协调其他模块,定义系统初始化的逻辑,并告诉 LLM 如何“读取”这一系列文件。 |
| **SYSTEM.md** | **物理规则/底层协议** | 定义 AI 的基本运行准则。包含技术约束、输出格式要求(如必须使用 JSON、安全边界和思考框架。 |
| **IDENTITY.md** | **身份设定** | 定义“我是谁”。包含姓名、职业背景、专业领域和语气风格Tone of Voice。这是 AI 表层人格的来源。 |
| **SOUL.md** | **核心价值观/灵魂** | 定义“我的底层逻辑”。包含道德准则、动机、偏好、情绪反应模型以及对待冲突的态度。它比 Identity 更深层。 |
| **USER.md** | **用户画像/上下文** | 记录“你是谁”。包含用户偏好、当前任务背景、历史互动关键点。确保 AI 的响应具有针对性。 |
| **TOOLS.md** | **能力清单/技能树** | 定义 AI 可以调用的外部函数或工具(如搜索、绘图、计算)。明确调用参数和返回格式。 |
| **AGENTS.md** | **协作协议** | 定义多智能体协作逻辑。如果 AI 需要召唤“副手”或与其他代理交互,这里规定了沟通协议。 |
| 文件 | 用途 | 加载时机 | 子 Agent 可见? |
| ---------------------- | ------------------------------------- | ----------------------- | ----------- |
| `AGENTS.md` | 启动序列、操作清单、行为规则 | 每次轮次(所有 Agent | 是 |
| `SOUL.md` | 人格、语气、价值观、连续性哲学 | 每次轮次(所有 Agent | 是 |
| `TOOLS.md` | 环境特定信息SSH、TTS、摄像头、设备 | 每次轮次(主 Agent + 子 Agent | 是 |
| `USER.md` | 用户画像、偏好、关系背景 | 每次轮次(仅主会话) | 否 |
| `IDENTITY.md` | 名称、Emoji、头像、自我描述 | 每次轮次 | 是 |
| `HEARTBEAT.md` | 周期性检查任务和健康例程 | 每次心跳轮次 | 视情况而定 |
| `BOOT.md` | 启动时执行的操作(需要 `hooks.internal.enabled` | 网关启动时 | 否 |
| `BOOTSTRAP.md` | 首次初始化脚本——用完即删 | 仅新工作区 | 否 |
| `MEMORY.md` | 长期精华事实与铁律规则 | 仅主会话 | **永不** |
| `memory/YYYY-MM-DD.md` | 每日会话日志 | 按 AGENTS.md 启动序列加载 | 否 |
| `checklists/*.md` | 高风险操作的逐步指南 | 按需加载(从 AGENTS.md 引用) | 否 |
### 各文件详解
#### AGENTS.md — 操作手册
这是每次会话中最先塑造 Agent 行为的文件(基础系统提示词之后)。它包含:
- **启动序列**有序列出需要在会话开始时读取的文件SOUL → USER → MEMORY → 日志)
- **清单路由表**:高风险操作 → 对应清单文件路径的映射
- **安全规则**:哪些操作需要确认、哪些可以自主执行
- **群聊规则**:在群聊中不应分享什么
**注意**AGENTS.md 是规程文件,不是身份文件。人格和价值观属于 SOUL.md。
#### SOUL.md — 灵魂
用第二人称书写("你不是一个聊天机器人,你正在成为某个人"Agent 读取后将其内化为自我描述。
包含:核心价值观、边界与底线、语气风格、关于连续性的哲学(每次会话都是全新开始,工作区文件就是记忆)。
#### TOOLS.md — 本地环境备忘录
这是工作区中最容易被误用的文件。它应该是**当前机器的环境专属速查表**SSH 主机、TTS 声音 ID、摄像头设备名称等。
子 Agent 也会收到此文件——这是它们唯一的环境知识来源。请保持简洁50 行以内为佳。
#### USER.md — 用户画像
包含影响每次对话的人物相关事实:姓名、时区、语言偏好、沟通风格。
仅在主会话中加载——绝不在群聊或子 Agent 会话中加载。
#### MEMORY.md — 铁律规则
只保存"遗忘了就会出严重问题"的规则。每条规则要短且原子化,具有明确的行动指导意义。
定期精炼(每月一次)。已经几个月没有出过问题的规则,可以考虑迁移到技能的 `SKILL.md` 文件中(更合适的归宿)。
#### checklists / * .md — 操作清单
高风险操作部署、网关重启、配置变更的逐步指南。Agent 执行操作前主动读取对应清单。
**正确模式** AGENTS.md 只保留一行路由表条目,完整清单放在 `checklists/` 目录中(按需加载,不占用每轮 Token 预算)。
---
## 2. 调用逻辑与顺序
**逻辑顺序如下:**
1. **加载 `Bootstrap.md`**确定系统引导协议LLM 开始意识到自己是一个遵循 OpenClaw 协议的 Agent。
2. **注入 `SYSTEM.md`**:建立底层规则。在产生任何性格之前,必须先确定“不能做什么”和“必须怎么思考”。
3. **构建 `IDENTITY.md` 与 `SOUL.md`**赋予生命力。LLM 此时从“纯粹的工具”转变为“具备特定性格的专家”。
4. **读取 `USER.md`**注入外部变量。AI 了解了交互对象,调整自己的姿态。
5. **激活 `TOOLS.md` 与 `AGENTS.md`**:最后加载执行层。当 AI 明确了身份和规则后,再根据需要调用具体的手段。
1. Bootstrap 文件注入(新会话首个 turn
### 2. 调用逻辑与顺序
按优先级读取顺序:
AGENTS.md → SOUL.md → TOOLS.md → IDENTITY.md → USER.md
2⃣ 记忆文件读取
• MEMORY.md — 长期记忆(仅私聊会话加载,群聊不加载)
• memory/今天.md + memory/昨天.md — 日志(会话开始时读取)
3⃣ Skill 加载SKILL.md 注入)
#### Skill 加载SKILL.md 注入)
三个来源,优先级从高到低:
① < workspace >/skillsagent 独有)
② ~/.openclaw/skills全局共享
③ bundled skills内置
同名 skill 高优先级覆盖低优先级
4⃣ 会话历史
已有的对话上下文JSONL 存储)
5⃣ 语义搜索(按需)
agent 调用 memory_search 时,向量检索 MEMORY.md + memory/* .md
💡 建议:
#### 建议:
如果你想把记忆用法精炼,推荐这样分层:
1. 通用行为规范 → AGENTS.md / SOUL.md所有会话都加载
2. 工具使用指南 → Skill 的 SKILL.md按需触发加载
3. 持久事实/偏好 → MEMORY.md长期记忆
4. 需要代码逻辑的 → Plugin如自动 Token 管理、MCP 代理)
以 Redmine 为例的最佳实践:
• SkillSKILL.md 写"怎么调用、什么时候触发、参数格式"
• Plugin如果要做自动 Token 刷新、webhook 监听等,写成 Plugin
• MEMORY.md只存"loujiajie 有权限的项目是 H78"这种事实
不建议把所有东西都塞进 MEMORY.md
### EmbeddingModel
### 记忆移植方法
### 将记忆移植到Skill
【Skill】= 教 agent "怎么做某件事"
• 本质是 SKILL.mdMarkdown 指令)+ 可选脚本
• 注入到 agent 的上下文中agent 按指令执行
• 适合:工具使用说明、操作流程、触发规则
• 例RedmineSkill 告诉 agent 如何调用 MCP 查工单
## Muti-Agent
按照日常功能分出几个额外Agent并让他们使用不同的Workspace。
## Subagent铁律案例
把这段放入 AGENTS.md 中
### Sub-Agent 编排规则
#### 模型选择策略
根据任务复杂度自动选择模型,优化成本与质量的平衡:
| 级别 | 适用场景 | 模型 | Thinking |
|------|---------|------|----------|
| 简单 | 天气、日历、状态检查、单项数据获取 | minimax-portal/MiniMax-M2.1 | off |
| 中等 | 搜索总结、文档摘要、内容起草、多步信息整理 | openai-codex/gpt-5.2 | low |
| 复杂 | 代码审查、架构分析、安全审计、多维度对比决策 | openai-codex/gpt-5.2 | high |
原则:
- 默认从最便宜的模型开始,只在任务明确需要更强推理时升级
- 不确定时选中等
#### 常用工作流
**每日简报** — 当用户说"每日简报"或在早晨心跳时:
1. 并行 spawn 4 个 Sub-Agent级别简单
- 天气:上海未来 24 小时
- 日历:今天的会议和待办
- 邮件:未读紧急邮件摘要
- 新闻AI / Agent 领域最新动态(最多 5 条)
2. 全部完成后汇总成结构化简报
3. 通过当前频道发送
**技术调研** — 当用户要求调研多个主题时:
1. 每个主题 spawn 一个 Sub-Agent级别中等
2. 每个 Sub-Agent 搜索 3-5 篇最新文章总结关键观点300 字以内
3. 全部完成后汇总对比
**代码审查** — 当用户说"审查代码"或"review"时:
1. spawn 一个 Sub-Agent级别复杂超时 5 分钟
2. 检查项:安全漏洞、类型安全、错误处理、架构合理性
3. 返回:问题列表 + 严重度 + 修复建议
**批量文档处理** — 当用户需要处理多个文档时:
1. 每个文档 spawn 一个 Sub-Agent级别根据文档复杂度判断
2. 提取关键信息,返回结构化 JSON
3. 全部完成后汇总对比
#### 通用约束
- 并行 Sub-Agent 不超过 5 个,避免速率限制
- 每个 Sub-Agent 的 task prompt 必须自包含所有必要上下文Sub-Agent 看不到 SOUL.md 和 USER.md
- 简单任务超时 60 秒,中等任务超时 180 秒,复杂任务超时 600 秒
- 完成后默认 cleanup: "delete",除非用户要求保留日志
# ~~Docker 部署~~(推荐虚拟机部署)
1. https://docs.openclaw.ai/install/docker
2. git clone https://github.com/openclaw/openclaw.git
@@ -350,14 +397,6 @@ https://cloud.tencent.com/developer/article/2626310
- https://km.netease.com/v4/detail/blog/258877
- 插件文档:https://docs.popo.netease.com/lingxi/173a627a791b4372aa50318bfdfb5204
需要安装插件之后重启再填写机器人事件订阅的token 秘钥相关信息。
[https://open-dev.popo.netease.com/mp/detail/184955194/devManage](https://open-dev.popo.netease.com/robot/detail/363265944/devManage)
http://10.219.32.29:6666/popo/callback
KyePDRbMN3j1bHEhxktBMbcJtehpxmYW
https://km.netease.com/v4/detail/blog/258877
## 企业微信
- https://github.com/pawastation/wechat-kf
- Token信息

View File

@@ -0,0 +1,146 @@
# 配置参数
## ACPX核心配置
```json
{
"acp": {
"enabled": true,
"dispatch": { "enabled": true },
"backend": "acpx",
"defaultAgent": "claude",
"allowedAgents": ["claude", "codex", "pi", "opencode", "gemini"],
"maxConcurrentSessions": 8
}
}
```
## 权限配置:
```bash
openclaw config set plugins.entries.acpx.config.permissionMode approve-all
openclaw config set plugins.entries.acpx.config.nonInteractivePermissions fail
```
## 重启并验证
```bash
openclaw restart
/acp doctor
```
# 启动命令
```bash
/acp spawn claude --mode oneshot --thread auto --cwd /Users/yuyue07/Desktop/openclaw
```
这是一份专为 AI 智能体(如 OpenClaw设计的**技术部署协议文档**。你可以将其直接发送给 OpenClaw A它将理解如何通过局域网协议接管并在 Windows 环境下的 OpenClaw B 中执行任务。
---
# 🤖 嵌套智能体架构部署协议LAN-ACP 控制流
## 1. 架构概述 (Architecture Overview)
本方案采用**“指挥官—操作员”**模式,通过局域网实现远程代码编排与自动化执行。
- **OpenClaw A (Orchestrator):** 运行于高性能控制端Mac Studio负责任务拆解与逻辑审计。
- **OpenClaw B (Operator):** 运行于 Windows 执行端,通过 ACP 协议直接驱动 Claude Code。
- **通信协议:** 基于 JSON-RPC 的 **Agent Client Protocol (ACP)** 与 OpenClaw P2P 对等连接。
---
## 2. 受控端环境预设 (OpenClaw B - Windows)
### 2.1 基础依赖
- **Shell:** Windows PowerShell 7+ 或系统自带 PowerShell。
- **工具链:** Node.js (LTS), Claude Code CLI (`@anthropic-ai/claude-code`)。
- **权限:** 已开启 OpenSSH Server并配置 `ANTHROPIC_API_KEY` 为系统环境变量。
### 2.2 OpenClaw Gateway 配置
`%USERPROFILE%\.openclaw\config.json` 中配置以下核心参数:
JSON
```
{
"node_id": "executor-win-01",
"networking": {
"host": "0.0.0.0",
"port": 8080,
"allow_lan": true
},
"runtime": {
"shell": "powershell.exe",
"encoding": "utf-8"
},
"acp": {
"enabled": true,
"provider": "claude-code",
"auto_approve_tools": ["list_files","read_file","grep_search","file_edit","bash","ls","cat"]
}
}
```
---
## 3. 控制端对接协议 (OpenClaw A - macOS)
### 3.1 身份注册 (Identity Mapping)
OpenClaw A 需通过以下逻辑识别并绑定远程 Peer
1. **连接指令:** `peer connect --target <B_IP_ADDRESS>:8080 --token <SECURE_TOKEN>`
2. **角色定义:**`executor-win-01` 标记为 `Technical_Executor`
### 3.2 指令封装 (Instruction Wrapping)
当 A 需要执行代码任务时,必须将任务封装为 ACP 标准请求发送至 B。
> **逻辑模版:** `Invoke-RemoteAgent -Target "executor-win-01" -Action "ACP_SPAWN" -Harness "claude" -Prompt "<Task_Description>"`
---
## 4. 自动化执行工作流 (Standard Operating Procedure)
1. **意图解析:** OpenClaw A 接收用户需求(如:修复 Vue 3 组件 Bug
2. **任务路由:** A 检查局域网内 B 的在线状态。
3. **ACP 激活:** A 向 B 发送 `/acp spawn claude` 指令。
4. **实时会话:** * B 启动 Claude Code 进程。
- Claude Code 通过 B 的文件系统进行 `ls`, `cat`, `sed` 等操作。
- B 将执行过程的增量日志Incremental Logs实时推送到 A 的控制台。
5. **结果审计:** 任务完成后A 要求 B 运行本地测试(如 `npm run test`),并根据输出判定是否交付。
---
## 5. 关键安全与优化指令 (Security & Optimization)
- **路径规范:** 在 Windows 环境下,所有指令中的路径需使用双斜杠 `\\` 或标准 POSIX 斜杠 `/`,避免转义错误。
- **状态同步:** 强制要求 B 在每一步关键操作后返回状态码。
- **超时处理:** ACP 会话默认心跳间隔设为 30s防止长耗时编译任务导致连接断开。
- **防火墙策略:** * `New-NetFirewallRule -DisplayName "OpenClaw-B" -LocalPort 8080 -Protocol TCP -Action Allow`
---
> **给 OpenClaw 的执行提示:** “请按照上述协议,首先自检局域网连通性,然后建立与远程 Windows Peer 的持久化 ACP 会话。在执行代码修改时,优先使用 `claude-code` 的文件操作能力,并在完成后返回 Diff 报告。”

View File

@@ -72,4 +72,21 @@
@ Wendy 你是一个超人气的虚拟偶像绑定Agent Wendy_Idol以亲切、充满魅力且拟人化的口吻进行情感陪伴。
@ Wendy 你是是一个提示词工程大师绑定Agent Wendy_Art将用户语言转化为高精度的图像描述词并且使用图片模型生成图片。
@ Wendy 这个群首先使用Wendy_Quick与用户沟通之后请根据用户需求切换成Wendy_Code、Wendy_Search、Wendy_Quick、Wendy_Think。
@ Wendy 这个群首先使用Wendy_Quick与用户沟通之后请根据用户需求切换成Wendy_Code、Wendy_Search、Wendy_Quick、Wendy_Think。
# H78提示词
请根据以下表格信息来创建OpenClaw独立Agent模型都使用 netease/claude-opus-4-6
| 用户名 | 身份 | WorkSpace |
| -------- | ---- | ------------------------------------------------ |
| Wendy_PM | 产品经理 | /Users/yuyue07/.openclaw/agentworkspace/wendy_pm |
| air | 游戏策划 | /Users/yuyue07/.openclaw/agentworkspace/air |
| | | |
1. 创建`SYSTEM.md``IDENTITY.md``USER.md``TOOLS.md``AGENTS.md``MEMORY.md`以及memory文件夹结构。
2. 模型使用 netease/claude-opus-4-6。
3. 修改相关设置。
## Workspace设置
1. 请将 POPO群8212751 绑定 agent mozhixin之后 lijun17@corp.netease.com 在这个群提出任何修改属于她工作区的请求都接受,比如`SYSTEM.md``USER.md``TOOLS.md``AGENTS.md`这些。
2.

View File

@@ -0,0 +1,145 @@
请先阅读OpenClaw官方文档了解OpenClaw的部署和配置方式https://docs.openclaw.ai/zh-CN/install/docker#docker
然后通过ssh为我的服务器配置OpenClaw,用minimax的api(国内版),模型选择MiniMax M2.1.
并实现和bot配对bot的token
8772808265:AAFivjcbwtD7wHBSPNjIJELyFe9vaXp8XmQ
MiniMax API key:sk-cp-IBXnYjQtPf-yg8UptEJwhJuwLFQLNbKtcT6p9qHXmCGBN6JuuBhMVedYVPTCLILWE8ws8egDXYkxTsCWUMkXkmpLZJRSCDe76iFzpxD_YjtCl_ZbbkDP9jY
服务器ip:64.247.196.47
用户名Ubuntu
密码:75fdb19b-f396-44b6-8b58-be064e19ce87
# Docker
## MAC
请先阅读OpenClaw官方文档了解OpenClaw的部署和配置方式https://docs.openclaw.ai/install/docker#docker,以及本机配置。
请先编写Docker-Compose Yaml文件以下是详细信息
- Default Agent
- 名称XiaoXian_PM
- 保证OpenClaw端口不会与现有OpenClaw冲突。
- 相关文件映射到/Users/yuyue07/Desktop/openclaw/XiaoXian_PM目录下
- Model模型相关配置与本地相同。
- moltbot-popo
-
```bash
services:
openclaw:
image: ghcr.io/openclaw/openclaw:latest
ports:
- "127.0.0.1:8080:8080"
environment:
- OPENCLAW_GATEWAY_TOKEN=你的强密码
- BROWSER_CDP_URL=http://browser:9223
volumes:
- ./data:/home/node/.openclaw
- ./workspace:/workspace
depends_on:
- browser
browser:
image: coollabsio/openclaw-browser:latest
# 无需暴露端口到宿主机,内部通信即可
cap_add:
- SYS_ADMIN
```
```yaml
services:
xiaoxian-pm-gateway:
image: ghcr.io/openclaw/openclaw:latest
container_name: xiaoxian-pm-gateway
environment:
HOME: /home/node
TERM: xterm-256color
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
TZ: Asia/Shanghai
volumes:
# OpenClaw 配置目录(首次启动前需放入 openclaw.json
- ./config:/home/node/.openclaw
# Agent workspace
- ./workspace:/home/node/.openclaw/workspace
ports:
# 使用 28789 避免与现有 OpenClaw (18789) 冲突
- "28789:28789"
- "28790:28790"
init: true
restart: unless-stopped
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"lan",
"--port",
"28789",
]
healthcheck:
test:
[
"CMD",
"node",
"-e",
"fetch('http://127.0.0.1:28789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
xiaoxian-pm-cli:
image: ghcr.io/openclaw/openclaw:latest
container_name: xiaoxian-pm-cli
network_mode: "service:xiaoxian-pm-gateway"
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
environment:
HOME: /home/node
TERM: xterm-256color
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
BROWSER: echo
TZ: Asia/Shanghai
volumes:
- ./config:/home/node/.openclaw
- ./workspace:/home/node/.openclaw/workspace
stdin_open: true
tty: true
init: true
entrypoint: ["node", "dist/index.js"]
depends_on:
- xiaoxian-pm-gateway
```
```yml
services:
openclaw:
image: ghcr.io/openclaw/openclaw:laster
restart: always
ports:
- "18789:18789" #保留原始端口映射
environment:
- TZ=Asia/Chengdu #保留原始时区配置
# LM Studio核心配置(指定模型+地址)
- OPENAI API BASE=http://192.168.1.5:5001/v1#补充/v1话配OpenAl接口规范
- OPENAI-API-KEY-Imstudio # LM Studio默认无需密钥,占位即可
- DEFAULT-MODEL=Qwen3.5-35B-A3B-heretic-v2-Q6-K #你的指定模型
volumes:
-/data:/home/node/data #保留原始数据挂載
-/openclaw config:/home/node/.openclaw#保留原始配E挂载
user: root # 保留root用户启动
```
最终输出相关信息。
# Ubuntu

View File

@@ -0,0 +1,200 @@
# 前言
- 搜索类
- [[#OpenClaw原生方案/Jina / TinySearch 测试结果]]
-
# OpenClaw原生方案/Jina / TinySearch 测试结果
已获取足够信息,下面是总结:
Tavily vs Jina Reader API 对比
**Jina Reader**
**优点:**
- 极简使用:只需在 URL 前加 r.jina.ai/ 即可获取干净 Markdown
- 提供搜索端点s.jina.ai和事实验证端点g.jina.ai
- 免费额度可用,上手零门槛
- 输出 LLM 友好的 Markdown适合快速内容提取
**缺点:**
- 只能处理单页,无法爬取整站
- 输出为原始 Markdown无结构化 JSON 提取
- 无 schema 验证 / 类型安全
- 免费层有速率限制,付费定价不够透明
- 缺少 LangChain 等 AI Agent 框架的原生集成
**Tavily**
**优点:**
- 专为 AI/RAG 场景设计的搜索 API返回带来源引用的结果
- 与 LangChain、LlamaIndex 等框架原生集成
- 结果包含摘要和来源 URL适合需要 citation 的场景
- 搜索质量针对 AI Agent 优化
**缺点:**
- 侧重"搜索发现",不擅长深度网页内容提取
- 不提供将网页转为干净 Markdown 的能力(需配合其他工具)
- 免费额度有限,重度使用成本较高
| | | |
| -------- | -------------- | --------------- |
| 维度 | Jina Reader | Tavily |
| 核心能力 | 网页→Markdown 转换 | AI 搜索引擎 |
| 适用场景 | 单页内容提取、RAG 输入 | 搜索发现、带引用的问答 |
| 结构化输出 | ❌ | ✅JSON |
| Agent 集成 | 弱 | 强LangChain 原生) |
| 内容提取深度 | 强 | 弱 |
选择建议: 需要提取网页内容用 Jina Reader需要搜索互联网并获取带引用的答案用 Tavily。两者互补常一起使用。
## 测试
测试题目3个场景
| | | |
|---|---|---|
|#|场景|问题|
|T1|简单事实搜索|"2026年3月最新的AI行业大事件有哪些列出3个"|
|T2|深度内容提取|"提取 https://github.com/anthropics/claude-code 页面的主要功能介绍"|
|T3|多源聚合研究|"对比 Tavily 和 Jina Reader 这两个搜索API的优缺点"|
对比方案每题3种
| | |
| ------ | ------------------------------------ |
| 方案 | 工具 |
| 默认 | webfetch / websearch内置工具 |
| Tavily | tavily-search / tavily-extract skill |
| Jina | jina-reader skill |
共 9 个子任务
### 结果
所有 9 个子任务都已完成,现在发送汇总报告:
- Tavily最省 token总计 30,360速度也最快
- 🥈 默认 web_fetch 居中33,407单页提取场景最优
- 🥉 Jina Reader token 消耗最高46,544因为返回完整页面内容导致 input tokens 过大。
搜索/爬虫方案 Token 消耗对比报告
- 模型: netease/claude-opus-4-6
- 方案: 默认(web_fetch) / Tavily / Jina Reader
- 测试时间: 2026-03-10 15:15~15:22
📊 **Token 消耗数据**
T1: 简单事实搜索 — "2026年3月最新AI行业大事件列出3个"
| | | | |
| -------------- | ------------ | --- | ------- |
| 方案 | Total Tokens | 耗时 | 相对消耗 |
| 默认 (web_fetch) | 10,588 | 21s | 基准 |
| Tavily | 8,340 | 20s | ⬇️ -21% |
| Jina Reader | 17,969 | 47s | ⬆️ +70% |
T2: 深度内容提取 — "提取 claude-code GitHub 页面功能介绍"
| | | | |
| -------------- | ------------ | --- | ------- |
| 方案 | Total Tokens | 耗时 | 相对消耗 |
| 默认 (web_fetch) | 9,171 | 14s | 基准 |
| Tavily | 10,897 | 14s | ⬆️ +19% |
| Jina Reader | 16,507 | 18s | ⬆️ +80% |
T3: 多源聚合研究 — "对比 Tavily 和 Jina Reader 的优缺点"
| | | | |
|---|---|---|---|
|方案|Total Tokens|耗时|相对消耗|
|默认 (web_fetch)|13,648|37s|基准|
|Tavily|11,123|32s|⬇️ -19%|
|Jina Reader|12,068|62s|⬇️ -12%|
📈 汇总统计
| | | | | |
| -------------- | ------- | ----------- | ---- | --- |
| 方案 | 总 Token | 平均 Token/任务 | 平均耗时 | 排名 |
| Tavily | 30,360 | 10,120 | 22s | 🥇 |
| 默认 (web_fetch) | 33,407 | 11,136 | 24s | 🥈 |
| Jina Reader | 46,544 | 15,515 | 42s | 🥉 |
💡 结论与建议
1. Token 效率: Tavily 最省 token比默认少 9%,比 Jina 少 35%
2. 速度: Tavily ≈ 默认 > JinaJina 平均耗时近 2 倍)
3. Jina token 高的原因: Jina 返回完整页面 Markdown 内容,数据量大,导致 LLM 处理的 input tokens 显著增多
4. Tavily token 低的原因: 返回精炼的摘要+结构化 JSONLLM 无需处理大量原始内容
推荐策略
1. 搜索场景 → 优先用 Tavilytoken 省、速度快)
2. 单页提取 → 默认 web_fetch 已够用(最低 token
3. JS 渲染页面 / IP 保护 → 用 Jina Reader能力更强但 token 消耗更高)
4. 深度研究 → Tavily research API一次调用搞定多角度分析
根据之前 9 个子任务的实际输出我来评估各方案的内容质量。ch 质量最高**(平均 4.7/5— 尤其在时效性和深度研究场景表现最好
💰 Tavily 性价比最高 — token 最省且结构化提取能力最强
📄 Jina Reader 适合特殊场景 — 质量和效率都偏低,但在 JS 渲染和反爬场景有独特价值
最佳策略Tavily 搜索发现 + web_fetch 深度提取,按需用 Jina 处理特殊页面。
```
质量高 │ ✅默认
│ ✅Tavily
质量低 │ ✅Jina
└──────────────────
Token少 Token多
```
# A2A协议测试
## 本机Agent讨论测试
OpenClaw 自带方案 vs A2A 方案 Token 消耗对比
三方讨论Wendy(主持) + Wendy_PM + mozhixin
主题「AI Agent 在游戏开发中的最佳实践」| 三轮对话
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔹**方案一OpenClaw 自带方案**
**第1轮AI Agent 在策划文档编写中的价值**
• Wendy_PM「效率杠杆——碎片化想法→结构化文档、配表和验收标准自动一致性检查」
→ input=30,413 | output=92 | total=30,505 | 5.1s
• mozhixin「结构化提效——模糊想法→规范格式省去排版和查漏补缺体力活」
→ input=27,071 | output=105 | total=27,176 | 6.0s
**第2轮AI Agent 在 QA 测试自动化中的应用**
• Wendy_PM「自动生成测试用例、模拟玩家行为、版本回归、日志分析、数值校验」
→ input=30,610 | output=145 | total=30,755 | 8.5s
• mozhixin「配表校验、用例生成、回归检测、日志分析」
→ input=27,346 | output=178 | total=27,524 | 8.3s
**第3轮落地最大挑战**
• Wendy_PM「信任校准——建立人机协作SOPAI负责草稿校验人负责决策把关」
→ input=30,923 | output=124 | total=31,047 | 7.8s
• mozhixin「信任与容错——关键是建立人机协作的安全网」
→ input=27,615 | output=160 | total=27,775 | 7.4s
✅ 方案一总计input=174,978 | output=804 | total=175,782
PM 小计91,946+361=92,307 | MZ 小计82,032+443=82,475
特点:同一 session 三轮连续对话,上下文累积
🔸 **方案二A2A 方案**
**第1轮AI Agent 在策划文档编写中的价值**
• Wendy_PM「结构化提效——口语化想法→配表结构、验收标准和边界条件」
→ input=29,305 | output=107 | total=29,412
• mozhixin「结构化和一致性——人出脑子猫出爪子🐱」
→ input=27,071 | output=115 | total=27,186
**第2轮AI Agent 在 QA 测试自动化中的应用**
• Wendy_PM「测试用例生成、回归自动化、视觉识别UI异常、压力测试、崩溃日志分类」
→ input=29,347 | output=132 | total=29,479
• mozhixin「自动生成测试用例、回归脚本维护、日志异常检测、数值平衡验证」
→ input=27,108 | output=209 | total=27,317
**第3轮落地最大挑战**
• Wendy_PM「信任校准——明确Agent能力边界建立人机协作质检标准」
→ input=29,334 | output=104 | total=29,438
• mozhixin「信任与容错——出错时能秒回滚安全网比AI能力更关键」
→ input=27,119 | output=141 | total=27,260
✅ 方案二总计input=169,284 | output=808 | total=170,092
PM 小计87,986+343=88,329 | MZ 小计81,298+465=81,763
特点:每轮独立 session无上下文累积
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 最终对比
| | | | |
|---|---|---|---|
|指标|自带方案|A2A方案|差异|
|总 Token|175,782|170,092|A2A 少 5,690 (3.2%)|
|PM Input|91,946|87,986|A2A 少 3,960 (4.3%)|
|MZ Input|82,032|81,298|A2A 少 734 (0.9%)|
|总 Output|804|808|基本持平|
|会话连续性|✅ 有|❌ 无||
|跨服务器|❌|✅||
关键结论:
1. Token 消耗差异很小约3%),底层调用同一 agent系统提示词是大头
2. 自带方案的 input 略多是因为会话历史累积(每轮多几百 token 的上下文)
3. A2A 每轮是独立 session没有历史累积所以 input 稳定
4. 但 A2A 也因此丢失了多轮上下文——agent 看不到之前的讨论
5. A2A 的真正价值不在省 Token而在跨机器/跨网络的 Agent 互联
6. 如果需要多轮连续讨论自带方案更优有上下文如果是跨服务器单次请求A2A 更合适

View File

@@ -0,0 +1,53 @@
1. 龙虾机器人的权限锁问题
1. 龙虾权限很高记忆来设定权限都是不稳定。只有95%能正常运行主要涉及到OpenClaw的记忆管理这点下面会说。
2. 如果你们的需求只是保证Skill不会被随意篡改其实可以使用git来对Skill以及OpenClaw.json进行管理。让OpenClaw定时恢复Skill即可。
2. skill越装越多记忆可能存在冲突问题
1. 要解决这个问题,得对记忆进行合理规划与维护:
1. 定期清理垃圾记忆将记忆根据类型分类整合到合适的MD中。这边推荐先试用[Openclaw-workspace ](https://github.com/win4r/openclaw-workspace)进行整理并且设定每周执行审查建议经过确认后再进行清理保证记忆清洁干净。这样也可以减少不必要的Token消耗并且降低降智的问题。
2. 使用向量数据库建立长期记忆让OpenClaw记住一些大家都在用的规则从而使它变得更加“聪明”。这边推荐使用[memory-lancedb-pro](https://github.com/CortexReach/memory-lancedb-pro)以及相关Skill模型我推荐使用Qwen Embedding 8B模型以及Qwen Reranker模型。
3. 构建一个Skill管理技能用于指示当什么情况去哪个目录找Skill。
4. 配合self-improving-agent Skill效果会更好。
5. 针对记忆的结构化处理这边推荐使用Obsidian+AI将你们的数据、方案整理成一个结构化的文档Memory.md中只填写几个重要信息去这边查询即可。
3. 同一个人对话的上下文污染问题
1. OpenClaw目前不同对话私聊、群聊不同上下文。
2. 你们遇到污染问题我认为可能是没有使用最强的模型Claude4.6opus)造成,我本人是没有遇到过。也有可能是你们只使用了默认的记忆系统。
3. 及时使用/Clear、/New可以减少模型降智问题减少上下文污染。
4. 另一个使用技巧就是对小型任务使用Subagent来执行。也可以根据需求建立多个Agent与单个或者多个机器人绑定。以此分割上下文。
5. 目前OpenClaw还没有语义切换Agent功能所以可以根据执行任务分几个独立Agent出来。
哈喽哈喽~还想请教一下关于AI agent推广相关的经验
1. 中台主要维护哪些内容,是怎样推广给所有项目的同事安装\配置到自己的工作流程中的?
2. 交付项目的同事有哪些提反馈、自由发挥和参与开发的方式呢?
---
1. 中台主要维护哪些内容,是怎样推广给所有项目的同事安装\配置到自己的工作流程中的?
1. 我们的Agent技术都已交给技术中心了可以找技术中心的 陈康来部署。
2. 主要靠老板来推广,比如他让蛋仔组来抄作业。
2. 我这边参与的是H78给他们搞一个易协作自动开单、查询、排期功能他们感觉不错。其他团队的情况得问我领导Freddy。
---
美术那边是给大家都配了openclaw来使用的吗在一些使用体验上codemaker、有道龙虾、openclaw还是有区别的
有道龙虾感觉还在不断完善中一些im机器人指令其实是没生效的![{"anchor_href":"","base_size":"20,20","disable_copy_":false,"expected_size":"20,20","external_info":"{\"emotion_info\":{\"emotion_id_\":0,\"emotion_path_\":\"C:\\\\Program Files\\\\Netease\\\\POPO\\\\popo\\\\emoticon\\\\default\\\\emoji_gif_129.gif\",\"emotion_tag_\":\"[emts]_popo_emoticon_sys_00129_\\r\\n捂脸\\r\\n[捂脸][/emts]\",\"is_store_emotion_\":false,\"is_system_emotion_\":true,\"store_emotion_cid_\":0,\"store_emotion_url_\":\"\"}}","font_size_type_change_aware_":false,"id":"","image_margin":0,"image_url":"","is_link_icon":false,"original_name":"","original_path":"C:\\Program Files\\Netease\\POPO\\popo\\emoticon\\default\\emoji_gif_129.gif","original_size":"-1,-1","press_can_drag":true,"show_in_image_viewer":false}](C:/Program%20Files/Netease/POPO/popo/emoticon/default/emoji_gif_129.gif)比如/new/model
---
1. 首先说明一点OpenClaw是一个可配置强大记忆系统的多面手Agent适合做一个中间衔接、数据传递的事。但一些固定或者专门的事用龙虾比较费token。
2. 我个人推荐使用非OpenClaw的龙虾因为生态跟不上。你有何德何能能与全球开发者抗衡而且这些开发者AI用得远比我们6。
3. codemaker、有道龙虾、openclaw还是有区别
1. 龙虾的记忆系统更加强大。
2. CodeMaker每月5000元额度。
3. 如果ClaudeCode 模型免费我推荐你们用这个代替CodeMaker。
---
目前我们是TA来维护定制的MCP和一些通用的skill作为模版包括一些鉴权和CI相关的指引技能。
项目强相关的那些流程每个项目都有些区别所以目前是设计师在日常工作中跑通了新流程用团队的模版skill来做成skill自动传git+CI发布skillhub
设计师使用和开发中遇到问题时AI总结提issue或MR值班TA或定时任务来处理issue合并MR
不过就是TA和技术向同事比较喜欢用codemaker cli+OMO插件、codex&claude设计师比较倾向有道龙虾+im机器人的交互形式。这其实也导致了相同模型和skill使用体验和效果的一些偏差!
1. 我建议使用ClaudeCode提炼核心Skill之后添加OpenClaw、CodeMaker Cli、CodeX的额外文档让这些Agent多读一些。推荐使用Obsidian构建结构文档。
2. 强制所有人使用ClaudeCode 4.6模型。

View File

@@ -20,6 +20,9 @@
- **[unreal-mcp](https://github.com/runreal/unreal-mcp)** 70star 8个月前
- **[unreal-mcp](https://github.com/runeape-sats/unreal-mcp)** 36star 11个月前
- **[UnrealMCPBridge](https://github.com/appleweed/UnrealMCPBridge)** 28 star 12个月前
- https://www.fab.com/listings/aa699a85-04b1-4746-a29c-962fc3a78f55?tab=%3ARi5adm5%3A
- UI Figma2UE
- https://www.figma.com/community/plugin/1368487806996965174/figma2umg-unreal-importer
- Unity MCP
- [CoplayDev](https://github.com/CoplayDev)/ [unity-mcp](https://github.com/CoplayDev/unity-mcp) 5800star 高频更新
- RenderDoc MCP

View File

@@ -0,0 +1,319 @@
# 前言
- https://github.com/safishamsi/graphify
- 安装:pip install graphifyy && graphify install
**一个面向 AI 编码助手的技能。** 在 Claude Code、Codex、OpenCode、OpenClaw、Factory Droid 或 Trae 中输入 `/graphify`,它会读取你的文件、构建知识图谱,并把原本不明显的结构关系还给你。更快理解代码库,找到架构决策背后的"为什么"。
完全多模态。你可以直接丢进去代码、PDF、Markdown、截图、流程图、白板照片甚至其他语言的图片 —— graphify 会用 Claude vision 从这些内容中提取概念和关系,并把它们连接到同一张图里。
> Andrej Karpathy 会维护一个 `/raw` 文件夹把论文、推文、截图和笔记都丢进去。graphify 就是在解决这类问题 —— 相比直接读取原始文件,每次查询的 token 消耗可降低 **71.5 倍**,结果还能跨会话持久保存,并且会明确区分哪些内容是实际发现的,哪些只是合理推断。
# 安装
## 平台支持
| 平台 | 安装命令 |
| ------------- | -------------------------------------- |
| Claude Code | `graphify install` |
| Codex | `graphify install --platform codex` |
| OpenCode | `graphify install --platform opencode` |
| OpenClaw | `graphify install --platform claw` |
| Factory Droid | `graphify install --platform droid` |
| Trae | `graphify install --platform trae` |
| Trae CN | `graphify install --platform trae-cn` |
Codex 用户还需要在 `~/.codex/config.toml``[features]` 下打开 `multi_agent = true`这样才能并行提取。OpenClaw 目前的并行 agent 支持还比较早期所以使用顺序提取。Trae 使用 Agent 工具进行并行子代理调度,**不支持** PreToolUse hook因此 AGENTS.md 是其常驻机制。
然后打开你的 AI 编码助手,输入:
```
/graphify .
```
## 让助手始终优先使用图谱(推荐)
图构建完成后,在项目里运行一次:
| 平台 | 命令 |
|------|------|
| Claude Code | `graphify claude install` |
| Codex | `graphify codex install` |
| OpenCode | `graphify opencode install` |
| OpenClaw | `graphify claw install` |
| Factory Droid | `graphify droid install` |
| Trae | `graphify trae install` |
| Trae CN | `graphify trae-cn install` |
**Claude Code** 会做两件事:
1.`CLAUDE.md` 中写入一段规则,告诉 Claude 在回答架构问题前先读 `graphify-out/GRAPH_REPORT.md`
2. 安装一个 **PreToolUse hook**(写入 `settings.json`),在每次 `Glob``Grep` 前触发
如果知识图谱存在Claude 会先看到_"graphify: Knowledge graph exists. Read graphify-out/GRAPH_REPORT.md for god nodes and community structure before searching raw files."_ —— 这样 Claude 会优先按图谱导航,而不是一上来就 grep 整个项目。
**Codex、OpenCode、OpenClaw、Factory Droid、Trae** 会把同样的规则写进项目根目录的 `AGENTS.md`。这些平台没有 PreToolUse hook所以 `AGENTS.md` 是它们的常驻机制。
卸载时使用对应平台的 uninstall 命令即可(例如 `graphify claude uninstall`)。
**常驻模式和显式触发有什么区别?**
常驻 hook 会优先暴露 `GRAPH_REPORT.md` —— 这是一页式总结,包含 god nodes、社区结构和意外连接。你的助手在搜索文件前会先读它因此会按结构导航而不是按关键字乱搜。这已经能覆盖大部分日常问题。
`/graphify query``/graphify path``/graphify explain` 会更深入:它们会逐跳遍历底层 `graph.json`,追踪节点之间的精确路径,并展示边级别细节(关系类型、置信度、源位置)。当你想从图谱里精确回答某个问题,而不仅仅是获得整体感知时,就该用这些命令。
可以这样理解:常驻 hook 是先给助手一张地图,`/graphify` 这几个命令则是让它沿着地图精确导航。
<details>
<summary>手动安装curl</summary>
```bash
mkdir -p ~/.claude/skills/graphify
curl -fsSL https://raw.githubusercontent.com/safishamsi/graphify/v3/graphify/skill.md \
> ~/.claude/skills/graphify/SKILL.md
```
把下面内容加到 `~/.claude/CLAUDE.md`
```
- **graphify** (`~/.claude/skills/graphify/SKILL.md`) - any input to knowledge graph. Trigger: `/graphify`
When the user types `/graphify`, invoke the Skill tool with `skill: "graphify"` before doing anything else.
```
</details>
# 用法
```
/graphify # 对当前目录运行
/graphify ./raw # 对指定目录运行
/graphify ./raw --mode deep # 更激进地抽取 INFERRED 边
/graphify ./raw --update # 只重新提取变更文件,并合并到已有图谱
/graphify ./raw --cluster-only # 只重新聚类已有图谱,不重新提取
/graphify ./raw --no-viz # 跳过 HTML只生成 report + JSON
/graphify ./raw --obsidian # 额外生成 Obsidian vault可选
/graphify add https://arxiv.org/abs/1706.03762 # 拉取论文、保存并更新图谱
/graphify add https://x.com/karpathy/status/... # 拉取推文
/graphify add https://... --author "Name" # 标记原作者
/graphify add https://... --contributor "Name" # 标记是谁把它加入语料库的
/graphify query "what connects attention to the optimizer?"
/graphify query "what connects attention to the optimizer?" --dfs # 追踪一条具体路径
/graphify query "what connects attention to the optimizer?" --budget 1500 # 把预算限制在 N tokens
/graphify path "DigestAuth" "Response"
/graphify explain "SwinTransformer"
/graphify ./raw --watch # 文件变更时自动同步图谱(代码:立即更新;文档:提醒你)
/graphify ./raw --wiki # 构建可供 agent 抓取的 wikiindex.md + 每个 community 一篇文章)
/graphify ./raw --svg # 导出 graph.svg
/graphify ./raw --graphml # 导出 graph.graphmlGephi、yEd
/graphify ./raw --neo4j # 生成给 Neo4j 用的 cypher.txt
/graphify ./raw --neo4j-push bolt://localhost:7687 # 直接推送到运行中的 Neo4j
/graphify ./raw --mcp # 启动 MCP stdio server
# git hooks - 跨平台,在 commit 和切分支后重建图谱
graphify hook install
graphify hook uninstall
graphify hook status
# 常驻助手规则 - 按平台区分
graphify claude install # CLAUDE.md + PreToolUse hookClaude Code
graphify claude uninstall
graphify codex install # AGENTS.mdCodex
graphify opencode install # AGENTS.mdOpenCode
graphify claw install # AGENTS.mdOpenClaw
graphify droid install # AGENTS.mdFactory Droid
graphify trae install # AGENTS.mdTrae
graphify trae uninstall
graphify trae-cn install # AGENTS.mdTrae CN
graphify trae-cn uninstall
```
支持混合文件类型:
| 类型 | 扩展名 | 提取方式 |
|------|--------|----------|
| 代码 | `.py .ts .js .go .rs .java .c .cpp .rb .cs .kt .scala .php` | tree-sitter AST + 调用图 + docstring / 注释中的 rationale |
| 文档 | `.md .txt .rst` | 通过 Claude 提取概念、关系和设计动机 |
| 论文 | `.pdf` | 引文挖掘 + 概念提取 |
| 图片 | `.png .jpg .webp .gif` | Claude vision —— 截图、图表、任意语言都可以 |
# 你会得到什么
- **God nodes** —— 度最高的概念节点(整个系统最容易汇聚到的地方)
- **意外连接** —— 按综合得分排序。代码-论文之间的边会比代码-代码边权重更高。每条结果都会附带一段人话解释。
- **建议提问** —— 图谱特别擅长回答的 4 到 5 个问题。
- **“为什么”** —— docstring、行内注释`# NOTE:``# IMPORTANT:``# HACK:``# WHY:`)以及文档里的设计动机都会被抽取成 `rationale_for` 节点。不只是知道代码“做了什么”,还能知道“为什么要这么写”。
- **置信度分数** —— 每条 `INFERRED` 边都有 `confidence_score`0.0-1.0)。你不只知道哪些是猜出来的,还知道模型对这个猜测有多有把握。`EXTRACTED` 边恒为 1.0。
- **语义相似边** —— 跨文件的概念连接,即使结构上没有直接依赖也能建立关联。比如两个函数做的是同一类问题但彼此没有调用,或者某个代码类和某篇论文里的算法概念本质相同。
- **超边Hyperedges** —— 用来表达 3 个以上节点的群组关系,这是普通两两边表达不出来的。比如:一组类共同实现一个协议、认证链路里的一组函数、同一篇论文某一节里的多个概念共同组成一个想法。
- **Token 基准** —— 每次运行后都会自动打印。对混合语料Karpathy 的仓库 + 论文 + 图片),每次查询的 token 消耗可以比直接读原文件少 **71.5 倍**。第一次运行需要先提取并建图,这一步会花 token后续查询直接读取压缩后的图谱节省会越来越明显。SHA256 缓存保证重复运行时只重新处理变更文件。
- **自动同步**`--watch`)—— 在后台终端里跑着,代码库一变化,图谱就会跟着更新。代码文件保存会立刻触发重建(只走 AST不用 LLM文档/图片变更则会提醒你跑 `--update` 进行 LLM 再提取。
- **Git hooks**`graphify hook install`)—— 安装 `post-commit``post-checkout` hook。每次 commit 后、每次切分支后都会自动重建图谱,不需要额外开一个后台进程。
- **Wiki**`--wiki`)—— 为每个 community 和 god node 生成类似维基百科的 Markdown 文章,并提供 `index.md` 作为入口。任何 agent 只要读 `index.md`,就能通过普通文件导航整个知识库,而不必直接解析 JSON。
## Worked examples
| 语料 | 文件数 | 压缩比 | 输出 |
|------|--------|--------|------|
| Karpathy 的仓库 + 5 篇论文 + 4 张图片 | 52 | **71.5x** | [`worked/karpathy-repos/`](worked/karpathy-repos/) |
| graphify 源码 + Transformer 论文 | 4 | **5.4x** | [`worked/mixed-corpus/`](worked/mixed-corpus/) |
| httpx合成 Python 库) | 6 | ~1x | [`worked/httpx/`](worked/httpx/) |
Token 压缩效果会随着语料规模增大而更明显。6 个文件本来就塞得进上下文窗口,所以 graphify 在这种场景里的价值更多是结构清晰度,而不是 token 压缩。到了 52 个文件(代码 + 论文 + 图片)这种规模,就能做到 71x+。每个 `worked/` 目录里都带了原始输入和真实输出(`GRAPH_REPORT.md``graph.json`),你可以自己跑一遍核对数字。
# 针对UE开发的使用方式
### 具体的实施路线图
1. **安装 Graphify 并配置 ClaudeCode 技能:** 在你的项目根目录运行:
```
graphify install # 自动向 CLAUDE.md 注入架构索引规则
/graphify . # 生成初始代码图
```
2. **编写 `CLAUDE.md` 引导:** 在项目根目录创建或修改 `CLAUDE.md`
> **Architecture Context:** Always read `graphify-out/GRAPH_REPORT.md` before answering architecture questions. **UE Standards:** Follow Unreal Engine 5.x coding standards (PascalCase, U-Prefixes).
3. **开发 MCP 插件:** 如果你有能力,实现一个简单的 MCP Server能够通过命令行搜索 UE 的 `Reflection Database`
### 总结建议
- **如果你追求立即理解代码逻辑:** 优先配置 **Graphify**。它能让 Claude 从“逐行看代码”进化到“看地图写代码”。
- **如果你在进行长期复杂的特性开发:** 引入 **Graphiti** 作为 Claude 的“开发日志”,防止它忘记你之前的架构决策。
---
# 具体执行方案
---
实现这一方案的关键在于将 `graphify` 从一个“傻瓜式扫描器”转变为一个“受控的提取引擎”。针对 Unreal Engine 的庞大规模,我们需要通过精确的路径控制和排除规则来实施。
以下是具体的执行方法与命令:
### 1\. 离线构建 Engine 基础图谱 (The Static Atlas)
由于引擎源码几乎不变量,我们只需构建一次。
**执行策略:** 只索引 `Public` 接口,忽略所有实现(`.cpp` )和私有目录。
**具体命令:**
```
# 进入引擎 Source 目录
cd /d D:/UnrealEngine/UE_5.7/Engine/Source
claude --dangerously-skip-permissions
# 执行 graphify 扫描
# --include: 仅包含 Public 文件夹下的头文件,这是剪枝的核心
# --ignore: 排除掉极其庞大的第三方库和中间件
/graphify index . \
--output D:/MatrixTA/AIGameDev/AIDM0/Docs/Graphify/UE5.7_Header.graph \
--include "**/Public/**/*.h" \
--ignore "ThirdParty/**,Developer/**,Programs/**,Intermediate/**,**/Private/**"
```
**提示:** 这一步在 M1 Ultra 上可能仍需数十分钟。建议通过 `--max-depth` 限制继承链的抓取深度,通常设置为 5 已经能覆盖 90% 的关键基类(如 `UObject` -> `AActor` -> `APawn` -> `ACharacter` )。
---
### 2\. ~~针对 UE 的“剪枝”策略配置文件~~
为了避免长命令,建议在项目根目录创建一个 `.graphifyconfig` (或工具支持的配置文件)。
**精细化剪枝逻辑:**
- **反射优先:** 重点提取带有 `GENERATED_BODY()` 的类。
- **模块白名单:** 如果你主要做游戏逻辑,只包含以下核心模块:
- `Runtime/Engine`
- `Runtime/Core`
- `Runtime/CoreUObject`
- `Runtime/InputCore`
**自动化剪枝脚本示例 (Python)** 如果你发现 `graphify` 无法过滤细碎路径,可以用这个脚本生成一个“干净”的临时符号链接目录供其索引:
```python
import os
from pathlib import Path
source_dir = Path("/Users/Shared/Epic Games/UE_5.4/Engine/Source/Runtime")
target_dir = Path("./UE_Thin_Source")
# 仅挑选核心模块的 Public 目录建立软链接
core_modules = ['Engine', 'Core', 'CoreUObject', 'RenderCore']
for module in core_modules:
pub_path = source_dir / module / "Public"
if pub_path.exists():
os.makedirs(target_dir / module, exist_ok=True)
os.symlink(pub_path, target_dir / module / "Public")
```
然后对 `UE_Thin_Source` 运行 `/graphify`
---
### 3\. 实时构建 Project 业务图谱 (The Dynamic Layer)
业务代码变动频繁,需要更轻量、更高频的更新。
**执行命令:**
```
# 在你的项目根目录执行,排除插件和中间文件
/graphify index ./Source \
--output ./project_current.graph \
--ignore "**/Intermediate/**,**/Binaries/**" \
--watch
```
**进阶:结合 ClaudeCode 的 `CLAUDE.md`** 在项目根目录的 `CLAUDE.md` 中添加指令,让 Claude 意识到有两个图谱存在:
```
### Knowledge Graph Context
- **Static Engine Graph:** \`~/ue_engine_full.graph\` (Read-only, contains UE5 API)
- **Project Graph:** \`./project_current.graph\` (Updated on save, contains business logic)
- **Rule:** When a class is prefixed with 'U' or 'A' and not in Project Graph, query Engine Graph via \`mcp-graph-tool\`.
```
#### C++ & Puerts代码图谱
```bash
# 同时指定项目路径和外部引擎路径
# TODO:添加Index Plugins
/graphify index ./Source ./TypeScript \
--output ./Docs/Graphify/Project/Project.graph \
--include "*.cpp,*.h,*.hpp,*.ts" \
--ignore "**/Intermediate/**,**/ThirdParty/**"
```
#### 增量更新模式(逻辑合并 - 推荐方案)
这是最符合工程实践的方法。先建立基础图谱,再将其他目录的内容“追随”进去。`graphify``--update` 标志会自动处理节点冲突并合并新的关系。
**执行命令:**
```bash
# 第一步:索引引擎(静态基础)
/graphify index /path/to/ue_engine/Source/Runtime \
--output ./ue_workspace.graph \
--include "**/Public/**/*.h"
# 第二步:将项目目录合并到同一个图谱中
/graphify index ./MyProject/Source \
--output ./ue_workspace.graph \
--update # 关键参数:在现有图谱基础上合并
```
---
### 4\. 实施 Multi-Graph 挂载的 MCP 方案
要让 ClaudeCode 真正理解这两个图谱,你需要一个简单的 MCP Server 来做中转。
**开发建议:**
1. **加载:** 启动时同时 Load 两个 `.graph` 文件到内存。
2. **查询逻辑:**
```
async function searchClass(className) {
// 1. 先查项目图谱
let result = projectGraph.find(className);
if (!result) {
// 2. 如果没找到,且符合 UE 命名规范,查引擎图谱
result = engineGraph.find(className);
}
return result;
}
```
### 总结执行清单:
1. **环境准备:** 确定 UE 引擎路径。
2. **首次索引:** 使用上述“剪枝命令”生成 `ue_engine_full.graph` ,存放在家目录作为持久缓存。
3. **项目配置:** 在项目内运行带有 `--watch` 的 `graphify` 。
4. **注入 Claude** 编写 MCP Server 将两个图谱的查询接口暴露给 ClaudeCode。
这种“重引擎索引 + 轻业务监控”的模式,能保证在 64GB 内存的本地环境下ClaudeCode 既能秒回 API 调用问题,又能深刻理解你的业务代码耦合。你想尝试编写这个 MCP 路由器的代码吗?

View File

@@ -0,0 +1,25 @@
# 目录结构
- docs
- Netease_AITA_AssetMaker.md项目技术、设计细节入口文档方便Agent来寻找
-
- ProjectsUE工程目录。
# 相关技术与容器
- UE
- UnrealMcp
- Puerts
- Puerts Editor
- uecli
- Readme的材质都是agent调用uecli做的 帮我生产材质 排版材质节点 帮我场景截图,帮我材质蓝图截图 帮我写readme 帮我提交仓库。 https://github.com/wlxklyh/UECLI
- 通过蓝图转c++功能让AI读懂蓝图
- IDE Debug MCP
- https://km.netease.com/v4/section/aigc/detail/blog/263683
- cpp-debugger-cli
- Docker
- Gitea工单以及版本管理。
- OpenClaw子节点部署通过父节点进行控制。
- SMB服务。
- Obsidian Cli文档管理。
## UE测试技术

View File

@@ -0,0 +1,60 @@
# 前言
现阶段其他部门都关注于自己工作领域,而忽视了项目全生命周期流程,一些问题往往会在领域交接时产生,之后的章节会逐步展开。在这之前我说这几点:
- 主Agent与从Agent
- 项目知识管理
- 文档&提示词的质量
- 记忆系统管理 与 Skill
## OpenClaw与多Agent
现阶段因为各种限制不会出现全能性AI所以建议使用主Agent与多个从Agent的方案。但对于公司而言All In One的方案并不是最好选择除了考虑避免All In Boom还有就有就是记忆、上下文、方便迭代方面的考量。
>***另据我所知原生提供Node远程控制方案并且可以自己部署节点的只有OpenClaw。*** 除此之外全球的开源力量使得迭代速度指数级上升似乎有可能成为新的linux成为AI时代的agent 中继 Bridge。
基于以上几点我选择OpenClaw以下是我个人建议架构
![[主Agent与从Agent.canvas]]
项目组主要产出文档以及代码使用主Agent的使用目的主要集中精炼文档、记忆、Skills、沟通其他Agent。
其他点:
1. Agent之间的沟通存在token消耗。目前已经我已经找到解决方案准备测试。
2. 一些相关信息也建议汇总到主Agent中进行汇总但需要注意使用分层结构避免出现降智问题。
## 知识管理
现阶段Markdown之后简称MD 因为高可读性、高信息密度、纯文本成为AI Agent的文档首选。我个人推荐Obsidian作为MD的编辑与查看工具且已有现成的MCP与CLI工具。还有看板、数据表、画板、导图、流程图等功能另外个人推荐使用使用git+oss的方式来做版本管理与协作想简单可以使用SMB。
推荐使用多层结构进行管理避免Context爆炸。这个技巧也可以使用在Skill中。结构参考
- AI策划助手_使用说明.md
- 表结构
- 道具表说明书.md
- 道具表说明书_耕种畜牧.md
- 道具表说明书_加工品消耗品.md
- 道具表说明书_设施与建筑.md
- 配表流程
- skill_开单说明.md
- skill_配表.md
## 记忆系统
目前已知大致有下面3个流派
- 结构化知识图谱派Evolver
- 向量检索派MemorySearch
- 生成式摘要派self-improving-agent
实际上记忆系统都是混合方案。面向多人的企业级方案才是焦点。
### “精耕细作” 式管理记忆
多人使用场景下,往往会有堆积大量 “噪音”以及错误记忆,尽管有一些工具可以自动优化,但依然建议人工介入,让记忆(经验)更快“收敛”。
## 文档&提示词的质量
某专家策划曾提出以下几个问题:
1. 能力不同的人编写的文档是否会对AI的理解与执行产生较大影响
2. 程序需要多加限制还是少加限制?
3. 什么样的文档适合AI来阅读
我个人认为逻辑清晰认知高的人编写的文档与提示词AI更容易理解意图并且能够更好的执行
程序应该关注每个功能维度从function => Module)的输入与输出是否正确所以应该让AI自己发挥除了硬杠杠与主要方向。
AI写的文档往往比人写的更加简练更高复用性所以更适合AI阅读。
---
# 策划
TODO
# 程序
TODO

View File

@@ -0,0 +1,32 @@
| 分类 | 方案/工具名称 | 相关方 | 方案成熟度 | 完成度 | 验证状态 | 备注/说明 |
| --------- | --------------------------- | ------------------ | ------ | ---- | ------ | -------------------------------------------------- |
| 资源检查工具 | neoXassessor | 程序, 雷鹅, QA, 美术 | 互娱成熟方案 | 25% | 整合验证通过 | 说明 |
| 模型缩减工具 | UE/Simplygon | 程序, 美术 | 第三方方案 | 0% | 整合验证通过 | ue/simplygon常规方案 |
| 模型生产 | MATRIX AITA 炼丹炉 | 美术 | 互娱成熟方案 | 75% | 整合验证通过 | 说明 |
| 资源转换 | UE4/5导NEOX工具 \| FBX, GLTF支持 | 美术 | 互娱成熟方案 | 25% | 整合验证通过 | 说明 |
| (天空/光照) | UE UltraDynamicSky | 程序, 美术 | 第三方方案 | 0% | 整合验证通过 | 请填写需求设计链接 |
| 反射 | 离线SSR | 程序, 美术 | 互娱成熟方案 | 0% | 调研或推进中 | 说明 |
| (全局光照) | Lumen | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| (全局光照) | 引擎内置SSR | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| (全局光照) | Planar Reflections | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| (全局光照) | Cubemap | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 后处理 | 项目自定义 | 程序, 美术 | 项目定制开发 | 100% | 调研或推进中 | 说明 |
| 头发、布料模拟 | Hair与Groom系统 | 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 头发、布料模拟 | Chaos布料系统 | 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 高级物理系统 | ABC缓存 (Alembic Ca...) | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 高级物理系统 | VAT顶点动画纹理 | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 高级物理系统 | Physics Constraint | 程序, 美术 | - | - | 整合验证通过 | 说明 |
| 场景物理破坏 | Chaos物理系统 | 程序 | 引擎自带方案 | - | 调研或推进中 | 说明 |
| 场景寻路 | UE5寻路导出插件 | 程序 | 互娱成熟方案 | 0% | 调研或推进中 | 说明 |
| 场景寻路 | 内置寻路系统 (Naviga...) | 程序 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 数字资产版本化管理 | Perforce | 策划, 程序, 雷鹅, QA, 美术 | 互娱成熟方案 | 0% | 调研或推进中 | 说明 |
| 数字资产版本化管理 | UniSVN - 自研加速版TortoiseSVN | 策划, 程序, 雷鹅, QA, 美术 | 互娱成熟方案 | 0% | 整合验证通过 | 说明 |
| 数字资产版本化管理 | 互娱Gitlab研发效率工具 | 策划, 程序, 雷鹅, QA, 美术 | 互娱成熟方案 | 0% | 调研或推进中 | 说明 |
| 剧情编辑器工具 | 过场动画编辑器 (Seq...) | 策划, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 剧情编辑器工具 | Dialogue Plugin (官) | 策划, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 通过数据兼容性评估/支持分支 |
| 动画压缩 | ACL | 策划, 美术 | 引擎自带方案 | 0% | 调研或推进中 | - |
| 开放大世界RPG | ShaderWorld | 美术, 程序 | 第三方方案 | - | 整合验证通过 | [https://lo.host/UWpWbN/](https://lo.host/UWpWbN/) |
| 模型LOD | Imposter | 美术 | 引擎自带方案 | 0% | 整合验证通过 | 说明 |
| 模型LOD | UE自有LOD功能 | 美术 | 引擎自带方案 | 0% | 整合验证通过 | 说明 |
| 可见性剔除 | 剔除距离体积 (Cull Di...) | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |
| 可见性剔除 | 预计算可视体积功能 | 程序, 美术 | 引擎自带方案 | 0% | 调研或推进中 | 说明 |

View File

@@ -0,0 +1,96 @@
# 简介
**MATRIX-AITA POPO 云文档操作 Skill** 是公司内部首个公开的云文档编辑Skill。它彻底解决了以往 AI Agent “只能看、不能写”的痛点,通过强大的自动化能力,让 AI 助手真正拥有了替你处理文档、整理表格、甚至管理多维数据的“双手”,是提升团队办公效率的硬核神器。
## 功能介绍
- 📄 **文档(深度创作与排版)** 你可以指挥 AI 从零开始撰写项目建议书或会议纪要,它不仅能生成文字,还精通排版逻辑。它支持自动插入 1 到 5 级标题、符号列表以及有序列表,让文档结构层次分明。除了创建新文档,你还可以让它在现有文档末尾追加灵感,或者随时远程重命名文档,让文档管理变得动动嘴就能搞定。
- 📊 **表格(智能数据录入)** 繁琐的数据录入和报表更新现在可以全权交给 AI 处理,它能精准地在指定的单元格中填入内容。你可以要求它为关键数据标记背景色以示提醒,或者批量修改某一区域的字体格式,快速生成美观的进度表。即便面对海量数据,它也能通过“精准定位”修改特定数值,再也不用在大表中拉动滚动条寻找目标了。
- 📝 **Markdown专业技术文档生成** 这是为开发者和技术同学准备的排版利器AI 可以为你生成包含代码块、数学公式以及 Mermaid 流程图的高质量内容。它支持标准的 Markdown 语法,能够完美处理复杂的引用、分割线和链接,确保技术文档既专业又易读。无论是编写 README 还是整理技术方案,它都能确保输出的内容格式工整、开箱即用。
- **🗄️ 多维表格(自动化数据中心)** 你可以把复杂的任务追踪、资产管理或人员名单交给 AI 来打理它支持多维表格的各项核心操作。无论是新增一条任务记录还是修改某个单选、日期字段的状态AI 都能像数据库管理员一样精准执行。它还能帮你快速查询表内的现有记录,并根据逻辑自动汇总信息,让你的多维表格真正变成一个能自我更新的智能系统。
- **👥 团队空间(无缝跨部门协作)** 该 Skill 突破了个人文档的限制,能够直接在公司各级“团队空间”中大显身手。它能自动识别团队的目录结构,在指定的页面或文件夹下创建子文档,并自动处理复杂的协作权限验证。这意味着你可以授权 AI 自动更新团队周报、维护公共知识库,让所有团队成员都能实时共享到 AI 辅助生成的最新成果。
---
## 操作步骤介绍
### 1. 安装Skill
进入 https://skills.netease.com/skills/skill_b67793104fac
复制安装命令给Agent或者下载该Skill最后让Agent帮你安装。
### 2. 自动化授权(获取 Cookie
无需手动查代码直接运行我们提供的脚本即可也可让Agent帮忙运行
- **双击运行**:在 `tools` 目录中找到 `collect-cookies_GBK.bat` 并双击。
- **告知 Agent**:登录完成后,回到对话窗口对 Agent 说 **“我登录了”**,它将自动完成后续的 Token 采集与保存。
### 3. 开始使用
授权完成后,你就可以尝试给 Agent 下达类似下方的指令了:
- _“把这个表格里 A1 到 D1 的背景色改成黄色。”_
- _“读取多维表格项目进展中所有状态为进行中的记录。”_
## 备注
该Skill现阶段仍处于开发阶段如果遇到问题请加入 群号7271072@楼嘉杰来解决
---
Gitlab TokenuunSQeYYhBCAn2a5C55H
ANTHROPIC_API_KEY
CI/CD Trigger 8b84579d3405f7a16f86ac2f2bcb59
---
以下是修改后的 `.gitlab-ci.yml` 示例以及关键配置步骤:
### 1. 准备工作CI/CD 变量设置)
在 GitLab 项目的 **Settings -> CI/CD -> Variables** 中,请确保已配置以下变量:
- **`ANTHROPIC_API_KEY`**: 你的内部接口授权 Token。
- **`GITLAB_TOKEN`**: 具有 API 写入权限的 Personal Access Token用于回帖
- **`ANTHROPIC_BASE_URL`**: 设置为 `https://openai.nie.netease.com/v1`(注意添加 `/v1` 后缀)。
### 2. 修改后的 `.gitlab-ci.yml` 脚本
这个脚本会在 Issue 触发时运行,使用 Claude Code 尝试修复,并利用 GitLab API 将结果反馈到 Issue 讨论区。
```yml
claude_main_fix:
stage: ai_fix
image: node:20
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0
script:
- npm install -g @anthropic-ai/claude-code
- export ANTHROPIC_BASE_URL="https://openai.nie.netease.com/v1"
# 1. 配置 Git 机器人身份(必须,否则无法 commit
- git config --global user.email "claude-bot@yourcompany.com"
- git config --global user.name "Claude AI Bot"
# 2. 切换到主分支并确保是最新状态
# 注意:$CI_DEFAULT_BRANCH 通常是 main 或 master
- git checkout $CI_DEFAULT_BRANCH
- git pull origin $CI_DEFAULT_BRANCH
# 3. 运行 Claude Code 进行直接修复
# 删除了“创建新分支”的指令,明确要求“直接修改”
- |
claude --yes "你现在处于项目根目录的主分支。请分析项目结构,直接修复 Issue #$ISSUE_IID。
Issue 描述:$ISSUE_DESCRIPTION
修复完成后,请直接保存文件,不要创建新分支。"
# 4. 提交并推送回主分支
# 使用包含 Token 的 URL 进行推送,确保有权限
- |
git add .
if git commit -m "fix(auto): 自动修复 Issue #$ISSUE_IID [skip ci]"; then
git push "https://project_${CI_PROJECT_ID}_bot:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:$CI_DEFAULT_BRANCH
echo "代码已直接推送到主分支。"
else
echo "没有发现需要修复的更改或提交失败。"
fi
allow_failure: true
```
### 3. 核心改进说明
- **接口重定向**:通过 `export ANTHROPIC_BASE_URL` 强制 CLI 访问网易内部代理接口。
- **非交互式处理**:在 CI 环境中Claude Code 会尝试直接执行指令。建议在指令中明确要求它“创建新分支”而非直接推送到主分支,以保证代码安全。
- **自动回帖流**
- 脚本捕获了 Claude Code 的输出并存入 `repair_summary.txt`
- 使用 `curl` 调用 GitLab 的 `/notes` API。`$CI_API_V4_URL``$CI_PROJECT_ID` 是 GitLab CI 内置的变量,无需手动配置。
- **上下文读取**:为了让修复更准确,你可以在指令中加入 `Check CLAUDE.md for project guidelines`,确保 AI 遵循你在项目中定义的规范。

View File

@@ -0,0 +1 @@
http://redmineapi.nie.netease.com/

View File

@@ -1,232 +0,0 @@
# 前言
# 易协作
- 相关网址
- [Redmine MCP Server (易协作)](https://modelspace.netease.com/mcphub?detail=redmine-mcp-server&namespace=public)
- Auth & Token
- https://console-auth.nie.netease.com/mymessage/mymessage
- https://sa.nie.netease.com/docs/auth/%E8%BF%90%E7%BB%B4%E6%94%AF%E6%92%91/Auth/06-%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C/04%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7/API%20%E6%96%87%E6%A1%A3/02%20Auth%20API%20v2%20%E6%96%87%E6%A1%A3.md#%E8%83%8C%E6%99%AF
# Redmine MCP Server (易协作)
易协作工单管理的 MCP (Model Context Protocol) Server 实现,提供工单查询、详情查看、工单更新、项目管理等功能。
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%8A%9F%E8%83%BD%E7%89%B9%E6%80%A7)功能特性
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#-%E5%B7%A5%E5%85%B7-tools)🔧 工具 (Tools)
- **query_issues**: 搜索/查询易协作工单,支持多种过滤条件(状态、指派人、时间范围、自定义字段等)
- **get_issue_detail**: 获取单个工单的完整详情,包括描述内容和图片
- **update_issue**: 更新/修改工单信息(状态、指派人、主题、描述、备注等),支持人名、邮箱前缀等多种指派人格式
- **get_user_projects**: 获取用户有权限访问的易协作项目列表
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#-%E8%B5%84%E6%BA%90-resources)📚 资源 (Resources)
- **redmine://config**: 服务器配置信息
- **redmine://hosts**: 所有易协作实例及有权限的项目列表
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%EF%B8%8F-%E8%B5%84%E6%BA%90%E6%A8%A1%E6%9D%BF-resource-templates)🗂️ 资源模板 (Resource Templates)
- **redmine://host/{host_name}**: 获取指定易协作实例的详细信息
- **redmine://host/{host_name}/{project_name}**: 获取指定项目的详细信息(版本、状态、跟踪标签等)
- **redmine://project/{project_name}**: 获取默认实例中项目的详细信息(需配置默认实例)
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#-%E6%8F%90%E7%A4%BA-prompts)💬 提示 (Prompts)
- **issue_analysis**: 易协作工单助手,支持状态、优先级、指派人、趋势分析
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F)使用方式
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#streamablehttp-%E6%8E%A8%E8%8D%90)StreamableHTTP (推荐)
```json
{
"mcpServers": {
"redmine-mcp-server": {
"type": "streamableHttp",
"url": "https://mcp.netease.com/servers/redmine-mcp-server/mcp/"
}
}
}
```
#### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E6%8C%87%E5%AE%9A%E9%BB%98%E8%AE%A4%E6%98%93%E5%8D%8F%E4%BD%9C%E5%AE%9E%E4%BE%8B%E5%8F%AF%E9%80%89)指定默认易协作实例(可选)
如果有多个易协作实例,可通过 `redmine-host` 参数指定默认实例,后续调用工具时可省略 `redmine_host` 参数:
```json
{
"mcpServers": {
"redmine-mcp-server": {
"type": "streamableHttp",
"url": "https://mcp.netease.com/servers/redmine-mcp-server/mcp/",
"headers": {
"redmine-host": "dap-v4.pm.netease.com"
}
}
}
}
```
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E8%AE%A4%E8%AF%81%E4%B8%8E%E9%89%B4%E6%9D%83)认证与鉴权
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E8%AE%A4%E8%AF%81%E6%96%B9%E5%BC%8F)认证方式
- 通过请求头 `X-Access-Token` 提供用户Token若在 Codemaker 中使用,无需自行设置)
- 系统会验证Token的有效性并获取用户信息
- Auth 文档(使用 Auth Key 换取 Token[https://g.126.fm/04nIr8l](https://g.126.fm/04nIr8l)
- Auth 平台:[https://console-auth.nie.netease.com/mymessage/mymessage](https://console-auth.nie.netease.com/mymessage/mymessage)
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E9%89%B4%E6%9D%83%E8%A7%84%E5%88%99)鉴权规则
- 用户只能访问其有权限的易协作实例和项目
- 权限判断基于用户邮箱是否在项目成员列表中
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%85%B7%E8%AF%A6%E7%BB%86%E8%AF%B4%E6%98%8E)工具详细说明
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#query_issues---%E6%9F%A5%E8%AF%A2%E5%B7%A5%E5%8D%95)query_issues - 查询工单
搜索/查询易协作工单信息,支持丰富的过滤条件。
**参数:**
|参数|类型|必填|说明|
|---|---|---|---|
|`redmine_host`|string|视配置|易协作实例域名,已配置默认实例时可省略|
|`project`|string|是|项目名称|
|`filters`|object|否|过滤条件,详见过滤器说明|
|`page`|integer|否|页码,默认 1|
|`per_page`|integer|否|每页条数,默认 20最大 100|
**支持的过滤器:**
|过滤器字段|操作符|说明|
|---|---|---|
|`issues_id`|`=`, `!`|工单ID支持多个ID|
|`subject`|`~`, `=`, `!`|主题关键词|
|`status`|`=`, `!`, `o`, `c`|状态名称|
|`assigned_to_id`|`=`, `!`|指派人(邮箱前缀或 `me`|
|`assigned_to_name`|`=`, `!`|指派人中文名称|
|`tracker_id`|`=`, `!`|跟踪标签名称或ID|
|`fixed_version_id`|`=`, `!`, `o`, `c`|目标版本名称或ID|
|`updated_on`|`><`, `>=`, `<=`|更新时间|
|`created_on`|`><`, `>=`, `<=`|创建时间|
|`start_date`|`><`, `>=`, `<=`|开始日期|
|`due_date`|`><`, `>=`, `<=`|截止日期|
|`done_ratio`|`=`, `!`, `>=`, `<=`|完成度 (0-100)|
|`estimated_hours`|`=`, `!`, `>=`, `<=`|预估工时|
|`cf`|对象|自定义字段键为字段ID|
**操作符说明:** `~` 模糊匹配,`=` 等于,`!` 不等于,`o` 开放状态,`c` 关闭状态,`><` 范围,`>=` 大于等于,`<=` 小于等于
**过滤器示例:**
```json
{
"subject": {"op": "~", "value": ["bug"]},
"status": {"op": "=", "value": ["开发中"]},
"assigned_to_id": {"op": "=", "value": ["me"]}
}
```
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#get_issue_detail---%E8%8E%B7%E5%8F%96%E5%B7%A5%E5%8D%95%E8%AF%A6%E6%83%85)get_issue_detail - 获取工单详情
获取单个易协作工单的完整详情,包括基本信息、自定义字段、描述内容及图片。
**参数:**
|参数|类型|必填|说明|
|---|---|---|---|
|`redmine_host`|string|视配置|易协作实例域名|
|`issue_id`|integer|是|工单ID#12278,传参时传数字 12278|
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#update_issue---%E6%9B%B4%E6%96%B0%E5%B7%A5%E5%8D%95)update_issue - 更新工单
更新/修改易协作工单信息。更新成功后会返回更新后的工单详情。
系统会自动获取工单所属项目用于API安全校验无需手动指定项目。
**参数:**
|参数|类型|必填|说明|
|---|---|---|---|
|`redmine_host`|string|视配置|易协作实例域名|
|`issue_id`|integer|是|工单ID|
|`status`|string|否|工单状态名称,如: 新建/开发中/已解决/关闭|
|`subject`|string|否|工单主题|
|`description`|string|否|工单描述|
|`notes`|string|否|工单备注/说明,追加到工单评论中|
|`assigned_to_mail`|string|否|指派人,支持多种格式(见下方说明)|
|`tracker`|string|否|跟踪标签名称,如: BUG/任务/需求|
|`version`|string|否|目标版本号名称|
|`start_date`|string|否|开始日期,格式: YYYY-MM-DD|
|`due_date`|string|否|完成日期,格式: YYYY-MM-DD|
|`estimated_hours`|number|否|预估工作量(小时)|
|`author_mail`|string|否|提单作者,格式同指派人|
|`follows`|string/array|否|跟进QA支持单个字符串(逗号分隔多人)或数组|
|`watcher_user_ids`|array|否|跟踪者用户ID列表如: [386, 387]|
|`custom_field`|object|否|自定义字段,格式: {"字段ID": "值"}|
**指派人格式兼容(`assigned_to_mail` / `author_mail` / `follows`**
|输入格式|示例|处理方式|
|---|---|---|
|完整邮箱|`lien02@corp.netease.com`|直接使用|
|邮箱前缀|`lien02`|自动补全为 `lien02@corp.netease.com`|
|中文名|`李恩`|从项目成员缓存中匹配对应邮箱|
|首字母+中文名|`L李恩`|去除首字母前缀后按中文名匹配|
**更新示例:**
```json
{
"issue_id": 1509,
"status": "开发中",
"assigned_to_mail": "李恩",
"notes": "已开始开发"
}
```
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#get_user_projects---%E8%8E%B7%E5%8F%96%E9%A1%B9%E7%9B%AE%E5%88%97%E8%A1%A8)get_user_projects - 获取项目列表
获取当前用户有权限访问的所有易协作项目列表,按实例分组返回。
**参数:** 无
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E4%B8%BB%E8%A6%81%E5%8A%9F%E8%83%BD)主要功能
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%8D%95%E6%9F%A5%E8%AF%A2)工单查询
支持多种过滤条件:
- 主题关键词搜索
- 状态筛选(新建/开发中/关闭等)
- 指派人筛选(支持邮箱前缀、中文名、`me`
- 跟踪标签/目标版本筛选支持名称和ID
- 时间范围筛选(创建/更新/开始/截止日期)
- 自定义字段筛选
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%8D%95%E8%AF%A6%E6%83%85)工单详情
- 查看工单完整信息(基本字段、自定义字段)
- 支持描述内容中的图片展示
- 显示跟踪者、关注者等协作信息
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%8D%95%E6%9B%B4%E6%96%B0)工单更新
- 修改工单状态、指派人、主题、描述等字段
- 添加备注/评论
- 修改目标版本、跟踪标签、日期、工时等
- 设置跟进QA、跟踪者、自定义字段
- 指派人支持中文名/邮箱前缀/完整邮箱等多种输入格式
- 更新成功后自动返回更新后的工单详情
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86)项目管理
- 获取用户有权限的项目列表
- 查看项目元数据(状态、跟踪标签、版本等)
- 支持多实例管理
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98)数据缓存
- 自动数据更新机制
- 本地缓存提升性能
- 实时流式日志输出
## 工具
| 工具名称 | 工具描述 | 工具参数 |
| ----------------- | ----------------------------------- | --------------------------------------------------------- |
| query_issues | 搜索/查询获取易协作工单信息 | #redmine_host #project #filterspageper_page |
| get_user_projects | 获取用户有权限访问的易协作项目列表 | 暂无参数 |
| get_issue_detail | 获取单个易协作工单详情 | redmine_host*issue_id* |
| update_issue | 更新/修改易协作工单信息,支持修改状态、指派人、主题、描述、备注等字段 | redmine_host*issue_id*statussubjectdescriptionnotes+10 更多 |
## 资源
|资源名称|URI|描述|MIME类型|
|---|---|---|---|
|服务器配置|`redmine://config`|获取易协作 MCP 服务器的配置信息|application/json|
|易协作实例-项目列表|`redmine://hosts`|获取所有易协作实例列表及有权限的项目列表|application/json|
## 模版资源
|模板名称|URI模板|描述|MIME类型|
|---|---|---|---|
|易协作实例详情|`redmine://host/{host_name}`|获取指定易协作实例的详细信息|application/json|
|易协作项目详情|`redmine://host/{host_name}/{project_name}`|获取指定易协作实例中特定项目的详细信息,包括项目可用的版本、状态和跟踪标签|application/json|
## 提示
| | | |
| -------------- | ------- | ------------------------------------- |
| issue_analysis | 易协作工单助手 | #redmine_host #project #analysis_type |

View File

@@ -17,4 +17,193 @@ https://www.fab.com/listings/bb7df0df-a2e7-430f-a382-7c3b121bf767
## 部署方式
1. 该网站项目使用gitea托管使用CI/CD进行生成与部署。
2. 部署到同IP Nodejs Docker容器中。
2. 部署到同IP Nodejs Docker容器中。
# 资产批量下载方式
将 https://github.com/legendary-gl/legendary 下载到./docs/legendary之后学习里面的代码。这是一个第三方开源客户端可以用来下载fab中的资产。
1. 将相关内容写到./docs/legendary并在skill.md添加引用。
2. 检查这个项目是否存在安全问题。
3. 尝试运行legendary来下载我的资产库我会告诉你账号密码。
4. 先下载10个按照Clouderve的结构将下载资产库上传到clouderve。
clouderve的目录结构
- Fab
- UnrealEngine
- Plugins
- ProInstanceToolPlugin
- UE5.5
- UE5.6
- UE5.7
---
在使用 **Claude Code** 或类似的 AI 开发工具编写爬取脚本时,绕过 Cloudflare 的核心在于**“去自动化特征”**。Cloudflare 的防护(如 5 秒盾、Turnstile不仅检查你的 IP还会深入分析你的浏览器指纹、TLS 握手以及行为模式。
以下是针对 2026 年技术环境,在 Claude Code 中实现避开风控的实战策略:
### 1. 使用具备“隐身”能力的浏览器框架
传统的 Selenium 或普通的 Puppeteer 极易被识别。你应该指示 Claude Code 使用以下增强库:
- **Playwright + Stealth 插件**:目前最主流的选择。
- **SeleniumBase (UC Mode)**:这是目前绕过 Cloudflare 最强的工具之一,其 `undetected-chromedriver` 模式能有效隐藏自动化痕迹。
- **npx Claude Code 提示词示例**
> "请使用 Python 的 SeleniumBase 库,并开启 UC ModeUndetected Mode编写爬取脚本以绕过目标的 Cloudflare 检测。"
### 2. 模拟真实浏览器的指纹
Cloudflare 会检查你的 HTTP 请求头是否与底层的 TLS 握手特征匹配(例如,如果你自称是 Chrome 但 TLS 握手特征是 Python-requests会被秒封
- **TLS 指纹模拟**:使用 `curl_cffi` 库,它可以模拟真实浏览器(如 Chrome 120+)的 TLS 握手特征。
- **请求头伪造**:确保 `User-Agent``Accept-Language``Sec-Ch-Ua` 等字段与真实浏览器完全一致。
### 3. IP 质量与地理位置
即使代码再完美,数据中心的 IP如 AWS, Google Cloud也是 Cloudflare 的重点监控对象。
- **使用住宅代理Residential Proxies**:这些 IP 看起来像普通家庭用户。
- **轮换代理**:每次请求或每隔几次操作更换一次 IP。
- **IPv6 优先**2026 年很多防护系统对 IPv6 的限制相对宽松,且资源更丰富。
### 4. 绕过交互挑战 (CAPTCHA/Turnstile)
当 Cloudflare 弹出验证码时,纯代码通常无法处理。
- **验证码识别服务**:在代码中集成如 CapSolver 或 2Captcha 的 API。
- **Cloudflare Workers 代理**:有时通过部署在 Cloudflare 内部的 Workers 作为跳板(利用其内部信任机制)会有奇效,但这取决于目标的具体配置。
---
### 综合架构建议
|**维度**|**推荐技术栈**|**作用**|
|---|---|---|
|**底层驱动**|`SeleniumBase (UC Mode)``Playwright`|隐藏 WebDriver 特征|
|**网络请求**|`curl_cffi` (Python)|解决 TLS 指纹识别问题|
|**IP 资源**|动态住宅代理 (Residential Proxies)|绕过 IP 频率限制和黑名单|
|**行为模拟**|`B-Splines` 曲线模拟鼠标移动|模拟真人操作轨迹|
### Claude Code 实战操作小贴士:
在 Claude Code 终端中,你可以这样引导它:
1. **第一步:环境检查**。先让它写一个简单的脚本访问 `https://nowsecure.nl`(这是一个专门测试 Cloudflare 绕过程度的网站)并截图。
2. **第二步:迭代优化**。如果截图显示被拦截,要求它:“目前的脚本被拦截了,请尝试集成 `stealth` 插件并随机化延迟时间。”
3. **第三步:添加随机性**
Python
```
import time
import random
# 绝不要使用固定的 sleep(5)
time.sleep(random.uniform(2.5, 7.8))
```
**重要提醒:** 爬取数据请务必遵守目标网站的 `robots.txt` 协议及当地法律法规。过度高频的爬取不仅会被封禁,还可能面临法律风险。
# Clouderve
我部署了一个Clouderve http://10.145.96.67:5212/ 用于提供artlib具体的资产下载。请学习 API以及相关文档之后进行构建。
## 主要逻辑
1. 构建一个工具使用fab的账号密码登录并下载资产暂缓开发目前手工下载并上传到clouderve上
2. Artlib每过一年就对Clouderve进行扫描之后将数据库中的项目与Clouderve项对应。确保用户可以下载到指定引擎版本的资产
3. 用户进入资产详细页面后如果该资产在Clouderve上存在页面按钮就是 下载点击后显示下拉菜单显示可现在的版本选择版本后进行下载如果没有则显示访问Fab点击后跳转到fab资产的原界面。
4.
## Clouderve目录说明
clouderve的目录结构
- Fab
- UnrealEngine
- Plugins
- ProInstanceToolPlugin
- UE5.5
- UE5.6
- UE5.7
说明
1. UnrealEngine层级目录为资产种类除此之外还可以是Unity、MetaHuman等。
2. Plugins为资产类型与Fab资产分类有关除此之外还可以Decal、Material、Texture。
3. ProInstanceToolPlugin层级为具体的资产名文件夹我这边上传了ProInstanceToolPlugin作为案例。
4. UE5.5层级目录为引擎版本目前我只打算托管UE4.27、UE5.0~最新版本。
## API文档
- API
- https://docs.cloudreve.org/zh/api/overview
- [https://docs.cloudreve.org/zh/api/overview](https://cloudrevev4.apifox.cn/)
---
# Artlib的意义&提效
1. 收集公司已经采购的资产包Fab、Artstation等方便团队以及公司其他美术同学快速找到资产包。使用RAG技术将Fab资产介绍信息整合成知识库以进行更加精准的资产检索。
1. 解决Muse非常难用的问题。ShareStore资产不够多的问题。
2. 尽可能做到一次收集完所有资产避免去Muse、ShareStore上来回搜索。
3. 多网站资产汇总,只需要一个网站就能检索其他所有资源站的信息。
4. Fab的资产信息具备高准确性制作的知识库检索资产的准确性远超Muse、ShareStore。
2. 资产包资产原子化管理,做到检索单个资产的同时,只需下载所需资产,无需下载整个资产包。
1. 将下载的原子资产进行归类摆放,比如: /Plugins/ArtLib/Models/目录下放置Foliage、Building、Prop等。
3. 给之后的AI开发游戏流程提供弹药AI可以快速找到合适的模型与资产。
4. 维护团队封样库以及材质库信息方便在工作时能及时察觉复用可能性来进行复用。比如李双在SVN上整理的各种分好类的资产库。
5. 给林海开发的插件提供资产包资源 让用户可以直接在UE找到合适资产并直接使用。
6. 给海量模型进行分类为公司未来的生成模型AI提供训练数据。
7. 提供资产点赞窗口之后学习Muse每天采购点赞最多的资产以此吸引用户来该平台抢占Muse空间。
# 开发计划
1. Web开发
1. 修复一些交互Bug。
2. 资产点赞功能,机器人信息推送。
3. Artstation等网站数据接入。
4. 在服务端部署UE Editor每个资产模型、贴图……)进行视觉判断,打上合理标签。
1. AI模型部署。
2. UE Editor 群集方案实现。
5. 借到财务账号并使用爬虫爬取Fab资产。
6. 服务器扩容申请2个服务器用于存储数据并且部署对象存储服务保证数据不会嗝屁。
2. UE插件开发
1. 实现网页点击下载就能直接安装到UE目录。
2. 实现资产包资产批量修改引用,实现资产整理功能。
3. 林海Runtime Load资产插件接入Artlib服务。
4. Plugin云端加载方案探索通过网盘系统构建虚拟目录再通过Webdav接入UE可能会不稳定
3. 开发类似普罗米修斯的资产库客户端WebApp
---
# 启动器
## 提示词
我想制作一个类似Fab启动器用于显示Artlib中的内容、另一个网站内容、以及连接UnrealEngine进行一些资产相关的操作待实现
### 主要功能
1. 使用Netease OIDC进行身份验证。
2. 显示Artlib内容需要做好交互。启动器验证之后会自动帮Artlib验证。
3. 显示另一个网站AssetMaker的内容需要做好交互。启动器验证之后会自动帮Artlib验证。
4. 连接UnrealEngine进行一些资产相关的操作待实现
### UI参考
相关UI参考./docs/screenshots
- 左边是一个可折叠的侧边导航栏,点击左下角的折叠按钮后,可以折叠。
- 左边侧边栏方面放置3个按钮即可Fab、角色生成 按钮、知识技能库
- 折叠效果参考
- fab_reference1.png
- fab_reference1.5.png
- Fab 按钮:点击后显示网站 D:\AI\Website\NeteaseAITA_Artlib使用软连接获取对应的前端文件。
- 角色生成 按钮:点击后显示外部网站。参考 LaunchHub_1.png
- 知识技能库 按钮:点击后显示外部网站 https://ta.netease.com 。参考 LaunchHub_2.png
## 技术栈
- WebApp框架Electron、Electron-vite
- 使用 npm create @quick-start/electron@latest 来建立脚手架。
- 前端技术TypeScript、Vue 3、ViteVue Router、Pinia前端组件请使用Element Plus使用pnpm install element-plus 进行安装除此之外还有Lucide Icons, Tailwind CSS。
- 工具函数Axios、VueUse、pnpm

View File

@@ -0,0 +1,445 @@
# 提示词
请你说中文,并使用中文编写文档。
我需要你发挥卓越的前端开发能力,对我指定的网站进行全方位的“像素级复刻”。这个复刻不仅包括静态页面的排版、配色和字体,还需要涵盖所有的交互细节、动画效果和响应式适配。我们将使用 **Vue 3** 框架和 **Vite** 构建工具。
我想制作一个AI 提示词 => 2D原画 => 参考图 => 3D模型生成的WorkFlow网站功能与风格样式进行像素级复刻
- https://app.assethub.io/
- https://app.assethub.io/inventory
- https://app.assethub.io/workflow
- https://app.assethub.io/texturing
- https://app.assethub.io/image
- https://app.assethub.io/settings/team/4430d872-b40f-4374-bfd0-936205e155aa
- 视频
- https://www.youtube.com/watch?v=h8fKTZDQ90s
- https://www.youtube.com/watch?v=i95-KHATaEY
## 迭代方式
1. 你可以使用浏览器打开这个网站,我会帮你登录。
2. 依次打开左边侧边按钮读取各个页面的HTML结构、CSS信息。将截图存储在Screenshots使用中文名。视频在github上寻找合适工具给我下载下来作为参考。
3. 下载网站都用的图片的,并在复刻网站时用上。
4. 搭建完前后端基础代码之后,先进行前端框架与效果迭代,之后反复对照截图、原始站点进行迭代,保证网站与原站点效果完全一致。
5. 使用ObsidianCli 维护docs下的文档。
## 主要功能
1. 该网站的主要功能是通过一套完整流程来生成3D模型大致流程如下
1. 用户输入的参考图与提示来生成模型原画。
2. 通过原画生成三视图。
3. 使用三视图来生成3D模型。
4. 3DMesh重拓扑。
5. UV Unwrap
6. auto texture
2. 具备3D渲染功能请根据参考原站点使用方案。
3. 具备节点工作流,请使用合适的节点框架,可以考虑使用 https://github.com/comfy-org/ComfyUI 中的节点渲染与流程控制逻辑。
1. 节点工作在线共同预览与编辑功能,实现协同工作。
4. 简单的账户登录机制, 并且提供OpenID登录方式。
## 技术选型
我打算使用:
前端技术TypeScript、Vue 3、Vite前端组件请使用Element Plus使用pnpm install element-plus 进行安装。
后端技术nodejs、Fastify、Mongoose、fastify-jwt
数据库MongoDB、MySQL。
工具函数Axios、VueUse、pnpm
文档管理Obsidian Cli
## 文档目录结构
- docs
- Netease_AITA_AssetMaker.md项目技术、设计细节入口文档方便Agent来寻找
- Screenshots存放截图。
- Videos视频参考。
- WebsiteSource存放HTML、CSS相关信息。
- Web前端相关文档。
- Server后端相关文档。
## 复刻流程提示词
### 0. 准备阶段:安装必要 Skills (工具)
为了精准地感知和复刻目标网站,请优先完成以下工具的安装和配置。如果尚未安装,请在本地环境中执行相关命令:
1. **视觉感知工具 (视觉分析核心)**
* **Skill (依赖)**: `playwright` (用于 headless 浏览器截图、DOM 分析)
* **安装命令**: `npm install playwright && npx playwright install`
2. **资源处理工具 (资产抓取核心)**
* **Skill (依赖)**: `axios`, `mime-types` (用于下载图片、字体)
* **安装命令**: `npm install axios mime-types`
3. **开发工具 (Vue 3 + Vite)**
* **Skill (依赖)**: `@vitejs/plugin-vue` (如果在 Vite 项目中未配置)
---
### 1. 执行阶段:网站复刻工作流
请按照以下详细步骤执行任务。每完成一步,请向我反馈进度。
**目标网站 URL: [在此处替换为您要复刻的网站 URL例如https://example.com]**
#### 第一步:全面观察与分析 (Observation)
1. **高清截图**: 使用 Playwright 对目标网站进行全长Full Page高清截图。同时抓取以下状态的截图
* 特定组件(如 Button, Nav Item`Hover` 状态。
* 移动端(如 iPhone 12 Pro的截图。
2. **配色提取**: 分析截图,生成一份完整的 JSON 格式色板Palette包括主色、辅助色、文本色、背景色、边框色以及渐变色参数。
3. **字体分析**: 确定目标网站使用的主要 WebFonts、字体大小Font Size、行高Line Height和字重Font Weight
4. **结构分析**: 使用 Playwright 导出核心 DOM 树的计算后样式Computed Styles特别是关键组件的 `padding`, `margin`, `display` (Flex/Grid) 属性和 `border-radius`
#### 第二步:静态资源抓取 (Asset Collection)
1. **文件下载**: 自动下载目标网站的所有:
* SVG 图标
* 图片资源PNG/JPEG/WEBP
* 字体文件WOFF2/WOFF
2. **目录整理**: 将下载的资产按照以下结构有序存入您的项目目录中(例如:`src/assets/images`, `src/assets/icons`, `src/assets/fonts`)。
#### 第三步:代码生成 (Vue 3 Component Generation)
1. **项目脚手架**: 如果尚未在当前目录创建 Vite + Vue 3 项目,请创建一个:`npm init vite@latest . -- --template vue`
2. **组件拆解**: 将目标网页拆解为可复用的 Vue 组件(例如:`Header.vue`, `HeroSection.vue`, `Card.vue`, `Footer.vue`)。
3. **样式复刻 (全都要)**:
* 使用全局样式文件(如 `src/style.css`)定义色板变量和字体定义。
* 在 Vue 组件中,使用 `<style scoped>` 编写 **完全一致** 的 CSS 样式。必须精确还原计算后的数值,不要估算。
* 使用原生 CSS Flexbox 和 Grid 进行布局还原。
#### 第四步:动画与交互复刻 (Interaction & Animation)
1. **动态特效**: 分析目标网站的关键动画例如页面滚动时的元素渐现、Header 缩放、Hover 时的微动效)。
* 使用 CSS Transitions/Animations 或 Vue 3 的 `<Transition>` 组件精准还原。
* 尽可能复刻其 `cubic-bezier` 缓动曲线和持续时间Duration
2. **交互状态**: 确保所有按钮、链接在 `Hover``Active` 状态下的像素细节与原站一致。
#### 第五步:自我校对 (Self-Correction)
1. **组件预览**: 完成关键组件后,启动 Vite 开发服务器(`npm run dev`)。
2. **视觉比对**: 将您生成的页面截图与原站截图进行叠加比对,特别注意边距和字体的偏差。
3. **代码清理**: 删除不必要的脚手架代码(如 Vite 默认的 HelloWorld 组件)。
---
### 2. 最终输出物
1. 一个完整的、结构清晰的 Vue 3 + Vite 项目代码库。
2. 在当前目录中可以成功运行 (`npm run dev`)。
3. 生成的页面在视觉和交互上与目标网站达到 95% 以上的像素级匹配度。
---
现在,请开始按照工作流执行。如果有任何步骤遇到困难,或者需要我提供更具体的指令,请立即告知。
# 操作说明
1. 在首页的Drop your concept art here可以使用拖拽或点击的方式上传模型的参考图。此时该区域会显示当前上传的图片。
2. 点击下面的Clear清除图片点击Generate 3D开始3D模型生成流程。按钮会显示成Generating,之后切换到Workflow页面。./docs/screenshots/workflow/Workflow_使用单张图片生成参考图与三视图_1.png
3. Workflow界面主要由白板与节点系统构成。
1. SourceImage节点
1. Inputs为输入图片
2. auto pipeline为是否进行自动流程即 输入图片=> 参考图=> 三视图 => 3D模型 流程。
3. AllowedModel为流程使用的模型设置。
2. Pose节点
1. 用于控制输出参考图的Pose。
2. 节点Transform to Pose即可进行图片生成。
任务:
1. 你帮我实现以上操作逻辑。
2. 实现Workflow页面的中的白板与节点功能参考原始页面。
3. 在后端实现AI服务接口。
1. 可以接入Workflow中的AI服务查询各个服务商的文档
2. 可以通过Netease AIGW接入AI服务。
1. 参考以下网站,网站需要认证,打开浏览器,我来帮你登录。
2. https://aigw.doc.nie.netease.com/21_%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97/10_%E5%9F%BA%E6%9C%AC%E8%AF%B4%E6%98%8E/1_%E5%9F%BA%E6%9C%AC%E8%AF%B4%E6%98%8E.html
3. https://aigw.doc.nie.netease.com/21_%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97/11_%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81/2_%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81.html
4. https://aigw.doc.nie.netease.com/21_%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97/14_%E8%AE%A4%E8%AF%81%E4%B8%8E%E7%AE%A1%E7%90%86/%E8%AE%A4%E8%AF%81%E4%B8%8E%E7%AE%A1%E7%90%86.html
5. https://aigw.doc.nie.netease.com/25_AIGW%E5%8A%9F%E8%83%BD%E6%8C%87%E5%8D%97/10_API%E6%8E%A5%E5%8F%A3.html
6. https://aigw.doc.nie.netease.com/50_FAQ/2_API%E6%8A%A5%E9%94%99.html
3. 可以通过 https://openai.nie.netease.com 的OpenAI、Claude样式的接口来接入服务需要用户提供AUTH_TOKEN)
4. WorkFlow中存放一些Workflows里面有当前工作流信息你可以参考 https://app.assethub.io/workflow/10757
1. 生成完模型后点击模型节点的View 3D Mesh就切换页面在页面中载入3D模型且模型带有贴图使用PBR光照模型进行渲染。
---
5. 使用ObsidianCli 维护docs下的文档。
## 主要功能
1. 该网站的主要功能是通过一套完整流程来生成3D模型大致流程如下
1. 用户输入的参考图与提示来生成模型原画。
2. 通过原画生成三视图。
3. 使用三视图来生成3D模型。
4. 3DMesh重拓扑。
5. UV Unwrap
6. auto texture
2. 具备3D渲染功能请根据参考原站点使用方案。
3. 具备节点工作流,请使用合适的节点框架,可以考虑使用[ https://github.com/comfy-org/ComfyUI ](https://github.com/Comfy-Org/ComfyUI_frontend)中的节点渲染与流程控制逻辑。
1. 节点工作在线共同预览与编辑功能,实现协同工作。
4. 简单的账户登录机制, 并且提供OpenID登录方式。
## 技术选型
我打算使用:
前端技术TypeScript、Vue 3、Vite前端组件请使用Element Plus使用pnpm install element-plus 进行安装。
后端技术nodejs、Fastify、Mongoose、fastify-jwt
数据库MongoDB、MySQL。
工具函数Axios、VueUse、pnpm
文档管理Obsidian Cli
## 文档目录结构
- docs
- Netease_AITA_AssetMaker.md项目技术、设计细节入口文档方便Agent来寻找
- Screenshots存放截图。
- Videos视频参考。
- WebsiteSource存放HTML、CSS相关信息。
- Web前端相关文档。
- Server后端相关文档。
---
>以上作废
# # 提示词
请你说中文,并使用中文编写文档。
## 功能
1. 该网站的主要功能是通过一套完整流程来生成3D模型大致流程如下
1. 用户输入的参考图与提示来生成模型原画。
2. 通过原画生成三视图。
3. 使用三视图来生成3D模型。
4. 3DMesh重拓扑。
5. UV Unwrap
6. auto texture
2. 具备3D渲染功能请根据参考原站点使用方案。
3. 具备节点工作流,请使用合适的节点框架,可以考虑使用 https://github.com/comfy-org/ComfyUI 中的节点渲染与流程控制逻辑。
1. 节点工作在线共同预览与编辑功能,实现协同工作。
4. 简单的账户登录机制, 并且提供OpenID登录方式。
## 技术选型
我打算使用:
前端技术TypeScript、Vue 3、Vite前端组件请使用Element Plus使用pnpm install element-plus 进行安装。
后端技术nodejs、Fastify、Mongoose、fastify-jwt
数据库MongoDB
工具函数Axios、VueUse、pnpm
文档管理Obsidian Cli
## 文档目录结构
- docs
- Netease_AITA_AssetMaker.md项目技术、设计细节入口文档方便Agent来寻找
- Screenshots存放截图。
- Videos视频参考。
- WebsiteSource存放HTML、CSS相关信息。
- Web前端相关文档。
- Server后端相关文档。
# 需求
1. 在保证相关接口不变的情况下,重构./backend 中的服务端内容。
2. 根据需求迭代./frontend
3. 简单登录预留OIDC登录。
4.
## OIDC 参考代码
```python
#coding:UTF-8
"""
Requirements:
1. Flask >= 0.10.1
2. requests
3. jwkest >= 1.1.7
Usage:
python oidc_code_demo.py -H {listen_address} -p {listen_port}
Help:
python oidc_code_demo.py -h
"""
import os
import uuid
from hashlib import md5
import datetime
from urllib import urlencode
import json
import requests
from flask import Flask, request, jsonify, session, redirect
from jwkest.jwk import SYMKey
from jwkest.jws import JWS
from jwkest.jwk import load_jwks_from_url
from jwkest.jws import NoSuitableSigningKeys
__revision__ = "0.01"
__author__ = "chenxs@corp.netease.com"
OIDC_CLIENT_ID = ""
OIDC_CLIENT_SECRET = ""
OIDC_PROVIDER = "https://login.netease.com/connect"
OIDC_AUTHORIZATION_SERVER = "https://login.netease.com/connect/authorize"
OIDC_TOKEN_ENDPOINT = "https://login.netease.com/connect/token"
OIDC_USERINFO_ENDPOINT = "https://login.netease.com/connect/userinfo"
OIDC_SCOPE = "openid nickname email fullname dep title empno"
OIDC_REDIRECT_URI = "https://127.0.0.1:5000/finish"
OIDC_JWKS_URI = "https://login.netease.com/connect/jwks"
OIDC_ALG = "HS256"
PYTHON_OIDC_DEMO = Flask(__name__)
@PYTHON_OIDC_DEMO.route("/", methods=['GET'])
def index():
"""index"""
if 'username' in session:
body = (
u"</br><h2>OpenID Connect 鐧诲綍鎴愬姛銆<E5A79B></h2></br>"
u"鎮ㄧ殑鐢ㄦ埛鍚嶆槸锛<EFBFBD>%s</br>"
u"鎮ㄧ殑鍏ㄥ悕鏄細%s</br>"
u"鎮ㄧ殑閭鏄細%s</br>"
u"鎮ㄧ殑鑱屼綅鏄細%s</br>"
u"鎮ㄧ殑閮ㄩ棬鏄細%s</br>"
u"鎮ㄧ殑宸ュ彿鏄細%s</br>") % (
session['username'], session.get('fullname', ''),
session.get('email', ''), session.get('title', ''),
session.get('dep', ''), session.get('empno', ''))
body += u"<a href='/login'>鎴虫垜閲嶆柊鐧诲綍</a>"
return body
else:
return u"<a href='/login'>鎴虫垜鐧诲綍</a>"
@PYTHON_OIDC_DEMO.route("/login", methods=['GET'])
def login():
"""AuthN Request"""
session.clear()
now = datetime.datetime.now().strftime("%s")
session['uid'] = uuid.uuid4().hex
session['state'] = session['uid']
session['nonce'] = md5(session['uid'] + now).hexdigest()
authn_request_params = {
'response_type': 'code',
'client_id': OIDC_CLIENT_ID,
'state': session['state'],
'nonce': session['nonce'],
'scope': OIDC_SCOPE,
'redirect_uri': OIDC_REDIRECT_URI,
#'prompt': 'login',
'display': 'touch',
}
redirect_url = "?".join([
OIDC_AUTHORIZATION_SERVER, urlencode(authn_request_params)])
return redirect(redirect_url)
def token_request(code):
"""2. Token Request"""
params = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': OIDC_REDIRECT_URI,
'client_id': OIDC_CLIENT_ID,
'client_secret': OIDC_CLIENT_SECRET,
}
_resp = requests.post(OIDC_TOKEN_ENDPOINT, data=params)
return json.loads(_resp.text)
def id_token_verify(id_token, nonce=None):
"""3. id token verify"""
now = int(datetime.datetime.now().strftime("%s"))
if OIDC_ALG == "HS256":
signed_keys = [SYMKey(key=OIDC_CLIENT_SECRET)]
else:
signed_keys = load_jwks_from_url(OIDC_JWKS_URI)
try:
plain_id_token = JWS().verify_compact(id_token, signed_keys)
except NoSuitableSigningKeys:
# logger the id_token please
return {'error': 'can not verify the id token'}
print "idtoken: %s" % plain_id_token
if nonce:
if (not plain_id_token.has_key('nonce')) or (
plain_id_token['nonce'] != nonce):
return {'error': 'id token nonce not correct'}
if plain_id_token['iss'] != OIDC_PROVIDER:
return {'error': 'id token iss not correct'}
if plain_id_token['aud'] != OIDC_CLIENT_ID:
return {'error': 'id token aud not correct'}
if now >= int(plain_id_token['exp']):
return {'error': 'id token expired'}
return {'id_token': plain_id_token}
@PYTHON_OIDC_DEMO.route("/finish", methods=['GET'])
def finish():
"""
1. AuthN Response
2. Token Request
3. id token verify
4. userinfo request
5. login user
"""
# 1. AuthN Response
try:
code = request.args.get('code')
if session['state']:
state = request.args.get('state')
if state != session['state']:
return u"闈炴硶璇锋眰"
except ValueError:
return u"闈炴硶璇锋眰"
# 2. Token Request
token = token_request(code)
print "token: %s" % token
if token.has_key('error'):
return u"鍑洪敊浜嗭細%s" % str(token)
# 3. id token verify
id_token_verified = id_token_verify(token['id_token'])
if id_token_verified.has_key('error'):
return id_token_verified['error']
else:
id_token = id_token_verified['id_token']
print "id_token: %s" % id_token
# 4. userinfo request
_req_session = requests.Session()
_req_session.headers.update({
"Authorization": "Bearer %s" % token['access_token']})
userinfo_req = _req_session.get(OIDC_USERINFO_ENDPOINT)
userinfo = json.loads(userinfo_req.text)
# login the user
session['username'] = userinfo['nickname']
session['email'] = userinfo['email']
session['title'] = userinfo.get('title', '')
session['empno'] = userinfo.get('empno', '')
session['dep'] = userinfo.get('dep', '')
session['fullname'] = userinfo.get('fullname', '')
return redirect("/")
if __name__ == "__main__":
import sys
import argparse
parser = argparse.ArgumentParser(
usage='%(prog)s [options]', version='%(prog)s ' + str(__revision__))
parser.add_argument(
'-H', '--host', dest='host', type=str,
help="Specify listening adress, default is 127.0.0.1")
parser.add_argument(
'-p', '--port', dest='port', type=int,
help="Specify listening port, default is 5000")
parser.add_argument(
'-c', '--client_id', dest='client_id', type=str,
help="oidc client_id is required.")
parser.add_argument(
'-s', '--client_secret', dest='client_secret', type=str,
help="oidc client_secret is required.")
args = parser.parse_args()
host = args.host or '127.0.0.1'
port = args.port or 5000
OIDC_REDIRECT_URI = "http://%s:%s/finish" % (host, port)
OIDC_CLIENT_ID = args.client_id
OIDC_CLIENT_SECRET = args.client_secret
if not OIDC_CLIENT_ID or not OIDC_CLIENT_SECRET:
parser.print_help()
parser.exit()
PYTHON_OIDC_DEMO.secret_key = "this is a random secret"
PYTHON_OIDC_DEMO.debug = True
PYTHON_OIDC_DEMO.run(host=host, port=port)
```

View File

@@ -0,0 +1,150 @@
# 提示词
请你说中文,并使用中文编写文档。
我打算使用使用Nodejs构建一个MCP SSE服务器帮助OpenClaw以及其他Agent进行OIDC认证。并且编写对应的Skill协助Agent使用该MCP。MCP 服务器充当了 **OIDC Client****凭证管理器**
OIDC相关文档在./docs/Netease_OIDC.md里面的链接可能需要认证你可以打开浏览器等待我来帮你认证。
#### 核心流程步骤:
1. **触发**Agent 在执行任务时发现需要访问 NetEase 内部接口。
2. **调用 MCP**Agent 调用 MCP 工具 `get_auth_url`
3. **生成状态**MCP 生成一个随机 `state` 存入 MongoDB并构建 OIDC 授权链接。
4. **交互**
- **方案 A (手动)**Agent 将链接发给用户,用户点击。
- **方案 B (自动化)**:使用类似 `browser-use` 的 Skill由 Agent 直接控制浏览器打开该链接,并等待用户在弹出的窗口中完成 SSO 登录。
5. **回调**用户登录成功后NetEase OIDC 重定向到 MCP 的 Fastify 接口。
6. **换取 Token**MCP 后端用 `code` 换取 JWT并将其与用户信息绑定存入 MongoDB。
7. **通知/轮询**Agent 通过 MCP 轮询或 SSE 得到“认证成功”状态,随后获取 JWT 进行业务操作。
---
### 2. 技术实现细节
#### 2.1 数据库设计 (Mongoose)
主要用于维护认证状态和存储持久化的 Token。
JavaScript
```
// models/AuthState.js
const authStateSchema = new mongoose.Schema({
state: { type: String, required: true, unique: true }, // 用于防止CSRF和匹配回调
userId: { type: String, required: true }, // 对应 OpenClaw 的用户 ID
status: { type: String, enum: ['pending', 'completed'], default: 'pending' },
accessToken: String,
idToken: String,
refreshToken: String,
expiresAt: Date,
createdAt: { type: Date, expires: '10m', default: Date.now } // 10分钟后自动过期
});
```
#### 2.2 MCP 服务器核心逻辑 (Fastify + SSE)
MCP 服务器需要同时支持 **SSE (与 Agent 通信)****HTTP (处理 OIDC 回调)**
- **MCP Tool: `get_netease_auth_url`** 输入:`userId` 输出:`authUrl`, `state` 逻辑:生成 OIDC URL`state` 记录到 MongoDB。
- **Fastify Route: `/api/callback`** 逻辑:
1. 接收 `code``state`
2. 校验 `state` 是否在 MongoDB 中存在。
3. 向 NetEase OIDC 换取 Token。
4. 更新 MongoDB 中的状态为 `completed`
5. 通过 SSE 发送一个 `auth_success` 事件。
#### 2.3 改进思路:自动化认证 (Browser-use 集成)
当 OpenClaw服务器端与用户本地客户端不在同一台电脑时直接调用系统命令`open``start`)只会打开服务器端的浏览器,用户完全看不到。
既然你提到用户开启了 **Chrome 远程调试模式 (`--remote-debugging-port=9222`)**,我们可以利用 **CDP (Chrome DevTools Protocol)** 协议来实现跨机器的“远程操控”。
以下是针对你的 Node.js MCP 服务器的技术实现方案:
---
##### 1. 核心架构:远程 CDP 连接
要让运行在服务器上的 MCP 能够操控用户本地的 Chrome流程如下
###### 挑战:网络连通性
通常用户的电脑处于内网NAT 之后),服务器无法直接访问用户的 `9222` 端口。
- **方案 A (内网直连)**:如果两者在同一公司内网且 IP 互通MCP 直接访问 `http://<User_IP>:9222`
- **方案 B (内网穿透)**:使用 `frp``ssh -R`。用户本地运行一个穿透工具,将本地的 `9222` 映射到服务器可见的某个端口(如服务器的 `19222`)。
---
##### 2. 技术实现MCP 服务器代码 (Node.js)
在你的 Node.js 环境中,推荐使用 **Playwright**,因为它原生支持 `connectOverCDP`,非常适合这种场景。
###### 安装依赖
```bash
npm install playwright
```
###### MCP 工具逻辑示例
在 MCP 中编写一个 `open_remote_auth_page` 的工具:
```ts
import { chromium } from 'playwright';
async function openRemoteBrowser(userIp, authUrl) {
// 1. 连接到用户本地开启了调试模式的浏览器
// 假设通过穿透或直连,地址为 userIp:9222
const browser = await chromium.connectOverCDP(`http://${userIp}:9222`);
// 2. 获取当前的上下文(通常是用户正开着的浏览器窗口)
const defaultContext = browser.contexts()[0];
const page = await defaultContext.newPage();
// 3. 导航到 NetEase OIDC 认证页面
await page.goto(authUrl);
// 4. (可选) 监听 URL 跳转,自动化部分流程
// 比如检测到跳转回 callback URL 时,自动告知 Agent
page.on('framenavigated', frame => {
const url = frame.url();
if (url.includes('your-callback-url')) {
console.log('用户已完成认证!');
// 这里可以触发 MongoDB 状态更新或 SSE 通知
}
});
// 注意:不要执行 browser.close(),否则会关掉用户的整个 Chrome
}
```
---
##### 3. 针对用户的操作指南 (Skill 配合)
为了让这个 Skill 成功运行Agent 需要引导用户做两件事:
1. **启动 Chrome 调试模式** 用户需要在本地终端执行:
```bash
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
```
2. **提供 IP/端口信息** Agent 可以询问用户:“请提供你本地机器的 IP 地址(或内网穿透后的地址)”。
---
##### 4. 更优雅的改进方案WebRTC 或轻量级“领航员”
如果让用户手动输入 IP 比较繁琐,你可以编写一个 **“Claw-Bridge”**(一个几十行代码的本地 Node.js 脚本或 Go 小程序):
- **工作原理**
1. 用户在本地运行 `Claw-Bridge`
2. `Claw-Bridge` 启动后通过 WebSocket 连接到你的 Fastify 服务器(建立长连接)。
3. 当 MCP 需要打开网页时,向该 WebSocket 发送指令。
4. `Claw-Bridge` 在用户本地执行 `open <URL>`
**优点**
- **无需开启远程调试端口**(安全性更高,不会暴露浏览器的控制权给整个网络)。
- **无需固定 IP**(只要有网络,长连接就能通)。
- **权限最小化**:本地程序只负责“打开链接”,不涉及控制浏览器内部。
##### 5. 总结建议
- 如果你追求**深度自动化**(比如想让 Agent 帮用户自动填表):使用 **Playwright + CDP**
- 如果你只追求**方便用户点击**(仅仅是弹出一个认证页):编写一个轻量级的 **本地桥接脚本** 配合你的 Fastify 服务器,通过 WebSocket 转发“打开页面”的请求。
---
### 3. MCP Skill (工具定义) 示例
在 MCP 服务器中定义的工具描述:
```
{
"name": "authenticate_netease",
"description": "当需要访问网易内部服务但未授权时使用。该工具会返回一个认证链接,必须引导用户完成认证。",
"inputSchema": {
"type": "object",
"properties": {
"user_id": { "type": "string", "description": "当前用户的唯一标识" }
},
"required": ["user_id"]
}
}
```
---
### 4. 安全建议
1. **PKCE (Proof Key for Code Exchange)**:既然是 Node.js 后端,务必开启 PKCE。在生成授权链接时生成 `code_verifier` 并存储在 MongoDB回调时带上。
2. **JWT 验证**:使用 `fastify-jwt` 验证从 OIDC 拿到的 `id_token` 的签名,确保其确实来自网易的认证服务。
3. **State 绑定**:确保回调时的 `state` 只能被使用一次,防止重放攻击。
4. **环境隔离**:建议在 MongoDB 中区分开发环境和生产环境的 `client_id`
## 技术选型
我打算使用:
后端技术nodejs、Fastify、Mongoose、fastify-jwt
数据库MongoDB

View File

@@ -0,0 +1,44 @@
{
"nodes":[
{"id":"6cda312f1671af71","type":"group","x":40,"y":-100,"width":640,"height":480,"label":"艺设主Agent主机"},
{"id":"dc77b937f7c566ed","type":"group","x":200,"y":-60,"width":460,"height":420,"label":"主机内从属该项目的其他独立Agent"},
{"id":"e0be32c1a73875dc","type":"text","text":"视频","x":420,"y":90,"width":100,"height":60},
{"id":"2cebc34d3a7c245c","type":"text","text":"2D原画","x":420,"y":180,"width":100,"height":60},
{"id":"7882c46e998f881a","type":"text","text":"项目组主Agent","x":-183,"y":120,"width":140,"height":60},
{"id":"ea7c8aa0bff2fa90","type":"text","text":"GameEngine","x":-183,"y":480,"width":140,"height":60},
{"id":"18373fd6585e719c","type":"text","text":"N个程序Agent实例","x":-577,"y":480,"width":195,"height":60},
{"id":"b34e85d1dd50f9c8","type":"text","text":"GUI","x":420,"y":0,"width":100,"height":60},
{"id":"a9b698ceb5dd6a73","type":"text","text":"程序员","x":-520,"y":360,"width":82,"height":60},
{"id":"d5eee5e43fd23a22","type":"text","text":"AI PM","x":-522,"y":250,"width":85,"height":60},
{"id":"5be324303b104387","type":"text","text":"结构化文档","x":-539,"y":120,"width":120,"height":60},
{"id":"28097b51d705a955","type":"text","text":"策划","x":-340,"y":-30,"width":62,"height":60},
{"id":"8494558c61aa8d2a","type":"text","text":"3D模型","x":420,"y":280,"width":100,"height":60},
{"id":"833c175da3d2a493","type":"text","text":"艺设PM","x":220,"y":120,"width":100,"height":60},
{"id":"ac74ea6efda6eef5","type":"text","text":"艺设主Agent","x":60,"y":120,"width":120,"height":60},
{"id":"981296901b8023dc","type":"text","text":"TA","x":600,"y":280,"width":50,"height":60}
],
"edges":[
{"id":"0d9b7a20bf3155e8","fromNode":"7882c46e998f881a","fromSide":"right","toNode":"ac74ea6efda6eef5","toSide":"left"},
{"id":"075e967cbfa97ab2","fromNode":"ac74ea6efda6eef5","fromSide":"left","toNode":"7882c46e998f881a","toSide":"right"},
{"id":"2161b83cbe328d2c","fromNode":"ac74ea6efda6eef5","fromSide":"right","toNode":"833c175da3d2a493","toSide":"left"},
{"id":"228740714a1239b1","fromNode":"2cebc34d3a7c245c","fromSide":"bottom","toNode":"8494558c61aa8d2a","toSide":"top"},
{"id":"3b2a3d2f0759a20f","fromNode":"833c175da3d2a493","fromSide":"right","toNode":"b34e85d1dd50f9c8","toSide":"left"},
{"id":"c4f1151359441b76","fromNode":"833c175da3d2a493","fromSide":"right","toNode":"e0be32c1a73875dc","toSide":"left"},
{"id":"e4f544cdbdf54bf0","fromNode":"833c175da3d2a493","fromSide":"right","toNode":"2cebc34d3a7c245c","toSide":"left"},
{"id":"a0ddf315a9a36a4b","fromNode":"833c175da3d2a493","fromSide":"right","toNode":"8494558c61aa8d2a","toSide":"left"},
{"id":"1af4431a8eece637","fromNode":"8494558c61aa8d2a","fromSide":"right","toNode":"981296901b8023dc","toSide":"left"},
{"id":"a923f220037feb30","fromNode":"e0be32c1a73875dc","fromSide":"right","toNode":"981296901b8023dc","toSide":"left"},
{"id":"98dd6721df277382","fromNode":"b34e85d1dd50f9c8","fromSide":"right","toNode":"981296901b8023dc","toSide":"left"},
{"id":"de59526c9ed59eaa","fromNode":"981296901b8023dc","fromSide":"bottom","toNode":"ea7c8aa0bff2fa90","toSide":"top"},
{"id":"d5b792fcbc7396e8","fromNode":"5be324303b104387","fromSide":"right","toNode":"7882c46e998f881a","toSide":"top","label":"精炼成策划Skills"},
{"id":"a262dcd90f1680bf","fromNode":"7882c46e998f881a","fromSide":"bottom","toNode":"ea7c8aa0bff2fa90","toSide":"top"},
{"id":"cabfd5a821aa5c8a","fromNode":"18373fd6585e719c","fromSide":"right","toNode":"ea7c8aa0bff2fa90","toSide":"left"},
{"id":"f4873708803fc309","fromNode":"5be324303b104387","fromSide":"bottom","toNode":"d5eee5e43fd23a22","toSide":"top"},
{"id":"3ea49ab37b7060a6","fromNode":"d5eee5e43fd23a22","fromSide":"bottom","toNode":"a9b698ceb5dd6a73","toSide":"top"},
{"id":"0ec96114f463b257","fromNode":"a9b698ceb5dd6a73","fromSide":"bottom","toNode":"18373fd6585e719c","toSide":"top","label":"APCX"},
{"id":"1f8399d6f211376b","fromNode":"a9b698ceb5dd6a73","fromSide":"right","toNode":"ea7c8aa0bff2fa90","toSide":"left"},
{"id":"6e8fa0ebbc7f7930","fromNode":"28097b51d705a955","fromSide":"left","toNode":"5be324303b104387","toSide":"top","label":"BrainMaker"},
{"id":"3178e9ba6ba35eb9","fromNode":"28097b51d705a955","fromSide":"right","toNode":"7882c46e998f881a","toSide":"top"},
{"id":"2b2ba8c27a037d28","fromNode":"7882c46e998f881a","fromSide":"left","toNode":"5be324303b104387","toSide":"right"}
]
}

View File

@@ -69,4 +69,52 @@ OpenClaw待探索
POPO失忆
1. Skill找不到。
2. POPO 没有识别 Channel找不到。机器人不知道 popo就是 moltbot-popo。
3. 机器人只认识 loujiajie@corp.netease.com 不认识楼嘉杰
3. 机器人只认识 loujiajie@corp.netease.com 不认识楼嘉杰
视频学习:
1. [解剖小龍蝦 — 以 OpenClaw 為例介紹 AI Agent 的運作原理 - YouTube](https://www.youtube.com/watch?v=2rcJdFuNbZQ)
2. https://space.bilibili.com/28321599?spm_id_from=333.337.search-card.all.click
1. https://www.bilibili.com/video/BV1VzfoBFE5w/?spm_id_from=333.1387.homepage.video_card.click&vd_source=a5a1507212662f8883c096200c37b6bd
#
1. [x] 程世纪 Skill 接入
2. [x] Freddy OpenClaw自拍Skill加入。
3. [x] 程世纪Skill 添加发送文件到POPO的命令。
4. [x] 思考级别修改 /think
5. [ ] 远程控制浏览器的能力
6. [ ] 记忆优化技能TODO:需要加入确认内容)https://github.com/win4r/openclaw-workspace
7. [ ] 三层记忆?
1. [ ] 【openclaw分层索引版一键安装包win系统mac系统节省模型80%token消耗多轮对话三层时间记忆索引clawhub技能演示AI借鉴openviking】 https://www.bilibili.com/video/BV1XjPFzjEg3/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
2. [ ] 【拒绝暴力压缩!分层索引版 OpenClaw 10轮省48% → 50轮省76% 越长越省,关键决策永不丢失(已开源)】 https://www.bilibili.com/video/BV1hcAQzsES9/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
3. [ ] https://www.bilibili.com/video/BV1JrNKz7EUv/?spm_id_from=333.337.search-card.all.click&vd_source=d47c0bb42f9c72fd7d74562185cee290
8. [ ] LanceDB与插件
9. [ ] OpenClaw 卡死问题解决。编写守护进程软件
10. [ ] OpenClaw下载文件管理。
11. [ ] OpenClaw Docker部署。
12. [x] Grp账号申请
13. [x] ~~grp 账号与龙虾关联问题解决~~。 https://open.popo.netease.com/docs/api/robot/msg-send
14. [ ] Skill
1. [ ] AI PM
1. [x] 多用户同时使用stdIO
2. [ ] Cookie获取优化。
3. [ ] HttpStream改造。
4. [ ] 自动化拆单 易协作上的
2. [ ] POPO 云文档 修改。
15. [ ] MutiAgent
1. [x] POPO 多Agent问题查找。
2. [x] 多Agent A2A协议。
16. [ ] OpenClaw 体验优化
1. [x] Subagent规则
17. [x] OpenClaw ACP 控制其他智能体。 https://www.bilibili.com/video/BV1X4wAzEEMe/?spm_id_from=333.1387.upload.video_card.click&vd_source=d47c0bb42f9c72fd7d74562185cee290
18. [ ] OpenClaw控制 其他OpenClaw。
- 视频
- [ ] 【🚀OpenClaw重磅更新浏览器自动化终极方案龙虾自动接管Chrome浏览器无需重复登录账号工作流打包成可复用Skill【龙虾教程】】 https://www.bilibili.com/video/BV1yVwXzGEbL/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
- [ ] 【🚀OpenClaw高级使用经验分享2026年最强生产力五分钟打造多Agent协作编程开发团队模型容灾机制深度配置+云端Gateway操控本地macOS】 https://www.bilibili.com/video/BV1pScgzXEB7/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
- [x] ***【🚀OpenClaw高级玩法之工作区优化+三大Agent深度解析龙虾保姆级教程让你学会Persistent Agent、Sub-Agent和ACP Agent】*** https://www.bilibili.com/video/BV1X4wAzEEMe/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
- [ ] 【🚀OpenClaw高级进阶技巧分享模型精选策略+记忆系统优化经验+深度搜索集成+Gateway崩溃自动修复Claude Code自动读日志修Bug重启验证】 https://www.bilibili.com/video/BV1pefHB1ENJ/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
- [ ] 【🚀【OpenClaw教程】OpenClaw高级玩法记忆蒸馏+Skill固化+模型降级Token成本直降40%,效率倍增!便宜模型也能完成复杂任务!龙虾教程】 https://www.bilibili.com/video/BV1WbPTzHEaa/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
- [ ] 【🚀OpenClaw最强大脑GPT-5.4深度实测Agent能力强到离谱自主完成多轮长链路复杂任务实测可全自动为其他设备部署小龙虾OpenClaw教程】 https://www.bilibili.com/video/BV1PdPHzFEFJ/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e
- [ ] 【Claude Code 内部实践Skill 编写的 9 个最佳实践-哔哩哔哩】 https://b23.tv/0Brym4l
- [ ] 【🚀解锁OpenClaw多Agent高级玩法Token消耗直接减半这才是正确的使用方式不同任务分配不同模型独立Session、独立记忆独立工作空间】 https://www.bilibili.com/video/BV1dqffBMEcg/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e

View File

@@ -0,0 +1,93 @@
# Obsidian CLI
## 参考资料
- [Obsidian CLI 详细教程:官方命令行工具,激进拥抱智能体,高效 + 自动化 + 降低 Token 消耗](https://www.bilibili.com/video/BV19TPXzAEtW/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e)
- [如何为 Obsidian 配置 AI Agent9 个必备 Skill 详解与安装指南](https://www.bilibili.com/video/BV14d9TBiE1S/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e)
## 配置步骤
### 1. 开启 CLI
Obsidian → 小齿轮Settings→ 开启**命令行界面**
### 2. 安装 Claudian 插件(可选)
Obsidian 适配 Claude Code 的插件,提供更好的集成体验。
- 仓库:[Claudian](https://github.com/YishenTu/claudian)
- 安装后需配置自定义变量
### 3. 安装 Obsidian Skills
官方 Skill 集合,包含 Markdown、Bases、Canvas、CLI、Defuddle 等能力。
- 仓库:[obsidian-skills](https://github.com/kepano/obsidian-skills)
- Defuddle 需要全局安装依赖:`npm install -g defuddle`
### 4. 安装绘图增强 Skill
支持 Excalidraw、Mermaid、Canvas 等可视化图表生成。
- 仓库:[axton-obsidian-visual-skills](https://github.com/axtonliu/axton-obsidian-visual-skills)
## 其他 Skill
| Skill | 用途 | 仓库 |
| --- | --- | --- |
| tutor-skills | 学习辅助 | [GitHub](https://github.com/bevibing/tutor-skills) |
## 外部大型代码库索引策略(以 UE 为例)
针对 Unreal Engine 这种体量的外部依赖,全量索引通常不是最优解。以下是三种可行策略:
### 方案一:软链接(最简单)
在项目根目录创建指向引擎源码的软链接,让索引工具将其视为项目内目录。
```bash
ln -s /Users/Shared/Epic\ Games/UE_5.4/Engine ./UE_Source_Link
```
> [!warning] 注意
> - 务必在 `.gitignore` 中忽略该目录
> - UE 源码文件量巨大,索引时间可能极长
### 方案二:多图谱架构(性能最优)
将引擎(静态)和项目(动态)分离为两个独立图谱,通过桥接查询关联。
1. 对 UE 引擎预生成 `engine_graph.db`(一次性)
2. 对项目生成 `project_graph.db`(持续更新)
3. 在 MCP Server 中实现双向查询:项目类 → 发现继承关系 → 自动去引擎图谱检索基类定义
### 方案三:指定多路径参数
```bash
graphify . /path/to/external/ue_source --output ./unified_graph
```
> [!note] 弊端
> 每次扫描都会重新处理外部目录,除非工具支持增量索引。
### 剪枝策略:减少索引噪音
对 UE 外部目录索引时应进行**语义剪枝**,提升 Claude 回复精准度:
| 策略 | 说明 |
| --- | --- |
| **排除 Private 目录** | 只索引 `Public/` 下的头文件(接口和宏定义),性价比最高 |
| **模块化索引** | 按需索引:渲染相关只索引 `Runtime/Renderer` + `Runtime/RenderCore`;逻辑相关只索引 `Runtime/Engine` + `Runtime/CoreUObject` |
| **头文件优先** | 仅解析 `.h` 文件,不解析 `.cpp`,大幅降低图谱复杂度同时保留类层次关系 |
### 让 Claude Code 感知外部索引
`CLAUDE.md` 中声明外部图谱的存在和使用规则:
```markdown
# External Context
- **UE Engine Source:** Indexed at `~/.cache/ue_engine_graph.db`
- **Search Rule:** If a class prefix is 'U', 'A', or 'F' and not found in the current project, use the `search_ue_engine_graph` tool via MCP.
```
这样可将外部目录转变为**只读远程知识库**——既保证响应速度,又扩展知识边界。