weft-ai-language
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeft AI Language
Weft AI 语言
Skill by ara.so — Daily 2026 Skills collection.
Weft is a programming language (implemented in Rust) for AI systems where LLMs, humans, APIs, databases, and agents are base language primitives. You wire nodes together, the compiler type-checks every connection, and the program runs with durable execution backed by Restate (survives crashes, supports multi-day human-in-the-loop pauses). A visual graph view is generated automatically from code.
由ara.so提供的技能 — 2026每日技能合集。
Weft是一款基于Rust实现的AI系统编程语言,其中LLM、人类、API、数据库和Agent都是语言的基础原语。你可以将节点连接在一起,编译器会检查每一个连接的类型,程序依托Restate实现持久化执行(可在崩溃后恢复,支持多日的人机交互暂停)。代码会自动生成可视化图形视图。
Installation & Setup
安装与配置
Prerequisites
前置要求
- Docker (for PostgreSQL)
- Node.js
- macOS: (Bash 4+ required)
brew install bash - Rust, Restate, and pnpm are auto-installed by
dev.sh
- Docker(用于PostgreSQL)
- Node.js
- macOS:(需Bash 4及以上版本)
brew install bash - Rust、Restate和pnpm会由自动安装
dev.sh
Clone and Configure
克隆与配置
bash
git clone https://github.com/WeaveMindAI/weft.git
cd weft
cp .env.example .envbash
git clone https://github.com/WeaveMindAI/weft.git
cd weft
cp .env.example .envEdit .env — add your API keys
编辑.env — 添加你的API密钥
undefinedundefinedEnvironment Variables (.env
)
.env环境变量(.env
)
.envbash
OPENROUTER_API_KEY= # Required for LLM nodes
TAVILY_API_KEY= # Required for Web Search nodes
ELEVENLABS_API_KEY= # Required for Speech-to-Text nodes
APOLLO_API_KEY= # Required for Apollo enrichment nodes
DISCORD_BOT_TOKEN= # Required for Discord nodesAll keys are optional at startup — missing keys surface as runtime errors only when the relevant node executes.
bash
OPENROUTER_API_KEY= # LLM节点必填
TAVILY_API_KEY= # 网页搜索节点必填
ELEVENLABS_API_KEY= # 语音转文本节点必填
APOLLO_API_KEY= # Apollo增强节点必填
DISCORD_BOT_TOKEN= # Discord节点必填所有密钥在启动时均为可选——仅当相关节点执行时,缺失的密钥才会触发运行时错误。
Start Development
启动开发环境
bash
undefinedbash
undefinedTerminal 1 — backend (PostgreSQL, Restate, all services)
终端1 — 后端服务(PostgreSQL、Restate及所有服务)
./dev.sh server
./dev.sh server
Terminal 2 — dashboard (SvelteKit at http://localhost:5173)
终端2 — 控制面板(SvelteKit,地址为http://localhost:5173)
./dev.sh dashboard
./dev.sh dashboard
Or both at once
或者一次性启动所有服务
./dev.sh all
undefined./dev.sh all
undefinedVS Code
VS Code
Use the Dev Local All task to start server + dashboard in split terminals.
使用Dev Local All任务可在拆分终端中同时启动服务器和控制面板。
Development Commands
开发命令
bash
./dev.sh server # Start backend services
./dev.sh dashboard # Start frontend
./dev.sh all # Start everything
./dev.sh extension # Build browser extension
./cleanup.sh # Stop everything, wipe Restate + DB
./cleanup.sh --no-db # Stop services, keep database
./cleanup.sh --services # Stop services only
./cleanup.sh --db-destroy # Remove PostgreSQL container entirely
cargo build # Build without running PostgreSQL (uses .sqlx snapshots)
cargo test # Test without running PostgreSQLbash
./dev.sh server # 启动后端服务
./dev.sh dashboard # 启动前端
./dev.sh all # 启动所有服务
./dev.sh extension # 构建浏览器扩展
./cleanup.sh # 停止所有服务,清空Restate与数据库
./cleanup.sh --no-db # 停止服务,保留数据库
./cleanup.sh --services # 仅停止服务
./cleanup.sh --db-destroy # 彻底移除PostgreSQL容器
cargo build # 构建项目,无需运行PostgreSQL(使用.sqlx快照)
cargo test # 测试项目,无需运行PostgreSQLInfrastructure Nodes (Kubernetes)
基础设施节点(Kubernetes)
Only needed if using nodes like Postgres Database that provision K8s resources:
bash
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-$(uname -s | tr '[:upper:]' '[:lower:]')-amd64
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind
INFRASTRUCTURE_TARGET=local ./dev.sh server仅在使用Postgres Database等需要部署K8s资源的节点时需要:
bash
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-$(uname -s | tr '[:upper:]' '[:lower:]')-amd64
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind
INFRASTRUCTURE_TARGET=local ./dev.sh serverThe Weft Language
Weft语言
Core Concepts
核心概念
- Nodes — typed computational units (LLM, HTTP, Human Query, Gate, etc.)
- Connections — typed edges between node ports; compiler validates all types
- Groups — collapse any set of nodes into a single reusable node
- Durable execution — programs checkpoint via Restate; long pauses are transparent
- 节点 — 类型化计算单元(LLM、HTTP、人工查询、网关等)
- 连接 — 节点端口间的类型化连接;编译器会验证所有类型
- 组 — 将任意节点集合并为单个可复用节点
- 持久化执行 — 程序通过Restate创建检查点;长时间暂停对程序透明
Node Syntax
节点语法
weft
node_name = NodeType -> (output_port: OutputType) {
label: "Human-readable name"
config_key: "value"
}
node_name.input_port = other_node.output_portweft
node_name = NodeType -> (output_port: OutputType) {
label: "人类可读名称"
config_key: "value"
}
node_name.input_port = other_node.output_portSimple Example — Poem Generator
简单示例 — 诗歌生成器
weft
undefinedweft
undefinedProject: Poem Generator
项目:诗歌生成器
Description: Writes a short poem about any topic
描述:针对任意主题创作短诗
topic = Text {
label: "Topic"
value: "the silence between stars"
}
llm_config = LlmConfig {
label: "Config"
model: "anthropic/claude-sonnet-4.6"
systemPrompt: "Write a short, beautiful poem (4-6 lines) about the given topic."
temperature: "0.8"
}
poet = LlmInference -> (response: String) {
label: "Poet"
}
poet.prompt = topic.value
poet.config = llm_config.config
output = Debug { label: "Poem" }
output.data = poet.response
---topic = Text {
label: "主题"
value: "星辰间的寂静"
}
llm_config = LlmConfig {
label: "配置"
model: "anthropic/claude-sonnet-4.6"
systemPrompt: "针对给定主题创作一首简短优美的诗歌(4-6行)。"
temperature: "0.8"
}
poet = LlmInference -> (response: String) {
label: "诗人"
}
poet.prompt = topic.value
poet.config = llm_config.config
output = Debug { label: "诗歌" }
output.data = poet.response
---Built-in Node Catalog
内置节点目录
AI Nodes
AI节点
| Node | Purpose |
|---|---|
| Configure model, system prompt, temperature |
| Call an LLM, returns |
| 节点 | 用途 |
|---|---|
| 配置模型、系统提示词、温度参数 |
| 调用LLM,返回 |
Data Nodes
数据节点
| Node | Purpose |
|---|---|
| Static or dynamic text value |
| Numeric value |
| Key-value map |
| Ordered list |
| Bundle/unbundle multiple values |
| 节点 | 用途 |
|---|---|
| 静态或动态文本值 |
| 数值 |
| 键值对映射 |
| 有序列表 |
| 打包/解包多个值 |
Flow Nodes
流程节点
| Node | Purpose |
|---|---|
| Conditional branching |
| Pause execution, send form to human, resume on response |
| Start a program from a human action |
| 节点 | 用途 |
|---|---|
| 条件分支 |
| 暂停执行,向人类发送表单,收到响应后恢复 |
| 通过人类操作启动程序 |
Communication Nodes
通信节点
DiscordSlackTelegramWhatsAppEmailXDiscordSlackTelegramWhatsAppEmailXStorage Nodes
存储节点
PostgresMemoryPostgresMemoryEnrichment Nodes
增强节点
ApolloWebSearchSpeechToTextApolloWebSearchSpeechToTextTrigger Nodes
触发节点
CronCronUtility Nodes
工具节点
DebugTemplateHTTPCodeDebugTemplateHTTPCodeCommon Patterns
常见模式
Pattern 1 — LLM with Structured Config
模式1 — 带结构化配置的LLM
weft
undefinedweft
undefinedProject: Content Summarizer
项目:内容摘要器
Description: Summarizes a webpage given a URL
描述:针对给定URL的网页内容生成摘要
url_input = Text {
label: "URL"
value: "https://example.com/article"
}
search = WebSearch -> (results: String) {
label: "Fetch Content"
}
search.query = url_input.value
summarizer_config = LlmConfig {
label: "Summarizer Config"
model: "anthropic/claude-sonnet-4.6"
systemPrompt: "Summarize the following content in 3 bullet points."
temperature: "0.3"
}
summarizer = LlmInference -> (response: String) {
label: "Summarizer"
}
summarizer.prompt = search.results
summarizer.config = summarizer_config.config
output = Debug { label: "Summary" }
output.data = summarizer.response
undefinedurl_input = Text {
label: "URL"
value: "https://example.com/article"
}
search = WebSearch -> (results: String) {
label: "获取内容"
}
search.query = url_input.value
summarizer_config = LlmConfig {
label: "摘要器配置"
model: "anthropic/claude-sonnet-4.6"
systemPrompt: "将以下内容总结为3个要点。"
temperature: "0.3"
}
summarizer = LlmInference -> (response: String) {
label: "摘要器"
}
summarizer.prompt = search.results
summarizer.config = summarizer_config.config
output = Debug { label: "摘要" }
output.data = summarizer.response
undefinedPattern 2 — Human-in-the-Loop Approval
模式2 — 人机交互审批流程
weft
undefinedweft
undefinedProject: Content Approval Pipeline
项目:内容审批流水线
Description: AI drafts content, human approves before publishing
描述:AI生成内容草稿,经人类审批后发布
draft_config = LlmConfig {
label: "Drafter Config"
model: "openai/gpt-4o"
systemPrompt: "Write a Twitter thread about the given topic. Be engaging."
temperature: "0.7"
}
topic = Text {
label: "Topic"
value: "distributed systems"
}
drafter = LlmInference -> (response: String) {
label: "Content Drafter"
}
drafter.prompt = topic.value
drafter.config = draft_config.config
draft_config = LlmConfig {
label: "草稿生成配置"
model: "openai/gpt-4o"
systemPrompt: "针对给定主题创作Twitter推文,风格要吸引人。"
temperature: "0.7"
}
topic = Text {
label: "主题"
value: "分布式系统"
}
drafter = LlmInference -> (response: String) {
label: "内容草稿生成器"
}
drafter.prompt = topic.value
drafter.config = draft_config.config
Pauses execution indefinitely until a human responds
无限期暂停执行,直到人类响应
approval = HumanQuery -> (approved: Boolean, feedback: String) {
label: "Human Approval"
question: "Do you approve this draft for publishing?"
}
approval.content = drafter.response
gate = Gate -> (passed: String) {
label: "Approval Gate"
}
gate.condition = approval.approved
gate.value = drafter.response
publisher = Discord {
label: "Publish to Discord"
channel: "announcements"
}
publisher.message = gate.passed
undefinedapproval = HumanQuery -> (approved: Boolean, feedback: String) {
label: "人工审批"
question: "是否批准此草稿发布?"
}
approval.content = drafter.response
gate = Gate -> (passed: String) {
label: "审批网关"
}
gate.condition = approval.approved
gate.value = drafter.response
publisher = Discord {
label: "发布至Discord"
channel: "announcements"
}
publisher.message = gate.passed
undefinedPattern 3 — Conditional Branching with Gate
模式3 — 基于网关的条件分支
weft
undefinedweft
undefinedProject: Sentiment Router
项目:情感路由
Description: Routes messages based on sentiment analysis
描述:根据情感分析结果路由消息
message = Text {
label: "Input Message"
value: "This product is absolutely terrible!"
}
sentiment_config = LlmConfig {
label: "Sentiment Config"
model: "anthropic/claude-haiku-3.5"
systemPrompt: "Classify sentiment as 'positive' or 'negative'. Respond with one word only."
temperature: "0.0"
}
classifier = LlmInference -> (response: String) {
label: "Sentiment Classifier"
}
classifier.prompt = message.value
classifier.config = sentiment_config.config
is_negative = Gate -> (passed: String) {
label: "Is Negative?"
}
is_negative.condition = classifier.response
is_negative.value = message.value
alert = Slack {
label: "Alert Team"
channel: "customer-issues"
}
alert.message = is_negative.passed
undefinedmessage = Text {
label: "输入消息"
value: "这个产品简直糟透了!"
}
sentiment_config = LlmConfig {
label: "情感配置"
model: "anthropic/claude-haiku-3.5"
systemPrompt: "将情感分类为'positive'或'negative'。仅用一个单词回复。"
temperature: "0.0"
}
classifier = LlmInference -> (response: String) {
label: "情感分类器"
}
classifier.prompt = message.value
classifier.config = sentiment_config.config
is_negative = Gate -> (passed: String) {
label: "是否负面?"
}
is_negative.condition = classifier.response
is_negative.value = message.value
alert = Slack {
label: "通知团队"
channel: "customer-issues"
}
alert.message = is_negative.passed
undefinedPattern 4 — Cron-Triggered Pipeline
模式4 — Cron触发的流水线
weft
undefinedweft
undefinedProject: Daily Digest
项目:每日摘要
Description: Sends a daily news digest every morning
描述:每天早上发送AI与技术新闻摘要
schedule = Cron {
label: "Daily Trigger"
expression: "0 8 * * *"
}
news = WebSearch -> (results: String) {
label: "Fetch News"
}
news.query = "AI and technology news today"
digest_config = LlmConfig {
label: "Digest Config"
model: "openai/gpt-4o-mini"
systemPrompt: "Summarize these news items into a concise morning digest."
temperature: "0.4"
}
digest = LlmInference -> (response: String) {
label: "Digest Writer"
}
digest.prompt = news.results
digest.config = digest_config.config
send = Email {
label: "Send Digest"
to: "team@example.com"
subject: "Your Daily AI Digest"
}
send.body = digest.response
undefinedschedule = Cron {
label: "每日触发器"
expression: "0 8 * * *"
}
news = WebSearch -> (results: String) {
label: "获取新闻"
}
news.query = "今日AI与技术新闻"
digest_config = LlmConfig {
label: "摘要配置"
model: "openai/gpt-4o-mini"
systemPrompt: "将这些新闻条目总结为简洁的晨间摘要。"
temperature: "0.4"
}
digest = LlmInference -> (response: String) {
label: "摘要生成器"
}
digest.prompt = news.results
digest.config = digest_config.config
send = Email {
label: "发送摘要"
to: "team@example.com"
subject: "你的每日AI摘要"
}
send.body = digest.response
undefinedPattern 5 — Multi-Step Research Agent
模式5 — 多步骤研究Agent
weft
undefinedweft
undefinedProject: Research Agent
项目:研究Agent
Description: Researches a topic and produces a structured report
描述:研究指定主题并生成结构化报告
query = Text {
label: "Research Query"
value: "latest advances in protein folding"
}
search = WebSearch -> (results: String) {
label: "Search"
}
search.query = query.value
query = Text {
label: "研究查询"
value: "蛋白质折叠的最新进展"
}
search = WebSearch -> (results: String) {
label: "搜索"
}
search.query = query.value
Enrich with professional data
用专业数据增强内容
enrichment = Apollo -> (data: String) {
label: "Enrichment"
}
analyst_config = LlmConfig {
label: "Analyst Config"
model: "anthropic/claude-sonnet-4.6"
systemPrompt: "You are a research analyst. Given search results, produce a structured report with: Executive Summary, Key Findings, Implications, and Further Reading."
temperature: "0.2"
}
pack_inputs = Pack -> (bundle: Dict) {
label: "Combine Sources"
}
pack_inputs.search_results = search.results
analyst = LlmInference -> (response: String) {
label: "Research Analyst"
}
analyst.prompt = pack_inputs.bundle
analyst.config = analyst_config.config
store = Postgres {
label: "Store Report"
table: "research_reports"
}
store.data = analyst.response
notify = Slack {
label: "Notify Team"
channel: "research"
}
notify.message = analyst.response
---enrichment = Apollo -> (data: String) {
label: "数据增强"
}
analyst_config = LlmConfig {
label: "分析师配置"
model: "anthropic/claude-sonnet-4.6"
systemPrompt: "你是一名研究分析师。根据搜索结果,生成包含以下部分的结构化报告:执行摘要、关键发现、影响分析、进一步阅读。"
temperature: "0.2"
}
pack_inputs = Pack -> (bundle: Dict) {
label: "合并数据源"
}
pack_inputs.search_results = search.results
analyst = LlmInference -> (response: String) {
label: "研究分析师"
}
analyst.prompt = pack_inputs.bundle
analyst.config = analyst_config.config
store = Postgres {
label: "存储报告"
table: "research_reports"
}
store.data = analyst.response
notify = Slack {
label: "通知团队"
channel: "research"
}
notify.message = analyst.response
---Adding a Custom Node
添加自定义节点
New nodes are two files in the directory. No registration needed — the crate auto-discovers nodes at startup.
catalog/inventory新节点需在目录下创建两个文件,无需注册—— crate会在启动时自动发现节点。
catalog/inventoryStep 1 — Create the folder
步骤1 — 创建文件夹
catalog/
└── my_category/
└── my_node/
├── backend.rs
└── frontend.tscatalog/
└── my_category/
└── my_node/
├── backend.rs
└── frontend.tsStep 2 — Implement backend.rs
backend.rs步骤2 — 实现backend.rs
backend.rsrust
use weft_nodes::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct MyNodeConfig {
pub label: String,
pub my_setting: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MyNodeInputs {
pub text: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MyNodeOutputs {
pub result: String,
}
pub struct MyNode;
#[async_trait]
impl Node for MyNode {
type Config = MyNodeConfig;
type Inputs = MyNodeInputs;
type Outputs = MyNodeOutputs;
async fn run(
config: Self::Config,
inputs: Self::Inputs,
) -> Result<Self::Outputs, NodeError> {
let result = format!("{}: {}", config.my_setting, inputs.text);
Ok(MyNodeOutputs { result })
}
}rust
use weft_nodes::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct MyNodeConfig {
pub label: String,
pub my_setting: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MyNodeInputs {
pub text: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MyNodeOutputs {
pub result: String,
}
pub struct MyNode;
#[async_trait]
impl Node for MyNode {
type Config = MyNodeConfig;
type Inputs = MyNodeInputs;
type Outputs = MyNodeOutputs;
async fn run(
config: Self::Config,
inputs: Self::Inputs,
) -> Result<Self::Outputs, NodeError> {
let result = format!("{}: {}", config.my_setting, inputs.text);
Ok(MyNodeOutputs { result })
}
}Step 3 — Define frontend.ts
frontend.ts步骤3 — 定义frontend.ts
frontend.tstypescript
import type { NodeDefinition } from "@/types/nodes";
export const MyNode: NodeDefinition = {
type: "MyNode",
label: "My Node",
icon: "sparkles", // Lucide icon name
category: "my_category",
inputs: [
{ name: "text", type: "String", required: true },
],
outputs: [
{ name: "result", type: "String" },
],
config: [
{ name: "label", type: "string", default: "My Node" },
{ name: "my_setting", type: "string", default: "prefix" },
],
};After adding both files, run — the node is available immediately.
./dev.sh servertypescript
import type { NodeDefinition } from "@/types/nodes";
export const MyNode: NodeDefinition = {
type: "MyNode",
label: "My Node",
icon: "sparkles", // Lucide图标名称
category: "my_category",
inputs: [
{ name: "text", type: "String", required: true },
],
outputs: [
{ name: "result", type: "String" },
],
config: [
{ name: "label", type: "string", default: "My Node" },
{ name: "my_setting", type: "string", default: "prefix" },
],
};添加两个文件后,运行——节点会立即生效。
./dev.sh serverType System
类型系统
Weft has generics, unions, type variables, and null propagation.
| Type | Description |
|---|---|
| Text value |
| Numeric value |
| True/false |
| Key-value map |
| Ordered collection |
| Nullable type — null propagates through the graph |
| Union type |
The compiler validates every connection before execution. Type mismatches, missing required connections, and broken architecture are caught at compile time.
Weft支持泛型、联合类型、类型变量和空值传播。
| 类型 | 描述 |
|---|---|
| 文本值 |
| 数值 |
| 布尔值(真/假) |
| 键值对映射 |
| 有序集合 |
| 可空类型——空值会在图中传播 |
| 联合类型 |
编译器会在执行前验证所有连接。类型不匹配、缺失必要连接和架构问题都会在编译阶段被捕获。
Project Layout Reference
项目结构参考
weft/
├── catalog/ # Node definitions — source of truth
│ ├── ai/ # LlmConfig, LlmInference
│ ├── code/ # Python execution
│ ├── communication/ # Discord, Slack, Telegram, WhatsApp, Email, X
│ ├── data/ # Text, Number, Dict, List, Pack, Unpack
│ ├── enrichment/ # Apollo, WebSearch, SpeechToText
│ ├── flow/ # Gate, HumanQuery, HumanTrigger
│ ├── storage/ # Postgres, Memory
│ └── triggers/ # Cron, webhooks, polling
├── crates/
│ ├── weft-core/ # Type system, compiler, executor, Restate objects
│ ├── weft-nodes/ # Node trait, registry, sandbox, node runner
│ ├── weft-api/ # REST API (triggers, files, infra, usage)
│ └── weft-orchestrator/ # Restate services + Axum project executor
├── dashboard/ # Web UI (SvelteKit + Svelte 5)
├── extension/ # Browser extension for human-in-the-loop (WXT)
└── scripts/
└── catalog-link.sh # Symlinks catalog into crates + dashboardweft/
├── catalog/ # 节点定义——事实来源
│ ├── ai/ # LlmConfig、LlmInference
│ ├── code/ # Python执行
│ ├── communication/ # Discord、Slack、Telegram、WhatsApp、Email、X
│ ├── data/ # Text、Number、Dict、List、Pack、Unpack
│ ├── enrichment/ # Apollo、WebSearch、SpeechToText
│ ├── flow/ # Gate、HumanQuery、HumanTrigger
│ ├── storage/ # Postgres、Memory
│ └── triggers/ # Cron、Webhook、轮询
├── crates/
│ ├── weft-core/ # 类型系统、编译器、执行器、Restate对象
│ ├── weft-nodes/ # 节点 trait、注册表、沙箱、节点运行器
│ ├── weft-api/ # REST API(触发器、文件、基础设施、使用统计)
│ └── weft-orchestrator/ # Restate服务 + Axum项目执行器
├── dashboard/ # Web UI(SvelteKit + Svelte 5)
├── extension/ # 人机交互浏览器扩展(WXT)
└── scripts/
└── catalog-link.sh # 将catalog链接到crates和dashboardTroubleshooting
故障排除
./dev.sh server
fails immediately
./dev.sh server./dev.sh server
立即失败
./dev.sh server- Ensure Docker is running ()
docker ps - Check that ports 5432 (Postgres), 8080 (Restate), and 9070 (Restate admin) are free
- Run then retry
./cleanup.sh
- 确保Docker正在运行(执行检查)
docker ps - 检查端口5432(Postgres)、8080(Restate)和9070(Restate管理端)是否空闲
- 运行后重试
./cleanup.sh
Node shows "API key missing" at runtime
节点在运行时显示“API密钥缺失”
- Add the required key to
.env - Restart the server ()
./cleanup.sh --services && ./dev.sh server
- 将所需密钥添加到文件中
.env - 重启服务器(执行)
./cleanup.sh --services && ./dev.sh server
Type mismatch compiler error
编译器报错类型不匹配
- Check that the output port type of the source node matches the input port type of the destination node
- Use to bundle multiple values into a
Packbefore passing to a node that expectsDictDict - Nullable types () can propagate null — use a
T?node to guard against null before consumingGate
- 检查源节点的输出端口类型是否与目标节点的输入端口类型匹配
- 使用将多个值打包为
Pack后,再传递给需要Dict类型的节点Dict - 可空类型()会传播空值——在使用前用
T?节点防范空值Gate
Restate state is stale after a crash
崩溃后Restate状态过期
bash
./cleanup.sh # Wipes Restate journal and DB, full resetbash
./cleanup.sh # 清空Restate日志和数据库,完全重置cargo build
fails without running Postgres
cargo build未运行Postgres时cargo build
失败
cargo buildThe directory is committed — offline mode is supported:
.sqlxbash
cargo build # Works without a running database
cargo test # Works without a running database.sqlxbash
cargo build # 无需运行数据库即可构建
cargo test # 无需运行数据库即可测试New node not appearing in dashboard
新节点未在控制面板中显示
- Confirm both and
backend.rsexist underfrontend.tscatalog/<category>/<node>/ - Run manually then restart the server
./scripts/catalog-link.sh - Check server logs for inventory discovery errors
- 确认和
backend.rs都存在于frontend.ts目录下catalog/<category>/<node>/ - 手动运行后重启服务器
./scripts/catalog-link.sh - 检查服务器日志中的节点发现错误
Key Resources
关键资源
- Documentation: https://weavemind.ai/docs
- Getting Started: https://weavemind.ai/docs/hello-world
- Language Reference: Nodes, Connections, Types, Groups, Parallel — all at https://weavemind.ai/docs
- Architecture: in the repo root
DESIGN.md - Roadmap: in the repo root
ROADMAP.md - Contributing: in the repo root
CONTRIBUTING.md - Community Discord: https://discord.com/invite/FGwNu6mDkU
- License: O'Saasy License (MIT + no competing hosted service) — https://osaasy.dev
- 文档: https://weavemind.ai/docs
- 快速入门: https://weavemind.ai/docs/hello-world
- 语言参考: 节点、连接、类型、组、并行等内容均在https://weavemind.ai/docs
- 架构: 仓库根目录下的
DESIGN.md - 路线图: 仓库根目录下的
ROADMAP.md - 贡献指南: 仓库根目录下的
CONTRIBUTING.md - 社区Discord: https://discord.com/invite/FGwNu6mDkU
- 许可证: O'Saasy许可证(MIT + 禁止竞争托管服务)—— https://osaasy.dev