Codync
免费开源的 1:1 Grok Bot 与 Muse 替代方案。可在 iPhone、Mac 或 Linux 桌面上将 Claude 代码、Codex、Cursor 以及 40 多个编码代理作为持久机器人使用。支持群组聊天、线程、应用。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Fa is a programming language designed for both AI agents and humans.
Agents get a language they can't get wrong without the compiler noticing: strict types, typed errors, requirements and mutations, clear diagnostics and an unambiguous grammar. Humans get code that reads almost like natural language, and that runs everywhere: web, server, native, WebAssembly.
Syntax-wise, Fa sits between Rust and TypeScript.
-- Load the score of the current user.
function loadScore = (): Integer throws ApiError requires session: Session => {
let response = try fetchScore(session.user.id)
response.score
}
Fa is in active development. Expect breaking changes.
Like Rust, Fa has no escape hatch: no any, no unchecked casts, no null surprises. If it compiles, it works.
An agent can rely on the compiler as its feedback loop instead of on runtime testing.
Fa brings the ideas of the Effect TypeScript library directly into the language, with no wrappers, generators or pipes to learn. Every function signature tells you everything it can do:
throws): there are no exceptions. Errors are values declared in the signature, and the compiler makes sure each one is either propagated with try or handled with catch.requires): dependencies are passed implicitly through the call stack, but they are part of the signature. Calling a function without providing what it requires is a compile error.mutates, invalidates): a function declares what it modifies, down to a field or an element, and which references it can invalidate.type ApiError = Errors {
NetworkError = { message: String }
TimeoutError = { duration: Integer }
}
type Session = {
user: { id: String, name: String }
}
function greet = () requires session: Session => {
console.log("Hello, {session.user.name}!")
}
function main = () throws ApiError => {
provide Session = { user = { id = "42", name = "Ada" } }
greet() -- the session is provided implicitly
-- `try` propagates the error if the call fails
let score = try loadScore()
-- `catch` handles it
let scoreOrZero = loadScore() catch error => 0
}
Diagnostics explain what went wrong, where, and how to fix it. They are written to be acted upon by a human or an agent without guesswork.
Every construct has a single meaning and, as much as possible, a single way to be written. There are few keywords, no context-dependent parsing and no hidden rules, which makes Fa easy to read and easy to generate.
Documentation is part of the language, not a convention on top of it. A comment written right above a declaration is its documentation: it is attached to the declaration and are available to the compiler, the language server and the tooling, so agents always find the documentation right next to the code they work on.
Fa favors words and simple operators over symbols. Code should read almost like a sentence:
for person in persons {
if person.age is 18 {
console.log("Welcome to adulthood, {person.name}!")
}
}
Fa is a universal language: write your code once, then compile it to JavaScript (browser, Bun, Node.js, Deno), native, WebAssembly or Rust source code.
The same code base can power your tooling, your applications and your games.
Fa has no garbage collector and no borrow checker, yet it is 100% memory-safe. It relies on two concepts.
When you reference an element of a collection, its type says where it is stored. The compiler tracks the operations that can move or remove elements, as precisely as it can: after one of them, the references it may have broken must be declared again before being used.
mutable persons: Array(Person) = [{ name = "Ana" }, { name = "Bao" }, { name = "Cleo" }]
use someone = persons[1] -- type: `Person in persons`
someone.name = "John" -- fine: modifying an element keeps the references valid
persons.pop() -- fine: `pop` only invalidates the last element
persons.push({ name = "Dan" }) -- `push` may reallocate the array: every reference into `persons` is invalidated
console.log(someone.name) -- error: `someone` was invalidated by `persons.push`: declare it again with `use someone = persons[...]`
A field that references another object names the collection it lives in, and is one side of a relation whose other side is declared too. The compiler keeps both sides in sync, and deleting an object cleans up every relation it was part of, so no reference is ever left dangling.
mutable people: Bag(Person) = []
type Person = {
name: String
bestFriend: (Person in people)?
bestFriendOf: Bag(people->bestFriend) -- the people whose `bestFriend` is me
}
use ana = people.add({ name = "Ana" })
use bao = people.add({ name = "Bao" })
ana.bestFriend = bao -- `bao.bestFriendOf` is updated automatically
people.delete(bao) -- `ana.bestFriend` becomes `none`
The full documentation lives in documentation/ and is published by the website in packages/website.
To test Fa locally, you need Rust installed. Install it with rustup from https://rustup.rs.
The parser project lives in packages/parser and builds as the fa-parser crate.
From the repository root:
cargo build -p fa-parser
The parser binary expects a file path and prints the parsed tree.
cargo run -p fa-parser -- path/to/file.fa
console.log("Hello, world")