# Справочник по манифесту

> Каждое поле neurosquad-card.json — описание, размер, разрешения, форма настроек, порты и инструменты — и правила, которые проверяет приложение.

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

У каждой карточки в корне папки лежит `neurosquad-card.json`. Приложение читает его при установке и
отказывается ставить карточку, чей манифест не проходит проверку; `npx @neurosquad/card-sdk validate`
выполняет ровно те же проверки на вашей машине.

Для подсказок в редакторе укажите в `$schema` схему, которая поставляется с SDK:
`./node_modules/@neurosquad/card-sdk/schema/neurosquad-card.v1.json` (шаблон React) или
`./vendor/neurosquad-card.schema.json` (простой шаблон). Она же экспортируется как
`@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/ru/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`. Карточку под более новый протокол, чем знает приложение, оно откажется ставить с сообщением «нужен более новый NeuroSquad». |
| `description` | | локализуемый текст, ≤ 300 | Показывается в диалоге установки и в выборе карточек. |
| `author` | | `{ "name", "url"? }` | `url` должен быть `https://`. Показывается как **указанный самим автором** (self-declared). |
| `license` | | строка ≤ 100 | Идентификатор SPDX, например `MIT`. |
| `homepage` | | URL `https://` | |
| `keywords` | | ≤ 20 уникальных строк, до 40 символов каждая | |
| `icon` | | путь к `.png` или `.webp` в пакете | Квадратная, ≤ 128 КБ (от 128×128 выглядит чётко). Проверяется по содержимому при установке. Без иконки у карточки будет кусочек пазла. |
| `minAppVersion` | | SemVer | Минимальная версия NeuroSquad, в которой карточка работает. |
| `entry` | | путь к файлу `.html`, по умолчанию `index.html` | Страница, которая загружается в карточку. |

**Локализуемый текст** — это либо обычная строка, либо объект, где обязателен английский:
`{ "en": "Test radar", "ru": "Радар тестов", "zh": "测试雷达" }`. Приложение показывает язык
пользователя, а если его нет — английский.

**Правила для текста.** В именах, описаниях, подписях, причинах и описаниях инструментов нельзя
использовать управляющие символы (табуляция и перевод строки в описаниях допустимы), переопределения
и изоляцию направления текста (bidi), разделители строк, символы нулевой ширины и другие невидимые
символы. Называть себя «NeuroSquad», «official» или «verified» в `displayName` или `author` могут
только официальные карточки (опубликованные из организации `glmn-ai`) — `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 }
}
```

Размеры — в единицах холста (CSS-пиксели при масштабе 100 %), целые числа: ширина 200–2400,
высота 120–1800, причём `minSize ≤ defaultSize ≤ maxSize`. По умолчанию 420×320, минимум 200×120,
максимум 2400×1800. Пользователь меняет размер в этих пределах; [`card.requestResize()`](https://docs.neurosquad.ai/ru/card-sdk/api/card-ui#resize)
тоже в них ограничивается.

## Разрешения — `permissions`

Список (до 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/ru/card-sdk/permissions). |
| `hosts` | Только для `network`, и там обязателен: до 32 шаблонов хостов. |
| `reason` | Локализуемый текст ≤ 300, показывается под разрешением в диалоге установки. Объясните зачем. |
| `optional` | `true` — не спрашивается при установке; карточка просит его во время работы через [`card.permissions.request()`](https://docs.neurosquad.ai/ru/card-sdk/api/environment#permissions). |

Обязательные разрешения при установке выдаются целиком или никак. Если указать один и тот же
идентификатор дважды, записи объединятся (и обязательная победит необязательную).

**Шаблоны хостов** для `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/ru/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`. По умолчанию 2 000 для `string`, 20 000 для `text`. |
| `min`, `max`, `step` | `number`. |
| `options` | Только `select`, 1–50 пар `{ "value", "label" }`. |

**Секреты** вводятся только в форме приложения, хранятся в зашифрованном виде и никогда не доходят
до карточки: карточка узнаёт лишь, задан ли секрет, и пользуется им через подстановку
`{{secret:<key>}}` в [заголовках сетевых запросов](https://docs.neurosquad.ai/ru/card-sdk/api/network#secrets).

## Порты — `ports`

Типизированные каналы данных по стрелкам: до 16 входов (`inputs`) и 16 выходов (`outputs`).
Подробно — в разделе [Порты](https://docs.neurosquad.ai/ru/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/ru/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` | JSON Schema с `"type": "object"`. Свойство `card` зарезервировано (его добавляет приложение). |
| `readOnly` | `true`, если инструмент ничего не меняет, — подсказка для агента. |
| `timeoutMs` | 1 000–120 000, по умолчанию 30 000. |

## Ваши JSON 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 КБ в сумме; `const` — не больше 4 КБ.
- **Нельзя:** `pattern` (регулярные выражения из карточки выполнялись бы в приложении — риск отказа в
обслуживании) и любые ключевые слова не из списка выше.

> `$id` схемы, `https://neurosquad.ai/schemas/neurosquad-card.v1.json`, — это идентификатор, а не
> адрес для скачивания: указывайте в `$schema` копию из SDK.
