跳到主要内容

文件系统

文件系统

工作区是一个目录,其 src/ 中存放 + 文件。每个 + 文件都是一个编译器角色:它的默认导出是传给 @norbital-ai/bolt 中该角色声明函数的一个字面量。名称来自路径,从不来自文件内容。不带 + 的文件是普通模块,可以放在任何位置。

API 参考:bolt

目录树

<workspace>/
├── package.json
├── tsconfig.json                          extends ./.norbital/tsconfig.json
├── norbital.template.json                 catalogue metadata (templates only)
├── assets/                                thumbnail.svg + runtime assets shipped in the artifact
├── seed/                                  <collection>.json[.gz] rows, assets.json + assets/**, optional seed.ts
├── tests/                                 bolt test (@effect/vitest + @norbital-ai/bolt/test)
├── .norbital/                             generated, never edited
└── src/
    ├── +workspace.ts                      tz, locale, currency, app order, AI model classes, connections
    ├── +secrets.ts                        secret names: OAuth clients, MCP settings; values set at runtime
    ├── data/
    │   ├── +relationship.ts               every relationship
    │   ├── model/+<model>.model.ts        storage: fields, kinds, constraints, state
    │   ├── custom_field/<field>/          +definition.ts, +renderer.svelte
    │   └── collection/<model>/            the exposed portion of model <model>
    │       ├── +collection.ts             reads, writes, the transform, queries, actions, notifications
    │       ├── +representation.svelte     optional record view (RecordShell otherwise)
    │       └── +pipeline.ts               optional import / export
    ├── access_control/
    │   ├── team/+team.ts                  team names → the policies each holds
    │   └── policy/+<name>.policy.ts       grants, embedded approvals, capabilities, limits
    ├── integration/<name>/
    │   ├── +integration.ts                a driver, configuration, credential, feeds, outbound
    │   └── +integration.svelte            optional setup screen
    ├── agent/
    │   ├── +agent.md                      in-app agent brief (staff)
    │   ├── +agent.external.md             brief for external members
    │   ├── envoy/+<id>.envoy.ts           an agent role a conversation instance deploys
    │   ├── skill/+<name>.skill.md         an agent skill
    │   └── mcp/+<name>.mcp.ts             an MCP server the agent may use
    ├── automation/+<name>.automation.ts   cron / event / webhook work and its I/O
    ├── app/
    │   ├── <app>/+app.ts                  title, icon, audience, pages in nav order
    │   ├── <app>/+<page>.page.svelte      one page per file
    │   └── <group>/+group.ts              a nav group; its apps live in its folder
    ├── i18n/
    │   ├── +messages.ts                   base locale keys
    │   └── +<locale>.messages.ts          other locales (keys ⊆ the base)
    └── lib/                               ordinary modules (no roles)

命名规则:

  • 如果文件夹已经说明了是什么,文件就是 +<role>.<ext>:data/collection/orders/+collection.ts。
  • 否则文件是 +<name>.<role>.<ext>:access_control/policy/+sales_rep.policy.ts。
  • 文件夹名使用单数,名称须匹配 ^[a-z][a-z0-9_]*$。
  • 未知的 + 文件、放错文件夹的角色,或没有对应 data/model/+<m>.model.ts 的 data/collection/<m>/ 文件夹,都是构建错误,其帮助信息会打印角色表。

角色

每个角色有一个声明函数。collection、app、group、integration 与 pipeline 先接收自己的名称;其余只接收字面量。代码体在声明之后以独立语句附加(c.transform(…)、c.query(…)、c.action(…)、a.run(…)),从不写在字面量内部。

角色src/ 下的路径默认导出指南
工作区设置+workspace.tsworkspace({…})快速入门
密钥+secrets.tssecrets({…})集成
模型data/model/+<m>.model.tsmodel({…})集合
关系data/+relationship.tsrelationship({…})集合
自定义字段data/custom_field/<f>/+definition.tscustomField({…})集合
自定义字段渲染器data/custom_field/<f>/+renderer.svelte{ view: CustomFieldView }UI 组件
集合data/collection/<m>/+collection.tscollection('<m>', {…})写入契约
记录视图data/collection/<m>/+representation.svelte{ view: RecordView<'<m>'> }UI 组件
集成integration/<n>/+integration.tsintegration('<n>', {…})集成
集成设置integration/<n>/+integration.svelteSvelte 组件集成
流水线data/collection/<m>/+pipeline.tspipeline('<m>', {…})流水线
团队access_control/team/+team.tsteam({…})策略
策略access_control/policy/+<p>.policy.tspolicy({…})策略
Agent 简报agent/+agent.md, agent/+agent.external.mdMarkdownNorbius
Agent 技能agent/skill/+<s>.skill.md带 description: frontmatter 的 MarkdownNorbius
MCP 服务器agent/mcp/+<n>.mcp.tsmcp({…})Norbius
Envoyagent/envoy/+<e>.envoy.tsenvoy({…})Envoy
自动化automation/+<a>.automation.tsautomation({…})自动化
应用app/<a>/+app.tsapp('<a>', {…})应用
页面app/<a>/+<p>.page.svelteSvelte 组件应用
导航分组app/<g>/+group.tsgroup('<g>', {…})应用
消息i18n/+messages.ts, i18n/+<locale>.messages.tsmessages({…})国际化

生成的文件

.norbital/
├── names.ts, names.client.ts   # the names index: every path-derived name → typeof its declaration
├── tsconfig.json               # the authored tsconfig.json only extends this
├── representations.check.ts
├── artifact/                   # bolt build output
├── seed/                       # the base (and sample) seed packs
└── cache/**

编译器写出 .norbital/;其中的内容既不编辑也不提交。名称索引把每个由路径得出的名称映射到其声明的 typeof,因此其他每个文件(包括每个页面)都由声明获得类型。只有在添加、重命名或删除角色文件时才会重写它。

命令

bolt check   # every error of every stage in one run
bolt build   # check + .norbital/artifact/ + seed packs
bolt test    # @effect/vitest with TestWorkspace.layer
bolt dev     # the author loop: PGlite, live reload, a dev mail sink
bolt start   # the self-host server (bolt-server)

五个命令,一切正常时以 0 退出,作者错误以 1 退出,工具故障以 2 退出。bolt build 是宿主运行的唯一关卡。

清单即数据库结构

没有迁移文件。宿主将已应用的数据库结构与清单比较,并在一个事务中应用一个计划。计划无法区分重命名与“删除再添加”,因此重命名字段或模型会丢失数据:先添加新字段并回填,再在之后的变更中删除旧字段。

哪些不是角色

编写接口是封闭的:上表之外的一切都不存在,以下路径也不会被读取——src/collections/、src/datatypes/、src/functions/、src/apps/、src/+agents.md、src/access/policies/、src/capabilities/、+anonymous_limits.ts、vite.config.ts 与 .norbital/migrations/。服务器函数就是集合的查询与操作,密钥名在 +secrets.ts 中声明,Agent 工具就是集合的读取、查询与操作。