Compare commits

...

13 Commits

Author SHA1 Message Date
9aad52347b refactor(tracers): 统一命令字段名并重构数组追踪器创建逻辑
- 将所有命令的 `params` 字段重命名为 `payload`,以保持命名一致性
- 将 `ArrayTracerCreateOptions` 从联合类型简化为单一接口,移除 `array` 参数,新增 `initial` 和 `walker` 参数
- 引入 `buildInitial` 函数集中处理初始数组的构建逻辑
- 使用 `metadata` 对象管理数组长度状态,替代独立的 `arrayLength` 变量
- 更新错误消息格式,移除方括号前缀
- 调整泛型参数,使 `createArrayTracer` 更通用
2026-03-04 02:34:12 +08:00
2dfc4ced67 docs: 优化开发规则与项目介绍文档的表述
- 移除关于禁止修改源代码的临时限制说明,该限制已不再适用
- 统一并优化多处中文标点与空格的格式,使文档更整洁
- 调整项目介绍中关于协议设计的表述,使其更清晰准确
- 合并`tracer-type.md`中的分隔线,使列表结构更紧凑
2026-03-02 21:06:36 +08:00
19d4b97669 fix(tracer): 修复异步scope中异常处理后的状态设置问题
发生ScopeError时不执行flush,否则即便抛出异常也会执行flush
2026-02-24 20:33:59 +08:00
8a2399e890 docs(tracer-context): 添加详细的中文注释说明scope的设计原理和实现细节。 2026-02-23 13:03:22 +08:00
9f08c34225 refactor(tracer-context): 引入ScopeError类并优化错误处理逻辑
- 新增ScopeError自定义错误类,用于区分范围相关错误
- 将error字段重命名为exception以更准确描述其用途
- 优化flush方法,仅在有必要时输出指令序列
- 简化错误处理逻辑,移除冗余的console.error调用
- 确保ScopeError能正确向上抛出而不被捕获
2026-02-23 03:20:13 +08:00
134d4e2b19 refactor(tracer-context): 改进 scope 状态管理以支持嵌套检测
- 引入 SCOPE_STATE 枚举明确区分初始、执行中和已完成状态
- 将 scoping 布尔标志替换为 state 枚举,支持检测嵌套调用
- 分离同步和异步错误处理流程,确保状态正确更新
- 修复 flush 方法中 commands 和 error 的清理逻辑
2026-02-23 02:05:58 +08:00
8894458f4c feat(tracer-context): 添加scope方法以支持追踪异步错误
新增scope方法用于包裹异步或同步代码块,自动捕获错误并记录到上下文中。同时将dump方法重命名为flush以更准确描述其行为(清空并输出指令序列)。重构内部数据结构,将commands和error统一管理在scopeResult对象中。
2026-02-22 22:37:06 +08:00
0e61e4f5b9 docs: 新增并更新产品战略、技术设计与商业化规划文档
- 新增 AI 时代下的 StructRail 战略定位与发展路线图,明确 AI 集成方向
- 更新前端可视化库设计方案,细化架构、技术挑战与商业化结合点
- 重构商业化策略文档为 Q&A 形式,深入探讨市场、产品与增长策略
2026-02-22 22:36:48 +08:00
a9eaaa6023 docs: 新增项目文档并更新开发规则
- 新增品牌命名、商业化策略、SDK视觉噪音处理、可视化库设计和系统架构文档
- 更新开发规则,明确禁止主动修改项目源代码文件
- 所有文档均为中文编写,用于记录项目设计讨论和决策
2026-02-18 00:18:35 +08:00
4929ca496b feat: 新增 GraphTracer 并重构 ArrayTracer 的初始化方式
- 新增 GraphTracer 及其类型定义,支持图的创建和操作命令
- 重构 ArrayTracer 的 create 函数,使用 walker/commit 模式替代直接的 array 参数,提高灵活性
- 更新类型导出和命令联合类型以包含 GraphTracer
- 调整示例代码以使用新的初始化方式
2026-02-14 01:30:30 +08:00
9d5a46129e refactor(tracer-context): 移除自动输出指令序列的逻辑
移除 process.on('exit') 中的自动输出逻辑,改为通过 dump 方法手动获取指令序列。
2026-02-13 20:57:27 +08:00
305a9c7dc3 docs: 添加开发规则文档
- 新增开发规则文档,明确代码修改前的讨论流程
- 规范API设计时的多语言兼容性考虑范围
- 文档包含C、C++、Java等主流编程语言支持要求
2026-02-10 09:23:32 +08:00
a3328b8617 fix(array-tracer): 修正创建命令中数组参数的必填性
将 `ArrayTracerCreateCommand.params.array` 从可选参数改为必填参数,以匹配实际实现逻辑。
同时更新 `createArrayTracer` 函数,确保在未提供 `array` 时使用空数组作为默认值,保持向后兼容性。
2026-02-08 23:29:24 +08:00
19 changed files with 861 additions and 54 deletions

View File

@@ -0,0 +1,65 @@
# AI 时代下的 StructRail 战略定位与发展路线图
## 1. 背景与趋势分析:从 Coding 到 Reasoning
在 AI 时代2024-2025+),中国软件开发职业环境对算法技能的要求发生了质的转变:
* **Coding 能力贬值**AI如 Copilot, GPT-4已能秒生成绝大多数标准算法代码。
* **Reasoning 能力升值**:面试官不再纠结于“手撕代码”的语法细节,转而考察:
* **代码审计**:能否一眼看出 AI 生成代码的逻辑漏洞(如边界条件、内存泄漏)。
* **过程推演**:能否清晰解释代码在特定数据输入下的执行轨迹。
* **底层理解**:能否跨越语言语法,理解数据结构在内存中的真实布局与操作(指针、引用、所有权)。
**结论**AI 极大地降低了“编写代码”的门槛,但极大地提高了**“理解与调试复杂逻辑”**的门槛。
## 2. StructRail 的新定位
StructRail 不仅仅是一个算法学习工具,更应定位为 **AI 生成代码的“验证引擎”与“调试器”**
* **测谎仪Verifier**:验证 AI 生成的复杂算法(如图算法、红黑树)逻辑是否正确。
* **白盒解释器Explainer**:将 AI 的“黑盒代码”转化为可视化的“白盒流程”,帮助人类理解。
* **逻辑调试器Visual Debugger**:通过 **Time Travel时间旅行** 功能,让开发者回溯到 Bug 发生的瞬间,直观看到拓扑结构错误(如链表断裂、图连接错误),而非枯燥的内存值。
## 3. AI 深度集成路线图
为了实现上述定位StructRail 需要在协议层、SDK 层和平台层进行 AI 深度集成。
### 第一阶段:开发辅助 (AI-Assisted Development)
*目标:降低用户接入 SDK 的门槛,让 Tracer 代码“自动生长”。*
1. **智能插桩助手 (Auto-Instrumentation Copilot)**
* **功能**:用户提供原始算法代码(如 C++ 快排AI 自动识别关键操作swap, compare并插入对应的 SDK 调用代码。
* **示例**:将 `swap(arr[i], arr[j])` 自动转换为 `tracer.pick(i); tracer.pick(j); tracer.patch(...); tracer.drop(...)`
2. **自然语言生成 (Text-to-Tracer)**
* **功能**用户输入自然语言描述“展示二叉树插入过程”AI 直接生成可运行的 Tracer 代码,用于快速演示。
### 第二阶段:运行时智能增强 (AI-Enhanced Runtime)
*目标:利用 Tracer 产生的数据流,进行实时的逻辑分析和解释。*
1. **实时算法解说员 (Live Narrator)**
* **功能**:平台后端接收 Tracer 指令流AI 实时分析并生成自然语言解说。
* **效果**当动画播放到“分区”步骤时AI 弹幕解释:“这里选取了 5 作为基准,将小于 5 的元素移到左侧”。
2. **逻辑错误诊断 (Logic Doctor)**
* **功能**AI 分析 Tracer 指令流,识别逻辑错误(如死循环、链表环路、非法的图操作)。
* **交互**:在时间轴上直接标记“逻辑错误点”,并给出修复建议。
### 第三阶段:协议层面的进化 (Protocol Evolution)
*目标:为 AI 提供语义信息,使其能理解操作意图。*
1. **协议扩展Meta 字段**
* **建议**:在 `TracerCommand` 接口中增加可选的 `meta` 字段,用于存储操作的语义信息。
* **示例**
```typescript
// 修改前:仅表示选中
tracer.pick(5);
// 修改后携带语义AI 可读取
tracer.pick(5, { meta: { role: 'pivot', intent: 'partition_base' } });
```
* **价值**AI 读取 `meta` 后,能生成更精准的解说词(“选中基准点” vs “选中下标 5”
## 4. 关键行动建议
1. **协议升级**:优先在 `Command` 接口中增加 `meta?: Record<string, any>` 字段。
2. **SDK 优化**:在设计 API 时,考虑如何方便地让 AI 生成代码(例如保持 API 的原子性和语义清晰)。
3. **Prompt 工程**:建立一套标准的 Prompt 模板,指导用户如何使用 LLM 将现有代码转换为 StructRail SDK 代码。

View File

@@ -0,0 +1,47 @@
# Structrail 品牌命名解读
## 1. 命名构成
- **项目名称**Structrail
- **构词方式**`Struct` + `t` + `rail` (共享字母 `t` 的混成词)
- **核心双关**
- Struct **Trail** (数据轨迹)
- Struct **Rail** (结构轨道)
## 2. 核心释义Struct Trail (数据轨迹)
这是最贴切且最具动态感的解释,直接映射了项目的核心价值——**可视化数据结构的演变过程**。
* **与 Tracer (跟踪器) 的呼应**
* 核心组件 `Tracer` 的作用是记录数据结构的变化。
* 每一次变化都在时间维度上留下了一个 `Trail` (痕迹/足迹)。
* 用户通过 `Tracer` 追踪到了数据的 `Trail`
* **Time Travel (时间旅行) 的隐喻**
* `Trail` 暗示了一条可以沿着往返的小径。
* 支持“上一步”、“下一步”的操作,就像沿着留下的面包屑 (breadcrumbs) 在历史轨迹中穿梭。
* 用户可以随时回溯,查看数据在某一时刻的状态。
* **Debugging (调试) 的本质**
* 算法执行的过程,本质上就是数据状态在时间流中留下的一条长长的轨迹。
* 调试就是沿着这条轨迹寻找异常点。
## 3. 双关释义Struct Rail (结构轨道)
作为第二层含义,`Rail` 为项目增添了稳固感和基础设施的韵味。
* **规范与引导 (On the Rails)**
* `Rail` 暗示了“轨道”,意味着代码在既定的逻辑轨道上运行。
* 可视化的目的之一是确保算法逻辑“在正轨上” (Stay on the rails),帮助用户发现何时“脱轨” (Off the rails)。
* **基础设施感 (Infrastructure)**
**Ruby on Rails* 一样,`Rail` 给人一种坚实底座的感觉。
* 暗示 Structrail 是承载算法运行、支撑可视化功能的坚实平台。
## 4. 结论与建议
建议以 **Struct Trail** 作为品牌叙事的核心,强调“追踪”、“轨迹”和“时间旅行”的概念,同时保留 **Struct Rail** 作为一种有趣的双关解读,暗示平台的稳定性和规范性。
**Slogan 构思:**
> **Structrail**: Visualize the **trail** of your data structures.
> (Structrail可视化你数据结构的轨迹。)

View File

@@ -0,0 +1,187 @@
# StructRail 产品商业化与战略规划 Q&A
本文档以问答形式记录了关于 StructRail 平台在商业化路径、技术策略、AI 时代定位等核心问题的深度探讨。
***
### Q1: 对于整个平台,如果希望它成为一个产生商业价值的产品,应该怎么做?
**A:**
要产生商业价值StructRail 不能只做一个“库”,而必须做一个“平台”。建议从 **用户价值**、**商业模式** 和 **产品形态** 三个维度进行规划:
1. **核心价值主张**:不仅仅是“看”算法,而是“懂”和“调试”。
* **可调试性 (Time Travel Debugging)**:支持逐行调试用户自己的代码,查看数据结构变化。
* **多语言支持**:打破语言壁垒,适合作为通用的教学工具。
* **创作自由度**:不仅支持标准算法,更支持用户自定义逻辑的可视化。
2. **商业化场景 (Product-Market Fit)**
* **ToC (学生/求职者)**:提供“可视化题解”和“调试会员”,解决刷题痛点。
* **ToB (教育机构)**:提供交互式课件和可视化作业系统,解决教学抽象和批改难的问题。
* **ToC (创作者)**:提供高清视频导出工具,服务技术博主。
3. **技术壁垒**
* 建立 Tracer Protocol 协议标准生态。
* 构建高性能的安全沙箱和渲染引擎。
***
### Q2: 在 ToC 市场,推荐在语言层面做会员功能差异化吗?
**A:**
**非常推荐**,这是一种符合技术成本逻辑的 Freemium 策略。
* **策略核心**
* **前端语言 (JS/TS/WASM)****完全免费**。利用浏览器端计算能力(零边际成本),作为引流款和开源展示。
* **后端语言 (Java/C++/Go)****云端运行付费**。利用云端沙箱(高成本),提供高性能、免配置的运行环境作为增值服务。
* **风险与对策**
* **风险**:直接锁死 Java/C++ 可能流失核心学生用户(算法主力语言)。
* **对策**:采用“混合运行时”策略。
* **云端一键运行**:仅限会员(或新用户试用),筛选付费意愿强的用户。
* **本地运行 (Local Runner)**:提供免费 CLI 工具,允许用户在本地运行重型语言并上传数据。给“白嫖党”留活路,同时不消耗服务器资源。
***
### Q3: SDK 调用代码混杂在算法中,会不会产生严重的视觉噪音?
**A:**
**会,而且影响很大。** 但这是“可编程性”的代价,可以通过分级策略解决:
1. **Level 1: 隐式追踪 (零侵入)**
* 对于 JS/TS (Proxy)、C++ (Operator Overloading)、Python (Magic Methods),利用语言特性实现**全自动追踪**。用户只需初始化,后续写原生代码即可触发可视化。
2. **Level 2: 显式调用 (精细控制)**
* 对于 Java 原生数组或 C 指针,无法隐式拦截,必须保留显式 SDK 调用。
* 这是为了保留“可编程性”,允许用户精确控制动画时机。
3. **Level 3: IDE 视觉降噪**
* 在 Web IDE 中,通过 **“幽灵文本” (Ghost Text)** 技术将 SDK 代码渲染为灰色/半透明。
* 提供 **“专注模式”**,一键折叠所有可视化相关代码,只展示算法逻辑。
***
### Q4: 既然有免费额度,会不会出现用户刷号(刷额度)的情况?应该一开始就筛选付费用户吗?
**A:**
刷号问题客观存在,但通过技术手段(手机号/微信登录)可控。对于中国市场,建议采取 **“漏斗筛选”** 策略:
1. **不要一上来就收费**:直接付费门槛太高,用户无法体验产品价值。
2. **用“麻烦”筛选用户**
* 提供免费的 **Local Runner**(本地运行+上传),路径繁琐,适合无付费能力但有时间折腾的学生。
* 提供付费的 **Cloud Sandbox**(云端一键运行),路径极致便捷,适合追求效率、愿意付费的用户。
3. **付费点设计**
* **效率**:免配置、一键运行。
* **数据**:云端存储、多端同步。
* **功能**Time Travel 深度调试。
***
### Q5: 我们的业务策略应该是 ToB/G 还是 ToC
**A:**
**ToC 树品牌、磨产品ToB/ToG 赚利润、上规模。** 建议采用 **Product-Led Growth (PLG)** 模式:
1. **起步期 (ToC)**:全力打磨 C 端体验,积累海量用户和社区口碑(题解/教程)。**目标是 DAU 和品牌声量。**
2. **成长期 (ToC -> ToB)**:推出“教师版/团队版”,通过 C 端用户(学生/助教)自下而上渗透高校。
3. **成熟期 (ToB/ToG)**:基于已有的教学渗透率,向高校/政府销售私有化部署或定制课程服务。**目标是营收和壁垒。**
***
### Q6: AI 时代下,如果 AI 能直接生成可视化,我们的产品痛点还存在吗?
**A:**
这是一个极度危险但也充满机遇的转折点。
* **威胁**:如果只做“手动写代码的库”,会被 AI 颠覆。因为 AI 可以生成 D3.js 代码。
* **机会**AI 生成的可视化通常是 **“黑盒”、“不可调试”、“不可交互”** 的。
**StructRail 的新定位AI-Powered Algorithm Visualization Engine**
我们不做 AI 的对手,做 AI 的 **“后端引擎”**
1. **自动插桩 (Auto-Instrumentation)**:利用 AI 分析用户代码,自动插入 StructRail SDK 指令。用户得到的是 **“可调试、可交互”** 的可视化,而非 AI 生成的死动画。
2. **精确性与标准化**StructRail 提供标准化的 Tracer Protocol保证可视化的精确性和可维护性这是 AI 生成的代码无法比拟的。
3. **AI 讲解 (AI Tutor)**:利用 SDK 产生的精确数据流,喂给 AI 生成实时语音旁白。
**结论**:痛点依然存在,但解法变了。从“帮用户画图”转变为“提供可被 AI 操控的标准可视化运行时”。
***
### Q7: 是否应该将前端渲染逻辑沉淀为独立的可视化库?它在商业化中扮演什么角色?
**A:**
**必须这样做。** 建议将前端渲染逻辑剥离为独立的开源库(暂定名 `StructRail Viz`),定位为 **“算法领域的 ECharts”**。
1. **技术解耦与复用**
* 将 Tracer SDK数据生成与渲染层数据展示分离中间通过标准化的 Tracer Protocol 连接。
* 该库本质上是一个 **确定性状态机 (Player)**,支持“时间旅行”和“进度拖拽”。
* 可以被嵌入到任何 Web 环境中,如 VS Code 插件、Hexo/Hugo 博客、在线文档、电子书等。
2. **生态扩展 (特洛伊木马策略)**
* 通过开源库进入开发者的工具链和内容生态,让 StructRail 的水印和链接遍布互联网。
* 建立 Tracer Protocol 的事实标准,任何生成该协议的工具(包括 AI都可以使用该库渲染。
3. **商业化变现点**
* **主题市场 (Theme Store)**:售卖高级皮肤(赛博朋克、手绘风、像素风)。
* **高级渲染器**:提供基于 WebGL/WebGPU 的高性能渲染引擎(用于大规模图数据)或 3D 渲染器。
* **导出服务**提供基于云端的高清视频渲染服务4K/60fps服务于内容创作者。
***
### Q8: 我们的平台如果面向全球市场开展商业化行动,相较于面向中国国内市场会有什么区别?
**A:**
我们的商业化策略在两个市场呈现出明显的**“分而治之”**特征:国内市场侧重于**“筛选与防守”**,全球市场侧重于**“增长与生态”**。
| 维度 | 全球市场 (Global Market) | 中国国内市场 (Domestic Chinese Market) |
| :--- | :--- | :--- |
| **1. 用户画像** | **CS 学生、开源贡献者、自学者**<br>侧重计算机科学基础教育、直观理解算法原理。 | **求职刷题党、考研学生、技术博主**<br>侧重“面试突击”、“算法竞赛”及“题解制作”,功利性更强。 |
| **2. 支付习惯** | **订阅制 (Subscription)**<br>习惯为工具和效率付费SaaS接受自动扣费。<br>**支付工具**Stripe (信用卡), PayPal。 | **买断/季卡 + 漏斗筛选**<br>付费意愿相对较低,需通过门槛筛选用户。<br>**支付工具**:微信支付、支付宝(需深度集成)。 |
| **3. 推广渠道** | **技术社区驱动 (Community Driven)**<br>主战场GitHub, Product Hunt, Reddit, Twitter。<br>策略:通过开源可视化库 (`@structrail/viz`) 进入开发者工具链。 | **内容创作者驱动 (Creator Economy)**<br>主战场Bilibili, 知乎, 掘金, 公众号。<br>策略:利用**“高清视频导出”**功能赋能技术博主,让他们的算法讲解视频成为平台的免费广告。 |
| **4. 基础设施** | **云端优先 (Cloud First)**<br>用户习惯 Web IDE 的无缝体验AWS/Cloudflare 等基础设施成熟,成本可控。 | **混合运行 (Hybrid Runtime)**<br>鉴于国内服务器带宽昂贵且用户量大,大力推广 **Local Runner**(本地运行+上传),将计算和流量成本转嫁给用户端。 |
| **5. 法律合规** | **数据隐私 (GDPR)**<br>重点关注用户数据(代码、日志)的隐私保护和跨境传输合规。 | **实名认证 (KYC)**<br>必须集成手机号/微信一键登录既是合规要求ICP备案也是防止“刷号/白嫖”的技术手段。 |
**核心行动差异:**
1. **中国市场 - 漏斗筛选与创作者经济**
* **漏斗筛选**:免费用户推荐使用 **Local Runner**(本地运行),筛选出动手能力强或预算有限的用户;付费用户享受 **Cloud Sandbox**(云端一键运行)。
* **视频破圈**:提供 **4K/60fps 高清视频导出** 功能成为技术博主B站/抖音)制作算法讲解视频的“生产力工具”,实现病毒式传播。
2. **全球市场 - PLG 与开源生态**
* **PLG 增长**:直接开放云端体验,通过极致的 **Time Travel Debugging** 体验留住用户。
* **开源渗透**:利用开源的 `@structrail/viz` 库建立技术标准,让全球开发者在博客/文档中嵌入组件,形成网络效应。
3. **共同战略 - AI 可视化引擎**
* 无论市场如何,定位均为 **“AI 的可视化引擎”**。开发 IDE 插件,让 AI 生成的代码自动插入 StructRail SDK解决 AI 代码“不可解释、难以调试”的痛点。

View File

@@ -0,0 +1,53 @@
# SDK 视觉噪音处理策略
## 1. 问题背景
在算法可视化场景中,为了记录数据结构变化,需要在用户算法代码中插入 SDK 调用(如 `tracer.patch()`, `tracer.pick()`)。过多的 SDK 调用代码会产生“视觉噪音”,破坏算法逻辑的连贯性,增加认知负担,与平台“低侵入性”和“原生体验”的设计目标冲突。
## 2. 核心原则
- **原生优先 (Native First)**:尽量利用编程语言特性实现隐式追踪,避免引入非标准的封装数据结构(如避免强制用户使用 `MyArray.set()` 替代 `arr[]`)。
- **显式降噪 (Explicit Reduction)**:在无法隐式追踪的场景下,通过 IDE 的视觉设计弱化 SDK 代码的存在感。
- **可编程性保留**:承认并保留显式调用 SDK 的必要性(用于精细控制动画或处理不支持的语言特性),将其视为“高级功能”而非“噪音”。
## 3. 分级解决方案
### 3.1 Level 1: 隐式追踪 (Implicit Tracing) —— 零侵入
利用现代编程语言的高级特性(代理、重载、魔术方法),拦截原生数据结构的读写操作,自动触发可视化事件。
- **适用场景**
- **JavaScript / TypeScript**: 使用 `Proxy` 对象拦截数组/对象操作。
- **C++**: 使用运算符重载(`operator[]`, `operator=`)封装 `std::vector` 或自定义容器。
- **Python**: 使用魔术方法(`__getitem__`, `__setitem__`)封装 `list`
- **用户体验**
```typescript
// 用户只需在初始化时声明一次
const tracer = new ArrayTracer().watch(arr);
// 后续全是原生代码,无感知
arr[i] = arr[j];
```
### 3.2 Level 2: 显式调用 (Explicit Call) —— 精细控制
对于不支持隐式拦截的语言特性(如 Java 原生数组、C 语言指针),或者用户需要插入非数据结构操作的指令(如 `tracer.delay()`, `tracer.log()`),必须使用显式 SDK 调用。
- **适用场景**
- Java 原生数组 (`int[]`)。
- C 语言指针操作。
- 算法逻辑之外的控制指令(暂停、日志、自定义高亮)。
- **代码规范**
- 保持 SDK 调用独立成行,避免嵌套在复杂逻辑中。
- 命名保持简洁(如 `tracer.patch` 而非 `Visualizer.getInstance().updateElement`)。
### 3.3 Level 3: IDE 视觉降噪 (Visual Noise Reduction)
在 Web IDE 层面通过 UI/UX 设计,将显式 SDK 调用代码“隐形”或“弱化”。
- **幽灵文本 (Ghost Text)**:将检测到的 SDK 调用行渲染为低对比度颜色如浅灰色opacity: 0.5),使视线自然聚焦于算法逻辑。
- **代码折叠 (Code Folding)**
- 提供“专注模式”开关,一键折叠所有 SDK 调用行。
- 在行号区域标记 SDK 调用,鼠标悬停时才高亮显示。
- **分离视图 (Split View) [可选]**
- **算法视图**:仅显示纯算法逻辑(隐藏 SDK 调用)。
- **完整视图**:显示包含 Tracer 调用的完整代码,供调试使用。
## 4. 结论
不应为了消除噪音而发明一套蹩脚的封装 API。正确的路径是
1. **能隐式则隐式**JS/Py/C++ Proxy
2. **不能隐式则显式**Java/C 原生操作)。
3. **显式噪音交给 IDE 处理**(变灰/折叠)。
这种策略既保留了代码的“可编程性”和“原生手感”,又解决了视觉干扰问题。

View File

@@ -0,0 +1,109 @@
# Structrail 系统架构设计与技术选型
本文档总结了 Structrail 平台的技术架构决策,包括 Monorepo 策略、服务拆分原则以及前后端架构方案的对比分析。
## 1. 总体架构策略Monorepo (单体仓库)
考虑到 Structrail 项目涉及多语言 SDK、统一的协议定义、前端可视化组件以及后端执行服务我们决定采用 **Monorepo** 架构。
### 核心收益
1. **单一事实来源 (Single Source of Truth)**:协议定义 (`@structrail/protocol`) 作为核心资产被前端、后端、SDK 共同引用。协议变更时,所有依赖方均可即时感知(类型检查报错),避免版本割裂。
2. **原子化提交 (Atomic Commits)**:由于协议变更往往涉及多端修改(如 ArrayTracer 新增指令 -> 前端渲染逻辑更新 -> SDK 实现更新Monorepo 允许在一个 Commit 中完成所有相关修改,保证系统一致性。
3. **统一版本管理**:便于统一管理多语言 SDK 的版本发布节奏。
4. **开发体验**:利用 `pnpm workspace``Turborepo` 等工具,实现高效的依赖管理和增量构建。
## 2. 服务架构设计
Structrail 的业务特性决定了其架构必须采用 **动静分离** 的策略,将轻量级的业务逻辑与重量级的代码执行隔离。
### 2.1 核心服务拆分
| 服务模块 | 职责描述 | 技术特征 |
| :--- | :--- | :--- |
| **Web (业务层)** | 用户界面、题目管理、社区互动、鉴权 | I/O 密集型,重交互,适合快速开发 |
| **API (接口层)** | 业务逻辑处理、数据转发、RPC 服务 | 高并发,低延迟,连接 Web 与 Runner |
| **Runner (执行层)** | 代码编译、沙箱运行、Trace 数据生成 | CPU 密集型,高风险,需独立部署与资源隔离 |
| **Protocol (共享层)** | 核心协议定义、类型声明、常量 | 纯代码库,无运行时依赖 |
### 2.2 架构方案对比
针对 Web 与 API 的实现,我们探讨了两种主流方案。两种方案均可行,且在 Monorepo 下都能实现 **100% 的端到端类型安全**
#### 方案 ANext.js 全栈架构 (SSR 优先)
* **架构描述**Web 与 API 合二为一,直接在 Next.js 的 Server Actions / Route Handlers 中处理业务逻辑,并调用 Runner 服务。
* **优势**
* **开发效率极致**:无 API 胶水层,前后端代码在同一文件中,调用后端函数像调用本地函数一样自然。
* **SSR 支持**:对 SEO 友好,首屏加载快(适合题目详情页、文档页)。
* **生态丰富**Vercel/Next.js 生态拥有大量现成组件。
* **劣势**
* **部署绑定**:较强依赖 Node.js Runtime 或 Vercel 平台。
* **边界模糊**Server Actions 可能导致前后端代码耦合,心智负担较重。
#### 方案 BReact (SPA) + Hono (API) 前后端分离 (CSR + Edge 优先)
* **架构描述**
* **Web**: 纯 React SPA通过 CDN 分发。
* **API**: 独立 Hono 服务,提供 RPC 接口。
* **通信**: 通过 `hono/client` 实现类型安全的 RPC 调用。
* **优势**
* **物理边界清晰**:前端关注 UI 交互,后端关注数据处理,职责分明。
* **部署极其灵活**前端可部署至任何静态托管OSS/Netlify后端可部署至 EdgeCloudflare Workers/Deno或容器。
* **高性能**Hono 基于 Web Standards冷启动快资源占用极低。
* **类型安全**:通过 Monorepo 导出 API 类型 (`AppType`),前端直接引用,实现与 tRPC 类似的开发体验。
* **劣势**
* **SEO 略弱**:纯 SPA 对 SEO 不如 SSR 友好(虽然可以通过预渲染解决)。
* **初期搭建成本**:需配置两个独立应用及通信链路。
### 2.3 结论与推荐
**推荐采用 Monorepo 架构,并根据团队偏好选择方案 A 或 B。**
* 如果更看重 **SEO****快速验证原型**,推荐 **方案 A (Next.js)**
* 如果更看重 **架构清晰度**、**部署灵活性 (Edge)** 和 **前后端解耦**,推荐 **方案 B (React + Hono)**
* *注:考虑到 Structrail 的编辑器交互极其复杂(重客户端逻辑),且 Runner 服务天然适合独立部署,**方案 B** 在长期维护和扩展性上可能更具优势。*
## 3. 建议的项目目录结构
无论选择哪种方案Monorepo 的基础结构应保持一致:
```text
structrail/
├── apps/ # 应用程序(业务层)
│ ├── web/ # [React/Next.js] 平台前端
│ │ └── ... (Visualizer 组件调用)
│ ├── api/ # [Hono/Node] 业务后端 (如果是方案 B)
│ ├── runner/ # [Go/Rust] 代码执行沙箱服务
│ └── docs/ # [VitePress] 文档站点
├── packages/ # 共享库(核心资产)
│ ├── protocol/ # 核心协议定义 (JSON Schema, TS Interfaces)
│ │ ├── index.ts # 导出 Tracer 类型、指令定义
│ │ └── schema.json # 用于校验 Trace 数据的 Schema
│ ├── sdk-ts/ # TypeScript SDK 实现
│ ├── ui/ # 通用 UI 组件库 (可选)
│ └── eslint-config/ # 统一的代码规范配置
├── sdks/ # 多语言 SDK (非 JS/TS 生态)
│ ├── c/ # C 语言 SDK (Makefile)
│ ├── python/ # Python SDK (Poetry)
│ ├── java/ # Java SDK (Maven/Gradle)
│ └── ...
├── tools/ # 工程化脚本
│ └── scripts/ # 批量发布、协议生成脚本
├── package.json # Root package.json
├── pnpm-workspace.yaml # pnpm workspace 配置
└── turbo.json # Turborepo 构建编排配置
```
## 4. 关键技术栈建议
* **包管理器与运行时**: `Bun` (All-in-One 工具链,提供极致的安装速度和高性能运行时)
* 作为包管理器替代 `npm/pnpm`
* 作为脚本执行器替代 `ts-node`
* 作为测试运行器替代 `Jest/Vitest`
* **构建系统**: `Turborepo` (任务编排、远程缓存)
* **前端框架**: `React` (配合 Vite)
* **后端框架**: `Hono` (完美适配 Bun 运行时,性能卓越)
* **Runner 语言**: `Go``Rust` (高性能、并发强、安全性好)
* **API 通信**: `Hono RPC` (如果分离) 或 `Server Actions` (如果全栈)

View File

@@ -0,0 +1,94 @@
# 前端可视化库设计方案 (`@structrail/viz`)
## 1. 核心目标
- **解耦**:将 Tracer SDK数据生成与前端渲染逻辑数据展示完全分离。
- **复用**:打造一个通用的、可嵌入的算法可视化库,服务于 StructRail 平台及第三方场景博客、文档、IDE 插件)。
- **标准**:作为 Tracer Protocol 的标准消费者,建立可视化渲染的事实标准。
## 2. 架构设计:确定性状态机 (Deterministic State Machine)
采用 **Player + Store + Renderer** 的分层架构确保时间旅行Time Travel的可靠性。
### 2.1 Player (播放器/控制器)
- **职责**:解析 JSON 指令流控制时间轴Play, Pause, Seek, Speed
- **特性**
- 维护当前帧索引 `currentIndex`
- 支持步进Step和连续播放。
- 处理“自动暂停”指令(如 `tracer.wait()`)。
### 2.2 Store (状态仓库/沙盒)
- **职责**维护“影子内存”Shadow Memory根据指令计算数据结构状态。
- **机制**
- **增量计算**:基于 immer.js 或类似机制只存储指令序列和初始状态通过重放Replay或关键帧Keyframe技术快速计算任意时刻的状态。
- **快照 (Snapshot)**:向渲染层提供只读的、标准化的数据快照。
- **State(t) = Apply(InitialState, Events[0...t])**
### 2.3 Renderer (渲染器/组件库)
- **职责**:纯 UI 展示层,遵循 `UI = Render(State)` 原则。
- **实现**
- **DOM/SVG 渲染器**:用于常规数据结构(数组、链表、树),支持 CSS 动画和高质量文本渲染。
- **Canvas/WebGL 渲染器**:用于大规模数据(如 10w+ 节点的图、矩阵热力图)。
- **组件化**:提供 `<ArrayVisualizer>`, `<GraphVisualizer>` 等独立组件。
## 3. 关键技术挑战与策略 (Advanced Technical Considerations)
为了确保该库能适应复杂的互联网环境(移动端、嵌入式、高性能场景),需重点关注以下方面:
### 3.1 响应式与移动端适配 (Responsive & Mobile First)
- **自适应布局**Renderer 需具备流式布局能力。例如 `ArrayVisualizer` 在窄屏(手机/VS Code 侧边栏)下应自动切换为“折行显示”或“垂直列表模式”,避免横向滚动。
- **触控交互**:设计移动端友好的交互模式(如长按代替 Hover双指缩放代替滚轮
### 3.2 样式隔离与嵌入性 (Style Isolation)
- **Shadow DOM**:推荐使用 Web Components (Shadow DOM) 封装渲染器,彻底隔离宿主页面(如博客全局 CSS的样式干扰。
- **CSS Modules / CSS-in-JS**:作为备选方案,确保类名哈希化,防止污染宿主环境。
### 3.3 性能降级与 LOD (Level of Detail)
- **自动后端切换**:根据数据规模动态选择渲染后端。
- 节点 < 500使用 SVG交互性好调试方便
- 节点 > 500自动降级为 Canvas/WebGL高性能
- **LOD 策略**:在缩放或快速播放时,自动隐藏非关键细节(如节点文本、阴影),保证渲染帧率。
### 3.4 状态序列化与分享 (Serialization)
- **State Export**:支持将当前 Store 的状态快照导出为 JSON。
- **Deep Link**:支持将状态编码为 URL 参数(如 `?state=base64...`),实现“分享当前步骤”功能。
### 3.5 插件系统与扩展性 (Plugin System)
- **Renderer Provider**:设计开放的注册接口,允许第三方开发者注册自定义渲染器。
```typescript
// 允许用户注册自定义渲染器,支持“主题市场”商业化
VizRegistry.register('GraphTracer', CyberpunkGraphRenderer);
```
- **中间件机制**:允许拦截和修改指令流,实现自定义的逻辑增强(如增加声音音效)。
## 4. 预期形态
该库将发布为 NPM 包,提供如下使用方式:
```typescript
import { Player, ArrayVisualizer } from '@structrail/viz';
import '@structrail/viz/dist/style.css'; // 或自动注入 Shadow DOM 样式
// 1. 初始化播放器
const player = new Player(events);
// 2. 渲染组件 (React 示例)
function App() {
const snapshot = usePlayerSnapshot(player);
return (
<div className="viz-container">
<ArrayVisualizer
model={snapshot.tracers['array-1']}
theme="cyberpunk" // 支持主题切换
/>
<Controls player={player} />
</div>
);
}
```
## 5. 商业化结合点
- **开源核心**:建立协议标准,获取流量。
- **付费扩展**
- **高级主题包**:赛博朋克、手绘风、企业定制皮肤。
- **高性能渲染器**3D 图算法渲染、大数据分析引擎。
- **云端服务**:高清视频导出 (MP4/GIF)。

View File

@@ -0,0 +1,12 @@
# 开发规则
- 在设计协议和API时我们需要考虑API的移植性尤其需要特别关注C语言因为C语言的语法表达力不算强。当然各类主流的编程语言都需要纳入考虑范围包括但不限于
- C++
- Java
- C#
- Kotlin
- Python
- Rust
- Go
- Swift
- Dart

View File

@@ -6,7 +6,7 @@
基于上述设想,我肯定无法接受从编译技术的角度去适配每一种编程语言(例如代码插桩甚至改造编译器),因为这会导致平台的开发变得非常复杂,维护成本也会非常高。因此我的想法是设计一套语言无关的协议,用来描述各种数据结构的变化(跟踪器),因此这套协议会定义需要支持的数据结构类型,以及每一种数据结构类型需要支持的操作指令,并且我倾向于将指令设计得更加“底层”一些,类似于“原语”的概念。
> 例如针对顺序表结构,我可能会定义 pick(获取元素)、drop(取消获取)、patch(修改元素) 指令来替代 swap(交换元素) 操作,因为交换两个元素的本质就是 获取元素 + 修改元素,而我在其中添加 drop 指令的目的则是使可视化过程更加具体,例如 pick 指令会将其选定的元素高亮,那么 drop 指令就可以取消该元素的高亮行为。
> 例如针对顺序表结构我可能会定义pick(获取元素)、drop(取消获取)、patch(修改元素)指令来替代swap(交换元素)操作,因为交换两个元素的本质就是获取元素+修改元素而我在其中添加rop指令的目的则是使可视化过程更加具体例如pick指令会将其选定的元素高亮那么drop指令就可以取消该元素的高亮行为。
我们会先选取一种编程语言(例如TypeScript)来实现这套协议,在实现的过程中,需要考虑到未来将添加其他编程语言的支持,因此需要考虑到不同编程语言之间的差异,例如语法/类型系统差异,进而反过来优化这套协议,以使其能够更好地支持不同的编程语言,这是一个双向的过程。

View File

@@ -12,8 +12,5 @@ Tracer 代表一个数据结构变化的跟踪器,用户可以通过调用 Tra
- LinkTracer: 链表
- TreeTracer: 树
- GraphTracer: 图
---
- LogTracer: 日志
- ControlTracer: 控制

View File

@@ -1,30 +1,113 @@
import type { TracerCommand } from '../types';
const createTracerContext = () => {
const commands: TracerCommand[] = [];
class ScopeError extends Error {
constructor(message?: string) {
super(message);
this.name = 'ScopeError';
}
}
if (typeof process !== 'undefined' && typeof process.on === 'function') {
process.on('exit', () => {
if (commands.length > 0) {
console.log(commands);
}
});
const SCOPE_STATE = {
INITIAL: 'initial',
SCOPING: 'scoping',
SCOPED: 'scoped',
} as const;
type ScopeState = (typeof SCOPE_STATE)[keyof typeof SCOPE_STATE];
type Error = {
stack?: string;
};
type ScopeResult = {
// 记录指令序列
commands: TracerCommand[];
// 记录异常信息
exception: Error;
// 检查scope的执行状态
state: ScopeState;
};
const createTracerContext = () => {
const scopeResult: ScopeResult = {
commands: [],
exception: {},
state: SCOPE_STATE.INITIAL,
};
const command = (command: TracerCommand) => {
scopeResult.commands.push(command);
};
// TODO: 输出指令序列和错误信息
const flush = () => {
const { commands, exception } = scopeResult;
if (commands.length > 0 || !!exception.stack) {
console.log(JSON.stringify({ commands, exception }, null, 2));
}
scopeResult.commands = [];
scopeResult.exception = {};
};
const getTracerContext = () => {
const command = (command: TracerCommand) => {
commands.push(command);
return {
command,
flush,
};
};
return {
commands,
command,
};
// 由于JavaScript/TypeScript在语言层面缺乏统一的“程序退出钩子”机制
// 所以我们无法在算法执行结束后自动地输出指令序列和异常信息,
// 尽管像Node.js这样的运行时提供了process.on('exit')但是我们希望保持SDK的环境无关性
// 所以为了不依赖于特定运行时的API我们设计了scope方法来创建一个显式的生命周期
// 算法逻辑将会被一个回调函数包裹作为routine参数
// 在routine执行完毕后scope会向外输出指令序列和异常信息。
const scope = (routine: () => void | Promise<void>) => {
if (scopeResult.state === SCOPE_STATE.SCOPED) {
throw new ScopeError('ScopeError: Detect multiple scope.');
}
if (scopeResult.state === SCOPE_STATE.SCOPING) {
throw new ScopeError('ScopeError: Detect nested scope.');
}
scopeResult.state = SCOPE_STATE.SCOPING;
// 如果routine是同步函数那可能会抛出同步错误所以需要用try-catch包裹
try {
const result = routine();
// 如果routine是异步函数需要用catch捕获异步错误
if (result instanceof Promise) {
result
.then(() => {
scopeResult.state = SCOPE_STATE.SCOPED;
flush();
})
.catch((error) => {
// 如果是ScopeError需要抛出否则会在嵌套调用scope时被外层scope捕获
if (error instanceof ScopeError) {
throw error;
}
scopeResult.exception.stack = (error as Error).stack;
scopeResult.state = SCOPE_STATE.SCOPED;
flush();
});
} else {
// 如果routine是同步函数执行完成后需要设置scope状态
scopeResult.state = SCOPE_STATE.SCOPED;
flush();
}
} catch (error) {
if (error instanceof ScopeError) {
throw error;
}
scopeResult.exception.stack = (error as Error).stack;
scopeResult.state = SCOPE_STATE.SCOPED;
flush();
}
};
return {
getTracerContext,
scope,
};
};
export const { getTracerContext } = createTracerContext();
export const { getTracerContext, scope } = createTracerContext();

View File

@@ -9,7 +9,12 @@ const controlTracer = createControlTracer({ description: 'ControlTracer' });
const arrayTracer = createArrayTracer({
description: 'ArrayTracer',
array: [1, 2, 3],
// array: [1, 2, 3],
walker: (commit) => {
commit(1);
commit(2);
commit(3);
},
});
arrayTracer.patch(0, 100);

View File

@@ -1,27 +1,51 @@
import { getTracerContext } from '../context';
import type { JsonValue } from '../types';
interface ArrayTracerCreateOptions<T extends JsonValue[]> {
interface ArrayTracerCreateOptions<T extends JsonValue> {
description?: string;
array?: T;
initial?: T[];
walker?: (builder: { add: (item: T) => void }) => void;
}
export const createArrayTracer = <T extends JsonValue[]>(
type ArrayTracerMetadata = {
// initial: JsonValue[];
length: number;
};
export const createArrayTracer = <T extends JsonValue = JsonValue>(
options: ArrayTracerCreateOptions<T>,
) => {
const { description = 'ArrayTracer', array } = options;
const { description, initial, walker } = options;
const tracer = crypto.randomUUID();
// 优化:仅维护数组长度作为影子状态,这在 C++/Java 等强类型语言中也极易实现(仅需一个 int 变量)
// 这种“最小必要状态”策略既能实现越界校验,又避免了在强类型语言中处理泛型存储的复杂性,且内存开销极低。
let arrayLength = array ? array.length : 0;
const metadata: ArrayTracerMetadata = {
length: 0,
};
const buildInitial = () => {
if (!!initial) {
return [...initial];
}
if (!!walker) {
const initial: T[] = [];
walker({
add: (item) => {
initial.push(item);
},
});
return initial;
}
return [];
};
// console.log(_initial);
const { command } = getTracerContext();
const validateIndex = (index: number) => {
if (index < 0 || index >= arrayLength) {
if (index < 0 || index >= metadata.length) {
throw new Error(
`[ArrayTracer] Index out of bounds: index ${index} is not within [0, ${arrayLength})`,
`ArrayTracer: Index out of bounds: index ${index} is not within [0, ${metadata.length})`,
);
}
};
@@ -30,18 +54,18 @@ export const createArrayTracer = <T extends JsonValue[]>(
type: 'ArrayTracer',
tracer: tracer,
action: 'create',
params: {
description: description,
array: array,
payload: {
description: description ?? 'ArrayTracer',
initial: buildInitial(),
},
});
// size 为正时,数组长度增加;为负时,数组长度减少(但不能小于 0
const scale = (size: number) => {
arrayLength += size;
if (arrayLength < 0) {
metadata.length += size;
if (metadata.length < 0) {
throw new Error(
`[ArrayTracer] Invalid size: ${size}, array length cannot be negative`,
`ArrayTracer: Invalid size: ${size}, array length cannot be negative`,
);
}
@@ -49,7 +73,7 @@ export const createArrayTracer = <T extends JsonValue[]>(
type: 'ArrayTracer',
tracer: tracer,
action: 'scale',
params: {
payload: {
size: size,
},
});
@@ -62,7 +86,7 @@ export const createArrayTracer = <T extends JsonValue[]>(
type: 'ArrayTracer',
tracer: tracer,
action: 'pick',
params: {
payload: {
index: index,
},
});
@@ -75,20 +99,20 @@ export const createArrayTracer = <T extends JsonValue[]>(
type: 'ArrayTracer',
tracer: tracer,
action: 'drop',
params: {
payload: {
index: index,
},
});
};
const patch = (index: number, value: T[number]) => {
const patch = (index: number, value: T) => {
validateIndex(index);
command({
type: 'ArrayTracer',
tracer: tracer,
action: 'patch',
params: {
payload: {
index: index,
value: value,
},
@@ -102,7 +126,7 @@ export const createArrayTracer = <T extends JsonValue[]>(
type: 'ArrayTracer',
tracer: tracer,
action: 'unset',
params: {
payload: {
index: index,
},
});

View File

@@ -0,0 +1,33 @@
import { getTracerContext } from '../context';
import type { GraphTracerGraph } from '../types';
interface GraphTracerCreateOptions {
description?: string;
graph?: GraphTracerGraph;
}
// 不要了,改为 walker/commit 方案
// TODO: 后续我们会添加创建图的辅助函数
// export const createGraphTracerHelper = () => {};
export const createGraphTracer = (options: GraphTracerCreateOptions) => {
const { description, graph } = options;
const tracer = crypto.randomUUID();
const { command } = getTracerContext();
command({
type: 'GraphTracer',
tracer: tracer,
action: 'create',
params: {
description: description ?? 'GraphTracer',
graph: graph ?? {
directed: false,
weighted: false,
nodes: [],
edges: [],
},
},
});
};

View File

@@ -1,3 +1,4 @@
export * from './array-tracer';
export * from './control-tracer';
export * from './graph-tracer';
export * from './log-tracer';

View File

@@ -6,36 +6,36 @@ type BaseArrayTracerCommand = BaseTracerCommand & {
type ArrayTracerCreateCommand = BaseArrayTracerCommand & {
action: 'create';
params: {
payload: {
description: string;
array?: JsonValue[];
initial: JsonValue[];
};
};
type ArrayTracerScaleCommand = BaseArrayTracerCommand & {
action: 'scale';
params: {
payload: {
size: number;
};
};
type ArrayTracerPickCommand = BaseArrayTracerCommand & {
action: 'pick';
params: {
payload: {
index: number;
};
};
type ArrayTracerDropCommand = BaseArrayTracerCommand & {
action: 'drop';
params: {
payload: {
index: number;
};
};
type ArrayTracerPatchCommand = BaseArrayTracerCommand & {
action: 'patch';
params: {
payload: {
index: number;
value: JsonValue;
};
@@ -43,7 +43,7 @@ type ArrayTracerPatchCommand = BaseArrayTracerCommand & {
type ArrayTracerUnsetCommand = BaseArrayTracerCommand & {
action: 'unset';
params: {
payload: {
index: number;
};
};

View File

@@ -1,8 +1,10 @@
import type { ArrayTracerCommand } from './array-tracer';
import type { ControlTracerCommand } from './control-tracer';
import type { GraphTracerCommand } from './graph-tracer';
import type { LogTracerCommand } from './log-tracer';
export type TracerCommand =
| ArrayTracerCommand
| LogTracerCommand
| ControlTracerCommand;
| ControlTracerCommand
| ArrayTracerCommand
| GraphTracerCommand;

View File

@@ -6,7 +6,7 @@ export type JsonValue =
| JsonValue[]
| { [key: string]: JsonValue };
export type TracerType = 'ArrayTracer' | 'LogTracer' | 'ControlTracer';
export type TracerType = 'LogTracer' | 'ControlTracer' | 'ArrayTracer' | 'GraphTracer';
export type TracerId = ReturnType<typeof crypto.randomUUID>;

View File

@@ -0,0 +1,94 @@
import type { BaseTracerCommand, JsonValue } from './common';
export type GraphTracerGraphNode = {
id: string;
value: JsonValue;
};
export type GraphTracerGraphEdge = {
source: string;
target: string;
weight: JsonValue;
};
export type GraphTracerGraph = {
directed: boolean;
weighted: boolean;
nodes: GraphTracerGraphNode[];
edges: GraphTracerGraphEdge[];
};
type BaseGraphTracerCommand = BaseTracerCommand & {
type: 'GraphTracer';
};
type GraphTracerCreateCommand = BaseGraphTracerCommand & {
action: 'create';
params: {
description: string;
graph: GraphTracerGraph;
};
};
type GraphTracerInsertCommand = BaseGraphTracerCommand & {
action: 'insert';
params: {};
};
type GraphTracerRemoveCommand = BaseGraphTracerCommand & {
action: 'remove';
params: {};
};
type GraphTracerUpdateCommand = BaseGraphTracerCommand & {
action: 'update';
params: {};
};
type GraphTracerConnectCommand = BaseGraphTracerCommand & {
action: 'connect';
params: {};
};
type GraphTracerDisconnectCommand = BaseGraphTracerCommand & {
action: 'disconnect';
params: {};
};
type GraphTracerWeightCommand = BaseGraphTracerCommand & {
action: 'weight';
params: {};
};
type GraphTracerVisitCommand = BaseGraphTracerCommand & {
action: 'visit';
params: {};
};
type GraphTracerLeaveCommand = BaseGraphTracerCommand & {
action: 'leave';
params: {};
};
type GraphTracerPickCommand = BaseGraphTracerCommand & {
action: 'pick';
params: {};
};
type GraphTracerDropCommand = BaseGraphTracerCommand & {
action: 'drop';
params: {};
};
export type GraphTracerCommand =
| GraphTracerCreateCommand
| GraphTracerInsertCommand
| GraphTracerRemoveCommand
| GraphTracerUpdateCommand
| GraphTracerConnectCommand
| GraphTracerDisconnectCommand
| GraphTracerWeightCommand
| GraphTracerVisitCommand
| GraphTracerLeaveCommand
| GraphTracerPickCommand
| GraphTracerDropCommand;

View File

@@ -2,4 +2,5 @@ export * from './array-tracer';
export * from './command';
export * from './common';
export * from './control-tracer';
export * from './graph-tracer';
export * from './log-tracer';