# 清单文件参考

> neurosquad-card.json 的每个字段——身份信息、大小、权限、设置表单、端口和工具——以及应用会检查的规则。

Source: https://docs.neurosquad.ai/zh/card-sdk/manifest

每张卡片的文件夹根目录都有一个 `neurosquad-card.json`。应用在安装时读取它，清单检查不通过的卡片会被拒绝；
`npx @neurosquad/card-sdk validate` 会在你的电脑上运行完全相同的检查。

想在编辑器里获得补全，可以把 `$schema` 指向 SDK 自带的 schema：
`./node_modules/@neurosquad/card-sdk/schema/neurosquad-card.v1.json`（React 模板）或
`./vendor/neurosquad-card.schema.json`（纯 HTML 模板）。它也以 `@neurosquad/card-sdk/schema.json` 导出。

## 完整示例

```json
{
  "$schema": "./node_modules/@neurosquad/card-sdk/schema/neurosquad-card.v1.json",
  "manifestVersion": 1,
  "name": "test-radar",
  "displayName": { "en": "Test radar", "ru": "Радар тестов", "zh": "测试雷达" },
  "version": "1.0.0",
  "protocol": 1,
  "description": "Runs the test suite in a connected terminal and shows what broke.",
  "author": { "name": "Acme", "url": "https://acme.dev" },
  "license": "MIT",
  "homepage": "https://acme.dev/test-radar",
  "keywords": ["tests", "ci"],
  "icon": "icon.png",
  "minAppVersion": "0.1.100",
  "entry": "dist/index.html",
  "card": {
    "defaultSize": { "w": 460, "h": 340 },
    "minSize": { "w": 320, "h": 220 }
  },
  "permissions": [
    "agents.read",
    "terminals.write",
    { "id": "fs.read", "reason": "Reads the JUnit report" },
    { "id": "network", "hosts": ["api.github.com"], "reason": "Links failures to GitHub issues" },
    { "id": "clipboard.write", "optional": true }
  ],
  "settings": [
    { "key": "command", "type": "string", "label": "Test command", "default": "npm test" },
    { "key": "githubToken", "type": "secret", "label": "GitHub token", "scope": "package" }
  ],
  "ports": {
    "inputs": [{ "id": "run", "label": "Run", "type": "ns:trigger", "default": true }],
    "outputs": [
      { "id": "failures", "label": "Failures", "type": "ns:tasks", "retain": true },
      { "id": "summary", "label": "Summary", "type": "ns:markdown" }
    ]
  },
  "tools": [
    {
      "name": "run_tests",
      "title": "Run the tests",
      "description": "Runs the project's tests and returns failing test names with messages.",
      "inputSchema": {
        "type": "object",
        "properties": { "filter": { "type": "string", "maxLength": 200 } }
      },
      "timeoutMs": 120000
    }
  ]
}
```

## 身份信息

| 字段 | 必填 | 规则 | 含义 |
| --- | --- | --- | --- |
| `$schema` | | 字符串 | 给编辑器用，应用会忽略。 |
| `manifestVersion` | 是 | `1` | 清单格式版本。 |
| `name` | 是 | `a-z`、数字和 `-`，以字母开头，2–48 个字符 | 包的短名。它是卡片[工具名](https://docs.neurosquad.ai/zh/card-sdk/api/tools)的前缀，也是自定义端口类型的命名空间。保留名（内置卡片和工具族）：`neurosquad`、`neurosquad-card`、`custom`、`canvas`、`browser`、`terminal`、`agent`、`note`、`todo`、`kanban`、`host`、`system`、`telegram`、`image`、`reference`、`ports`、`web-watch`、`watch`、`timer`、`sticky`、`standup`、`squad`、`mcp`、`skill`、`official`。 |
| `displayName` | 是 | 多语言文本，≤ 80 | 卡片在菜单、标题栏和安装对话框中显示的名称。 |
| `version` | 是 | SemVer（`1.2.0`、`1.2.0-beta.1`） | 仅供参考——安装锁定的是提交，而不是版本号。但还是要递增它：用户在更新时会看到。 |
| `protocol` | 是 | 整数 | 你开发时所针对的卡片协议——目前是 `1`。为比应用更新的协议开发的卡片会被拒绝，并提示“needs a newer NeuroSquad”。 |
| `description` | | 多语言文本，≤ 300 | 显示在安装对话框和卡片选择器中。 |
| `author` | | `{ "name", "url"? }` | `url` 必须是 `https://`。显示时标注为**自称**。 |
| `license` | | 字符串 ≤ 100 | SPDX 标识符，例如 `MIT`。 |
| `homepage` | | `https://` URL | |
| `keywords` | | ≤ 20 个不重复字符串，每个 ≤ 40 个字符 | |
| `icon` | | 包内 `.png` 或 `.webp` 的路径 | 正方形，≤ 128 KB（128×128 或更大会更清晰）。安装时会按文件字节检查。没有图标时卡片显示一块拼图。 |
| `minAppVersion` | | SemVer | 能运行这张卡片的最低 NeuroSquad 版本。 |
| `entry` | | `.html` 文件路径，默认 `index.html` | 加载到卡片中的页面。 |

**多语言文本**可以是普通字符串，也可以是必须包含英文的对象：
`{ "en": "Test radar", "ru": "Радар тестов", "zh": "测试雷达" }`。应用会显示用户所用的语言，缺失时回退到英文。

**文本规则。** 名称、描述、标签、理由和工具描述中不能包含控制字符（描述中允许制表符和换行）、双向文本覆盖或隔离字符、
行分隔符、零宽字符或其他不可见字符。只有官方卡片（从 `glmn-ai` 组织发布）可以在 `displayName` 或 `author` 中
自称“NeuroSquad”“official”或“verified”——`validate` 会警告，应用会拒绝。

**路径**（`entry`、`icon`）相对于清单文件，使用 `/` 分隔——不能有 `..`、不能以 `/` 开头、不能有反斜杠、
不能使用 Windows 设备名（`con`、`nul`……）、不能位于 `__ns/` 之下（应用保留了它），最多 20 层、240 个字符。

## 大小——`card`

```json
"card": {
  "defaultSize": { "w": 460, "h": 340 },
  "minSize": { "w": 320, "h": 220 },
  "maxSize": { "w": 1200, "h": 900 }
}
```

尺寸以画布单位计（100% 缩放时的 CSS 像素），为整数，宽 200–2400、高 120–1800，并满足 `minSize ≤ defaultSize ≤ maxSize`。
默认值：420×320，最小 200×120，最大 2400×1800。用户在最小和最大值之间调整大小；
[`card.requestResize()`](https://docs.neurosquad.ai/zh/card-sdk/api/card-ui#resize) 同样会被限制在这个范围内。

## 权限——`permissions`

权限 id 的列表（≤ 32 项），或带有附加信息的对象：

```json
"permissions": [
  "agents.read",
  { "id": "network", "hosts": ["api.github.com", "*.example.com", "status.example.org:8443"] },
  { "id": "fs.read", "reason": { "en": "Reads the JUnit report", "ru": "Читает отчёт JUnit" } },
  { "id": "clipboard.write", "optional": true }
]
```

| 键 | 含义 |
| --- | --- |
| `id` | [权限](https://docs.neurosquad.ai/zh/card-sdk/permissions)页面列出的 id 之一。 |
| `hosts` | 仅用于 `network`，且在那里必填：≤ 32 个主机模式。 |
| `reason` | 多语言文本 ≤ 300，显示在安装对话框中该权限的下方。说明为什么需要。 |
| `optional` | `true` = 安装时不询问；卡片在运行时通过 [`card.permissions.request()`](https://docs.neurosquad.ai/zh/card-sdk/api/environment#permissions) 申请。 |

必需权限在安装时要么全给、要么不装。同一个 id 列出两次会被合并（必需的条目优先于可选的）。

`network` 的**主机模式**：只能是小写主机名——`api.example.com`、`api.example.com:8443`（443 以外的端口），
或 `*.example.com`（任意子域名，不含 `example.com` 本身）。不能写协议、路径、IP 地址、单独的 `*` 或 `localhost`——
本机访问是单独的 `network.local` 权限。

## 设置表单——`settings`

最多 40 个字段。表单由应用绘制（从卡片的 **⋯ → Settings…** 打开，或调用
[`card.settings.open()`](https://docs.neurosquad.ai/zh/card-sdk/api/storage-settings#settings)）；卡片读取其中的值。

```json
"settings": [
  { "key": "command", "type": "string", "label": "Test command", "default": "npm test", "maxLength": 200 },
  { "key": "notes", "type": "text", "label": "Notes", "placeholder": "Anything the agents should know" },
  { "key": "interval", "type": "number", "label": "Check every (min)", "default": 5, "min": 1, "max": 60, "step": 1 },
  { "key": "compact", "type": "boolean", "label": "Compact view", "default": false },
  { "key": "branch", "type": "select", "label": "Branch", "default": "main",
    "options": [{ "value": "main", "label": "main" }, { "value": "dev", "label": "dev" }] },
  { "key": "accent", "type": "color", "label": "Accent", "default": "#22c55e" },
  { "key": "apiKey", "type": "secret", "label": "API key", "required": true, "scope": "package" }
]
```

| 键 | 含义 |
| --- | --- |
| `key` | 以字母开头；字母、数字、`_`、`-`；≤ 64。必须唯一。 |
| `type` | `string`（单行）、`text`（多行）、`number`、`boolean`、`select`、`color`（`#rrggbb`）、`secret`。 |
| `label`、`description`、`placeholder` | 多语言文本（≤ 80、≤ 300、≤ 80）。 |
| `default` | 与字段类型一致。`select` 必须是选项之一，`color` 必须是 `#rrggbb`，`number` 必须在 `min`/`max` 之间。**`secret` 不允许有默认值。** |
| `required` | 不填就无法保存表单。 |
| `scope` | `instance`（默认）：画布上的每张卡片各一份。`package`：这个卡片包的所有卡片共享。 |
| `maxLength` | 用于 `string`、`text`、`secret`。默认：`string` 为 2 000，`text` 为 20 000。 |
| `min`、`max`、`step` | 用于 `number`。 |
| `options` | 仅用于 `select`，1–50 个 `{ "value", "label" }`。 |

**密钥**（secret）只能在应用的表单中输入，加密保存，永远不会到达卡片：卡片只能知道它是否已设置，
并通过[网络请求头](https://docs.neurosquad.ai/zh/card-sdk/api/network#secrets)中的 `{{secret:<key>}}` 占位符来使用它。

## 端口——`ports`

通过箭头的类型化数据连接：最多 16 个 `inputs` 和 16 个 `outputs`。完整指南：[端口](https://docs.neurosquad.ai/zh/card-sdk/api/ports)。

```json
"ports": {
  "inputs": [
    { "id": "run", "label": "Run", "type": "ns:trigger", "default": true },
    { "id": "lookup", "label": "Look up", "type": "ns:text", "mode": "request",
      "response": { "type": "ns:json" } }
  ],
  "outputs": [
    { "id": "failures", "label": "Failures", "type": "ns:tasks", "retain": true },
    { "id": "coverage", "label": "Coverage", "type": "test-radar/coverage",
      "description": "Line coverage per file, 0..1",
      "schema": {
        "type": "object",
        "additionalProperties": { "type": "number", "minimum": 0, "maximum": 1 }
      } }
  ]
}
```

| 键 | 适用于 | 含义 |
| --- | --- | --- |
| `id` | 两者 | `a-z`、数字、`-`，以字母开头，≤ 32。同一方向内唯一。 |
| `label`、`description` | 两者 | 多语言文本（≤ 80、≤ 500）。会显示给用户、对端卡片以及探查该端口的智能体。 |
| `type` | 两者 | 知名的 `ns:*` 类型，或自定义的 `<package-name>/<type-name>`。 |
| `schema` | 两者 | 值还必须满足的额外 JSON Schema。**自定义类型必须提供。** |
| `mode` | 输入 | `stream`（默认）：发出即不管的消息。`request`：发送方会等待回复。 |
| `response` | 请求型输入 | `{ "type", "schema"? }`——回复的类型。`mode: "request"` 时必填。 |
| `default` | 输入 | 当对端的某个输出可匹配多个输入时优先选用的输入。最多一个。 |
| `retain` | 输出 | 应用会保留最后一个值：对端随时可以读取，新连接的对端会收到一次。 |

允许使用另一个卡片包命名空间下的自定义类型（会给出警告）——两张卡片正是这样约定共享格式的。

## 工具——`tools`

最多 32 个可供与卡片相连的智能体调用的工具。指南：[给智能体的工具](https://docs.neurosquad.ai/zh/card-sdk/api/tools)。

| 键 | 含义 |
| --- | --- |
| `name` | `a-z`、数字、`_`，以字母开头，≤ 40。智能体看到的是 `<name with - → _>_<tool>`，例如 `test_radar_run_tests`。这个对外名称不能与 NeuroSquad 的内置工具（`canvas_spawn_card`、`terminal_send_keys`……）同名，也不能包含 `__`。 |
| `title` | ≤ 80，给人看的标题。 |
| `description` | ≤ 2 000，**写给模型看**，用英文：它做什么、返回什么。 |
| `inputSchema` | `"type": "object"` 的 JSON Schema。属性 `card` 被保留（由应用添加）。 |
| `readOnly` | 工具不会改变任何东西时设为 `true`——会作为提示展示给智能体。 |
| `timeoutMs` | 1 000–120 000，默认 30 000。 |

## 你编写的 JSON Schema

端口 schema、回复 schema 和工具的 `inputSchema` 使用 JSON Schema 2020-12 的一个安全子集，安装时检查（≤ 500 个节点，嵌套 ≤ 16 层）：

- **支持：**`type`、`enum`、`const`、`properties`、`required`、`additionalProperties`、
`minProperties`、`maxProperties`、`items`、`minItems`、`maxItems`、`uniqueItems`、`minLength`、
`maxLength`、`format`、`minimum`、`maximum`、`exclusiveMinimum`、`exclusiveMaximum`、`multipleOf`、
`anyOf`、`oneOf`、`$ref`（`#` 或 `#/$defs/<name>`）、`$defs`。
- **格式：**`uri`、`date-time`、`date`、`email`、`color`、`uuid`。
- **会被忽略的注解：**`$id`、`$schema`、`$comment`、`title`、`description`、`default`、
`examples`、`deprecated`、`readOnly`、`writeOnly`。
- **上限：**`enum` ≤ 256 个选项、总计 ≤ 16 KB；`const` ≤ 4 KB。
- **不允许：**`pattern`（来自卡片的正则表达式会在应用中执行——存在拒绝服务风险），以及上面未列出的任何关键字。

> schema 的 `$id`——`https://neurosquad.ai/schemas/neurosquad-card.v1.json`——只是一个标识符，并不能下载：
> 请把 `$schema` 指向 SDK 中的那份副本。
