mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-09-05 18:23:50 +08:00
## 这是什么 / What 把自然语言意图翻译成第三方飞书 CLI(`lark-cli`)的正确调用,覆盖云文档、Markdown 文件、电子表格、多维表格、云空间、知识库、幻灯片、画板、即时消息、邮箱、日历、视频会议与妙记、任务、审批、OKR、考勤、应用搭建与实时事件等业务域。 声明 23 个业务域技能依赖,安装后即可使用,无需手工拷贝技能目录。 An agent that turns natural-language intent into correct calls to the third-party Feishu CLI, covering documents, sheets, Base tables, drive, wiki, messaging, mail, calendar, meetings, tasks, approvals, OKR and attendance. It declares 23 domain skill dependencies that install together with the agent. ## 结构 / Layout 与仓库既有的 `dingtalk-workspace` / `wecom-assistant` 条目保持一致: ``` agents/feishu-orchestrator/ ├── agent.json # 内联元数据(AgentFS 配置 ∪ 市场卡片,含 i18n 双语 + changelog) ├── catalog-metadata.v1.json # sidecar,字段全部从 agent.json 派生 ├── assets/avatar.webp # 512×512 图片头像 ├── persona.md / principles.md # L0/L1/L2 分层人格与硬规则 ├── README.md # 条目总览 + 文档索引 └── docs/01..13-*.md # 按业务域拆分的 13 篇功能文档 ``` ## 文档 / Docs 命令、参数约定与坑位**均来自真机验证**(2026-09-01,220 个已授权 scope)。未跑通的能力在 [`docs/13-能力边界.md`](agents/feishu-orchestrator/docs/13-能力边界.md) 中如实标注,不含任何租户、组织或个人标识。 其中固化了三处容易踩错的 CLI 契约: | 契约 | 踩错的后果 | |---|---| | `auth status` 成功时**没有**顶层 `ok` 字段 | 按通用 `ok === true` 判据会把「已授权」误判成「未授权」,反复推用户重新扫码 | | 身份不显式指定会落到 `bot` | bot 看不见用户的个人日历、云盘、邮箱,且返回**空成功**而非报错 | | `--ranges`(复数)的 sheet 前缀要用 `sheet_name` | 用 `sheet_id` 会通过确认门禁、但在 API 层报 `Sheet not found`;而单数 `--range` 的约定**正好相反** | ## 治理 / Governance - `governance.availability: listing-only` —— 与核心 Agent、钉钉、企微三个既有条目一致。inline agent 的内容随仓库走,没有独立制品 ref,无法满足 `installable` 分支「必须有不可变 ref 或 SHA-256 摘要」的门禁 - `governance.branding`:`independent-listing` / `nominative` / `logo not-used` —— 飞书、Lark 为第三方商标,头像为抽象编排拓扑图,不使用任何第三方 logo - `compatibility.requirements`:按仓库「外部依赖披露」规范声明运行时、权限、连接三类前置。DesireCore 不打包、不分发、不授权、不安装、不代付 `lark-cli` 及其背后的飞书产品 ## 顺带修正 / Incidental 根 `README.md` 的 Agent 清单停留在 `2` 个(遗漏 `wecom-assistant`),一并补齐为准确的 4 个;`manifest.json#stats.totalAgents` 3 → 4。 ## 校验 / Verification | 校验 | 结果 | |---|---| | `validate_catalog_metadata.py --require-complete` | **0 error**,sidecars 74,本条目零 warning | | `validate-i18n.py` | 0 error | | `test_validate_catalog_metadata.py` | 47/47 | | 发布前敏感信息扫描(邮箱 / 飞书真实 ID / 租户组织标识 / 带 ID 链接 / 密钥形态 / 隐藏文件,全工作树) | **零命中** | | 文档内部链接 | 13 个链接全部命中真实文件,无断链 | ## 依赖 / Dependency `requiredClientVersion: 10.0.143` —— 自动装齐依赖技能的能力来自主仓库 desirecore/desirecore#2587,该值按其合入后的首个发布版本填写。**若 #2587 未能进入 10.0.143,此值需回填修正**,否则用户在缺少该能力的版本上装完 Agent 会没有技能。 --------- Co-authored-by: yi-ge <jackyoncode@gmail.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
365 lines
16 KiB
Markdown
365 lines
16 KiB
Markdown
# DesireCore Market
|
||
|
||
DesireCore 官方市场仓库,存放官方维护的 Agent/Team/Skill 定义,以及经过整理的第三方 Skill 入口。
|
||
|
||
## Repository Shape
|
||
|
||
```
|
||
.
|
||
├── manifest.json # Market metadata, supported locales, aggregate stats
|
||
├── categories.json # Category registry and localized labels
|
||
├── builtin-skills.json # Built-in local SKILL.md skills
|
||
├── agents/
|
||
│ ├── desirecore/
|
||
│ │ └── agent.json
|
||
│ └── <agent-listing>/
|
||
│ ├── agent.json
|
||
│ ├── catalog-metadata.v1.json
|
||
│ └── USAGE.md # Optional usage notes (USAGE.<locale>.md for variants)
|
||
├── teams/
|
||
│ └── <team>/
|
||
│ └── entry.json
|
||
└── skills/
|
||
├── <local-skill>/
|
||
│ ├── SKILL.md
|
||
│ └── SKILL.<locale>.md
|
||
└── <external-entry>/
|
||
└── entry.json
|
||
```
|
||
|
||
The market currently contains:
|
||
|
||
- `5` Agents: `desirecore`, `dingtalk-workspace`, `feishu-orchestrator`, `invoice-organizer`, `wecom-assistant`
|
||
- `1` Team: `contract-review-team`
|
||
- `40` local built-in skills with `SKILL.md`
|
||
- `29` external skill entries with `entry.json`
|
||
- `69` publishable skills in total (`SKILL.md` + `entry.json`)
|
||
|
||
## Skill Sources
|
||
|
||
Local built-in skills are installable from this repository and must be listed in `builtin-skills.json`:
|
||
|
||
```text
|
||
baidu-poi-search, ccgp-gov-procurement, clone-agent, cnipa-patent-search, code-intelligence,
|
||
configuring-compute, create-agent, creditchina-query, dashscope-image-gen, delete-agent,
|
||
dev-environment-setup, discover-agent, docx, frontend-design, guizang-ppt,
|
||
image-to-image, mail-operations, manage-skills, manage-teams, markdown,
|
||
minimax-music-gen, minimax-video-gen, multi-source-sentiment, nodejs-runtime, pdf, pptx,
|
||
presentation-forge, python-runtime, registering-services, s3-storage-operations, skill-creator,
|
||
tech-diagram, tianyancha-risk, update-agent, using-services, web-access, workflow, workforce-optimization,
|
||
xiaomi-tts, xlsx
|
||
```
|
||
|
||
`builtin-skills.json#retired` lists old built-in Skill IDs that clients may safely retire during
|
||
startup. Clients only remove copies tracked in `skills.lock` as market/bundled content whose
|
||
`SKILL.md` hash still matches the installed record; manually installed or locally modified copies
|
||
are preserved. An ID must not appear in both `skills` and `retired`.
|
||
|
||
External entries are marketplace pointers to Git/Web/ZIP sources:
|
||
|
||
```text
|
||
agent-reach, ai-news-radar, amap-jsapi-skill, baoyu-skills, dingtalk-api,
|
||
dingtalk-cli, flyai-skill, follow-builders, humanizer, humanizer-zh,
|
||
ian-xiaohei-illustrations, impeccable, karpathy-guidelines, khazix-skills,
|
||
larksuite-cli, last30days, luckin-my-coffee, marketingskills,
|
||
mattpocock-skills, minimax-image-gen, minimax-tts, mt-paotui-for-client,
|
||
netease-skills, nuwa-skill, taste-skill, watch, watchless,
|
||
wechatpay-skills, wecom-cli
|
||
```
|
||
|
||
## Data Formats
|
||
|
||
### Local Skill (`skills/<id>/SKILL.md`)
|
||
|
||
Local skills use YAML frontmatter plus Markdown body. The top-level `name` must equal the directory slug. Display strings live in `metadata.i18n`.
|
||
|
||
```yaml
|
||
---
|
||
name: web-access
|
||
description: >-
|
||
Use this skill when ...
|
||
version: 2.0.1
|
||
type: procedural
|
||
risk_level: low
|
||
status: enabled
|
||
metadata:
|
||
author: desirecore
|
||
updated_at: '2026-05-05'
|
||
i18n:
|
||
default_locale: en-US
|
||
source_locale: zh-CN
|
||
locales: [zh-CN, en-US]
|
||
zh-CN:
|
||
name: 联网访问
|
||
short_desc: 联网搜索、网页抓取、登录态浏览器访问
|
||
body: ./SKILL.zh-CN.md
|
||
translated_by: human
|
||
en-US:
|
||
name: Web Access
|
||
short_desc: Web search, page fetching, logged-in browser access
|
||
body: ./SKILL.md
|
||
source_hash: sha256:...
|
||
translated_by: human
|
||
market:
|
||
category: research
|
||
channel: latest
|
||
maintainer:
|
||
name: DesireCore Official
|
||
verified: true
|
||
---
|
||
```
|
||
|
||
### External Entry (`skills/<id>/entry.json`)
|
||
|
||
External entries point to upstream packages or repositories. They are counted in `manifest.stats.totalSkills` but are not included in `builtin-skills.json`.
|
||
|
||
```json
|
||
{
|
||
"id": "example-skill",
|
||
"name": "Example Skill",
|
||
"category": "development",
|
||
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">...</svg>",
|
||
"tags": ["example"],
|
||
"maintainer": {
|
||
"name": "Example",
|
||
"verified": false,
|
||
"account": "example",
|
||
"url": "https://github.com/example/example-skill"
|
||
},
|
||
"stewardship": "community",
|
||
"license": "MIT",
|
||
"redistribution": "allowed",
|
||
"source": {
|
||
"kind": "git",
|
||
"repoUrl": "https://github.com/example/example-skill.git",
|
||
"repoBranch": "main"
|
||
}
|
||
}
|
||
```
|
||
|
||
### Team Listing (`teams/<id>/entry.json`)
|
||
|
||
A Team is a group of Agents with a supervisor. It is published as a **fork pointer
|
||
only**: the team body (`team.json`, `members.json`, `shared/`) always stays in the
|
||
upstream team repository, and the catalog registers just "what it is and where to
|
||
fork it from". Installation forks that repository and installs the declared members;
|
||
updates are a `git pull` on the fork. Because both actions are Git actions,
|
||
`source.kind` must be `git` and `source.repoUrl` is required — `zip` and `web` cannot
|
||
express either one — and a Team deliberately has **no** `installPolicy` /
|
||
`updatePolicy` pair: it is always market-initiated fork plus repository-driven update.
|
||
|
||
`teams/<id>/` therefore holds exactly `entry.json` plus the sidecar. There is no
|
||
inline form; a `team.json` in the catalog is rejected.
|
||
|
||
```json
|
||
{
|
||
"id": "example-team",
|
||
"name": "Example Team",
|
||
"category": "development",
|
||
"tags": ["example"],
|
||
"latestVersion": "0.1.0",
|
||
"maintainer": {
|
||
"name": "Example",
|
||
"verified": false,
|
||
"account": "example",
|
||
"url": "https://github.com/example"
|
||
},
|
||
"stewardship": "community",
|
||
"license": "MIT",
|
||
"redistribution": "source-pointer-only",
|
||
"source": {
|
||
"kind": "git",
|
||
"repoUrl": "https://github.com/example/example-team.git",
|
||
"repoBranch": "main",
|
||
"ref": "0123456789abcdef0123456789abcdef01234567"
|
||
},
|
||
"requiredClientVersion": "10.0.0",
|
||
"avatar": { "t": "示", "bg": "linear-gradient(135deg, #5856D6, #3634A3)" },
|
||
"supervisorName": "Example Supervisor",
|
||
"supervisorAgentId": "example-lead",
|
||
"memberCount": 3,
|
||
"memberNames": ["Example Member One", "Example Member Two"]
|
||
}
|
||
```
|
||
|
||
A Team card is rendered from `avatar`, not from `icon`. The client's runtime
|
||
projection `marketTeamSchema` requires `avatar` and has no `icon` property at all —
|
||
the same is true of `marketAgentSchema`, while only `marketSkillSchema` exposes
|
||
`icon`. The entry contract inherits `icon` from the shared common properties, so it
|
||
is *accepted*, but it can never reach a card. The validator therefore requires `icon`
|
||
on Skill listings only, and warns when an Agent or Team listing declares one.
|
||
|
||
`redistribution` stays `source-pointer-only` for a Team even under a permissive
|
||
license: the market never ships the team body, it only points at the repository the
|
||
client forks. The license governs what a fork may do; `redistribution` describes how
|
||
the content is delivered, and for teams that is always "fetch from upstream".
|
||
|
||
`supervisorName`, `supervisorAgentId`, `memberCount`, `memberNames` and
|
||
`requiredSkills` are display metadata declared by the publisher. They may drift from
|
||
the upstream repository, so installation, permissions and member resolution must read
|
||
the forked `team.json` / `members.json` instead. Teams are counted in
|
||
`manifest.stats.totalTeams`, which the client keeps optional: a catalog with no teams
|
||
may omit it, and once the key is present it must be exact.
|
||
|
||
### Catalog metadata sidecar (`catalog-metadata.v1.json`)
|
||
|
||
The versioned catalog metadata contract is stored at one fixed path next to each
|
||
legacy item:
|
||
|
||
```text
|
||
agents/<id>/catalog-metadata.v1.json
|
||
teams/<id>/catalog-metadata.v1.json
|
||
skills/<id>/catalog-metadata.v1.json
|
||
```
|
||
|
||
Legacy `agent.json`, `SKILL.md`, and `entry.json` files remain the compatibility
|
||
surface for older clients. New clients merge the sidecar through a deterministic
|
||
adapter. Any field repeated in both files must have the same value; the validator
|
||
rejects drift rather than choosing one copy silently.
|
||
|
||
Agent listings support exactly one of `agents/<slug>/agent.json` (inline metadata)
|
||
or `agents/<slug>/entry.json` (an external pointer), alongside the sidecar. Missing
|
||
or simultaneous primary files are rejected. For a pointer, `entry.id` and sidecar
|
||
`identity.id` use the catalog directory slug and `identity.kind` is `agent`; the
|
||
upstream AgentFS `agent.json.id` remains its own UUID and must not be rewritten.
|
||
|
||
An agent listing may also carry an optional `USAGE.md` next to `agent.json`. The
|
||
client renders it as a separate "Usage" section on the agent detail page, kept
|
||
apart from `fullDesc` (which is persona text and also enters the agent's runtime
|
||
context). Localized variants use `USAGE.<locale>.md`, resolved through the same
|
||
fallback chain as the `i18n` block: requested locale, then `i18n.source_locale`,
|
||
then `i18n.default_locale`, then the unsuffixed file. Its scope is what a reader
|
||
needs *before* installing — prerequisites, authorization steps, capability and
|
||
safety boundaries — not full documentation; clients truncate overlong content.
|
||
Longer material belongs in a skill's `references/` directory, which the agent
|
||
loads on demand. Listings without the file are unaffected and render no section.
|
||
Relative image references do not render on the detail page, so keep `USAGE.md`
|
||
text-only. See ADR-143 in the DesireCore repository.
|
||
|
||
Agent pointers first pass the complete raw client contract in
|
||
[`schemas/market-agent-entry.client.schema.json`](schemas/market-agent-entry.client.schema.json),
|
||
exported from `marketAgentEntrySchema` in the DesireCore repository at commit
|
||
`18bbb86f62e1288b1f945209bed74ec72620a9d4`. The schema's `$comment` records the
|
||
source blob as well. Refresh this generated snapshot from the TypeScript export
|
||
when changing client compatibility; do not replace it with permissive sidecar
|
||
validation. Version fields keep their original types and the client's supported
|
||
format. Installation/update policies must either both be absent (effective
|
||
`market/market`) or form a complete supported pair; the sidecar must preserve
|
||
that effective pair.
|
||
|
||
Agent pointer `latestVersion` maps to sidecar `release.version`; optional
|
||
`requiredClientVersion`, `installPolicy`, and `updatePolicy` must agree with the
|
||
sidecar compatibility/spec fields. Pointer source fields must describe the same
|
||
artifact as `provenance.content`, and `maintainer` maps to `upstreamMaintainer`.
|
||
An installable Agent pointer must itself pin `source.ref` (Git) or `source.sha256`
|
||
(Web/ZIP); an immutable ref supplied only by the sidecar cannot pin a mutable
|
||
entry. Existing immutable-source, license, governance-review and complete-coverage
|
||
checks still apply. Agent pointers do not receive the built-in Skill exceptions.
|
||
|
||
Agent 目录必须在 `agent.json` 内联元数据和 `entry.json` 外部指针中二选一,并提供 sidecar。
|
||
Pointer 原始 JSON 先通过固定客户端提交导出的完整 Schema;版本类型与格式、来源路径和策略组合不能由 sidecar 掩盖。
|
||
Pointer 的目录 slug、`entry.id`、sidecar `identity.id` 必须一致;上游 AgentFS 的 UUID 不改写。
|
||
安装/更新策略双缺省时有效值仍是 `market/market`,sidecar 不得将其改成系统条目。
|
||
`latestVersion`、最低客户端版本和安装/更新策略须与 sidecar 对齐;来源必须是同一个制品。
|
||
可安装指针自身必须固定 Git ref 或 Web/ZIP 摘要,不能只在 sidecar 宣称不可变版本。
|
||
现有许可、治理审查、不可变来源和完整覆盖门禁继续有效,不适用内置 Skill 的宽松例外。
|
||
|
||
Team listings are pointer-only, so `teams/<slug>/` carries exactly `entry.json` plus
|
||
the sidecar; an inline `team.json` is rejected. Team pointers first pass the complete
|
||
raw client contract in
|
||
[`schemas/market-team-entry.client.schema.json`](schemas/market-team-entry.client.schema.json),
|
||
exported from `marketTeamEntrySchema` the same way as the Agent snapshot; its
|
||
`$comment` records the source commit and blob. `entry.id`, the directory slug and
|
||
sidecar `identity.id` must agree, `identity.kind` is `team`, and `latestVersion` maps
|
||
to `release.version`. `supervisorName`, `supervisorAgentId`, `memberCount`,
|
||
`memberNames`, `requiredSkills` and `requiredClientVersion` are compared symmetrically:
|
||
the sidecar may neither drop a fact the pointer declares nor invent one it omits,
|
||
because the client reads the pointer and a version gate that exists only in the
|
||
sidecar would not gate anything. Pointer source fields must describe the same
|
||
artifact as `provenance.content`, and an installable Team pointer must itself pin a
|
||
full-SHA `source.ref` — a tag is not a reproducible pin, because a tag can be moved
|
||
to a different commit after the listing is reviewed.
|
||
|
||
团队条目只有指针形态:`teams/<slug>/` 仅放 `entry.json` 与 sidecar,目录内出现 `team.json` 直接判非法。
|
||
Pointer 原始 JSON 先通过由 `marketTeamEntrySchema` 导出的完整客户端 Schema;
|
||
`source.kind` 恒为 `git` 且必须有 `repoUrl`,团队没有 `installPolicy` / `updatePolicy` 组合。
|
||
目录 slug、`entry.id`、sidecar `identity.id` 必须一致,`identity.kind` 为 `team`。
|
||
展示字段与最低客户端版本双向比对:sidecar 既不得丢弃指针声明的事实,也不得凭空补上指针没有的事实。
|
||
可安装团队指针自身必须固定完整 SHA 的 `source.ref`,tag 或分支不算可复现锁定。
|
||
|
||
The sidecar records source-owned presentation, release, timestamp, content
|
||
provenance, governance, compatibility, and type-specific facts. It deliberately
|
||
cannot declare `catalogSourceId`, catalog commit/path/trust, effective official
|
||
status, installation state, device state, health, URLs discovered at runtime, or
|
||
`syncedAt`. DesireCore injects trusted catalog provenance and runtime facts.
|
||
|
||
`license.evidencePath`, `compliance.licenseEvidencePath` and `compliance.noticePath`
|
||
resolve differently by item shape, because the schema constrains only the string
|
||
form. Vendored content (built-in Skills, inline Agents) ships inside this repository,
|
||
so the path is relative to the catalog item directory and the file must actually be
|
||
there — a missing file is an error. A pointer distributes nothing, so its evidence
|
||
can only be inside the upstream snapshot at the pinned revision; the validator cannot
|
||
read that offline, so it warns when such a claim is made against an unpinned pointer.
|
||
Pin `source.ref` to a full commit SHA and the claim becomes falsifiable by anyone who
|
||
fetches it.
|
||
|
||
Time facts are explicit `known`/`unknown` values. A known day uses
|
||
`YYYY-MM-DD` with `precision: "day"`; a known second uses an RFC 3339 UTC value
|
||
ending in `Z` with `precision: "second"`. Never use the current date, clone time,
|
||
or synchronization time to fill an unknown catalog or release timestamp.
|
||
|
||
Collection children stay in their parent's sidecar. Each child declares the
|
||
canonical `skill + parentId + id` identity and its own release fact; a collection
|
||
parent may have an unknown version, and a child version must not be inferred from
|
||
the parent.
|
||
|
||
The strict source schema is
|
||
[`schemas/catalog-metadata.v1.schema.json`](schemas/catalog-metadata.v1.schema.json).
|
||
|
||
## Categories
|
||
|
||
Valid category slugs are declared in `categories.json`:
|
||
|
||
```text
|
||
productivity, development, business, creative, design, media,
|
||
communication, research, data, management
|
||
```
|
||
|
||
## Validation
|
||
|
||
Run these checks before submitting changes:
|
||
|
||
```bash
|
||
# Full market + i18n validation
|
||
uv run scripts/i18n/validate-i18n.py
|
||
|
||
# Catalog sidecar validator unit tests and standalone validation
|
||
uv run scripts/catalog/test_validate_catalog_metadata.py
|
||
uv run scripts/catalog/test_collection_generator.py
|
||
uv run scripts/catalog/validate_catalog_metadata.py
|
||
|
||
# Translation freshness check
|
||
uv run scripts/i18n/translate.py --check
|
||
|
||
# Verify pinned collection children without changing entry.json (network required;
|
||
# mutable collections are reported and skipped because their output is not reproducible)
|
||
uv run scripts/gen-collection-children.py --check
|
||
|
||
# Optional network check for entry.json source URLs
|
||
uv run scripts/i18n/validate-i18n.py --online
|
||
```
|
||
|
||
The validators check market stats, category references, `builtin-skills.json`,
|
||
`entry.json` structure, sidecar schema and legacy consistency, immutable source
|
||
evidence, collection identity, i18n completeness, and translation freshness.
|
||
Human-locked translations (`translated_by: human`) must keep `source_hash`
|
||
aligned after manual review. During a data migration,
|
||
`scripts/catalog/validate_catalog_metadata.py --require-complete` additionally
|
||
requires one sidecar for every top-level Agent, Team and Skill.
|
||
|
||
Detailed i18n guidance is in [docs/I18N.md](docs/I18N.md).
|
||
|
||
## License
|
||
|
||
MIT License. See [LICENSE](LICENSE).
|