diff --git a/builtin-skills.json b/builtin-skills.json index d55027e..f70c406 100644 --- a/builtin-skills.json +++ b/builtin-skills.json @@ -1,5 +1,6 @@ { "skills": [ + "configuring-compute", "create-agent", "dashscope-image-gen", "delete-agent", diff --git a/manifest.json b/manifest.json index ea4e5f7..e0d6574 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "DesireCore Official Market", - "version": "1.2.6", + "version": "1.2.7", "schemaVersion": "1.1.0", "supportedLocales": ["zh-CN", "en-US"], "defaultLocale": "en-US", @@ -27,8 +27,8 @@ }, "stats": { "totalAgents": 1, - "totalSkills": 25, - "lastUpdated": "2026-06-15" + "totalSkills": 26, + "lastUpdated": "2026-07-07" }, "features": [ "verified-only", diff --git a/skills/configuring-compute/CHANGELOG.md b/skills/configuring-compute/CHANGELOG.md new file mode 100644 index 0000000..92397b2 --- /dev/null +++ b/skills/configuring-compute/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## [1.0.0] - 2026-07-07 + +- 首个版本:通过 Agent Service HTTP API 配置算力供应商与 API Key +- 密钥只写不读安全模型(secrets 端点只写、config 响应掩码、明文查看仅限用户 UI) +- 完整流程:查看配置 → 创建/更新 provider → 写入密钥 → 验证 → 启用/同步模型 → reload 刷新 diff --git a/skills/configuring-compute/SKILL.md b/skills/configuring-compute/SKILL.md new file mode 100644 index 0000000..ff18aa3 --- /dev/null +++ b/skills/configuring-compute/SKILL.md @@ -0,0 +1,195 @@ +--- +name: configuring-compute +description: >- + Configure compute providers (model API endpoints and API keys) for the user + via the Agent Service HTTP API: create/update providers, write API keys + (write-only), verify them, and reload the configuration. Use when the user + asks to add or configure a model provider, set an API key, or fix compute + configuration. 用户要求配置算力、添加模型供应商或设置 API Key 时使用。 +version: 1.0.0 +type: meta +risk_level: medium +status: enabled +disable-model-invocation: true +tags: + - compute + - provider + - configuration + - meta +metadata: + author: desirecore + updated_at: '2026-07-07' + i18n: + default_locale: en-US + source_locale: zh-CN + locales: + - zh-CN + - en-US + zh-CN: + name: 配置算力 + short_desc: 帮用户配置模型供应商与 API Key(密钥只写不读) + description: >- + 通过 Agent Service HTTP API 为用户配置算力供应商(模型 API 端点与 API Key): + 创建/更新 provider、写入 API Key(只写)、验证密钥、刷新配置。 + Use when 用户要求添加或配置模型供应商、设置 API Key、修复算力配置。 + body: ./SKILL.zh-CN.md + translated_by: human + en-US: + name: Configure Compute + short_desc: Configure model providers and API keys for the user (keys are write-only) + description: >- + Configure compute providers (model API endpoints and API keys) for the user + via the Agent Service HTTP API: create/update providers, write API keys + (write-only), verify them, and reload the configuration. Use when the user + asks to add or configure a model provider, set an API key, or fix compute configuration. + body: ./SKILL.md + translated_by: human +market: + icon: >- + + category: productivity + channel: latest + maintainer: + name: DesireCore Official + verified: true +--- + +# Configure Compute + +Help the user configure compute providers — model API endpoints and API keys — +through the Agent Service HTTP API. + +## Security model (read this first, non-negotiable) + +- **API keys are write-only.** You can create and overwrite keys; you can NEVER + read an existing key back. There is no API that returns key plaintext to you, + `GET /api/compute/config` returns masked values only, and the runtime blocks + file reads of `secrets.json` (Read/Grep tools and shell commands alike). +- **Do not try to work around this.** Never attempt to read + `~/.desirecore/config/secrets.json`, never echo a key the user gave you back + into chat more than necessary, never store keys anywhere except via + `POST /api/compute/secrets`. +- If the user asks "what is my current key", answer: keys cannot be read back; + they can only be replaced. Point them to the provider settings UI, which has + a user-only reveal control. + +## How to call the API + +- Prefer the `Bash` tool with `curl`. The API base URL is already injected into + the "Local API" section of the system prompt; reference it directly. +- On Windows without Git Bash, use the `HttpRequest` tool with the same URLs. + +## Workflow + +### 1. Inspect current configuration + +```bash +curl -s $BASE/api/compute/config +``` + +Response contains `providers[]` where `apiKey` is a **masked display value** +(first 4 chars + bullets) and `hasApiKey: boolean` tells you whether a key is +configured. Use this to decide between creating a new provider and updating an +existing one. Never treat the masked `apiKey` as a real key. + +### 2. Create a provider (if needed) + +```bash +curl -s -X POST $BASE/api/compute/providers \ + -H 'Content-Type: application/json' \ + -d '{ + "provider": "deepseek", + "label": "DeepSeek", + "baseUrl": "https://api.deepseek.com", + "services": ["chat"], + "apiFormat": "openai-completions", + "priceCurrency": "CNY" + }' +``` + +Required fields: `provider`, `label`, `baseUrl`, `services`. The response +returns the created provider with its generated `id` — keep it for later steps. +Known provider presets and model lists are available via +`GET /api/compute/pi-providers` and `GET /api/compute/pi-models/:provider`. + +### 3. Set the API key (write-only) + +Ask the user for the key. Reuse the provider's existing `apiKeyRef` if set; +otherwise generate one like `key-` and attach it to the provider: + +```bash +# Write the secret (write-only endpoint; there is no GET counterpart) +curl -s -X POST $BASE/api/compute/secrets \ + -H 'Content-Type: application/json' \ + -d '{"ref": "key-abc123", "value": ""}' + +# Attach the ref to the provider if it was not set yet +curl -s -X PUT $BASE/api/compute/providers/ \ + -H 'Content-Type: application/json' \ + -d '{"apiKeyRef": "key-abc123"}' +``` + +### 4. Verify the key + +```bash +curl -s -X POST $BASE/api/compute/verify-key \ + -H 'Content-Type: application/json' \ + -d '{"provider": "deepseek", "baseUrl": "https://api.deepseek.com", "apiKeyRef": "key-abc123", "apiFormat": "openai-completions"}' +``` + +Returns `{ valid, latencyMs, errorMessage?, suggestedBaseUrl? }`. If +`suggestedBaseUrl` is present, offer to update the provider's `baseUrl`. + +### 5. Enable and populate models + +```bash +curl -s -X PUT $BASE/api/compute/providers/ \ + -H 'Content-Type: application/json' -d '{"enabled": true}' + +# Optional: sync the model list from the built-in registry +curl -s -X POST $BASE/api/compute/sync-models/ +``` + +### 6. Reload so the UI reflects the change + +Always finish with: + +```bash +curl -s -X POST $BASE/api/compute/reload +``` + +This re-validates the configuration and broadcasts a refresh event to the +client UI. Report the returned `providerCount` / `enabledProviderCount` / +`modelCount` to the user as confirmation. + +## Endpoint reference + +| Method | Path | Purpose | +| ------ | ---- | ------- | +| GET | `/api/compute/config` | Full config; `apiKey` masked + `hasApiKey` | +| POST | `/api/compute/providers` | Create provider | +| PUT | `/api/compute/providers/:id` | Patch provider (label/baseUrl/enabled/apiFormat/apiKeyRef/...) | +| DELETE | `/api/compute/providers/:id` | Remove provider | +| POST | `/api/compute/secrets` | Write key `{ref, value}` — **write-only** | +| DELETE | `/api/compute/secrets/:ref` | Delete key | +| POST | `/api/compute/verify-key` | Probe a key end-to-end | +| POST | `/api/compute/sync-models/:id` | Sync model list from registry | +| POST | `/api/compute/reload` | Re-validate config + broadcast UI refresh | +| GET | `/api/compute/pi-providers` | Known provider presets | +| GET | `/api/compute/pi-models/:provider` | Known models for a preset | + +## Error handling + +| Symptom | Cause | Action | +| ------- | ----- | ------ | +| 400 on create | Missing required field / unknown field | Fix the request body (schema is strict, `additionalProperties: false`) | +| 404 on PUT | Wrong provider id | Re-list via GET config | +| `valid: false` on verify | Wrong key / wrong baseUrl / wrong apiFormat | Show `errorMessage` to the user; try `suggestedBaseUrl` if present | +| 403 anywhere | You tried a credential-gated endpoint (key reveal) | Stop — that endpoint is for the human user's UI only | + +## Confirmation etiquette + +- Before overwriting an existing key (`hasApiKey: true`), confirm with the user. +- Before deleting a provider or key, confirm with the user. +- After finishing, summarize what changed (provider, enabled state, model count) + without repeating the key value. diff --git a/skills/configuring-compute/SKILL.zh-CN.md b/skills/configuring-compute/SKILL.zh-CN.md new file mode 100644 index 0000000..fddd3c2 --- /dev/null +++ b/skills/configuring-compute/SKILL.zh-CN.md @@ -0,0 +1,130 @@ +# 配置算力 + +通过 Agent Service HTTP API 帮用户配置算力供应商——模型 API 端点与 API Key。 + +## 安全模型(先读这里,不可协商) + +- **API Key 只写不读。** 你可以创建和覆盖密钥,但**永远无法**读回已有密钥。 + 没有任何 API 会向你返回密钥明文:`GET /api/compute/config` 只返回掩码值, + 运行时同时拦截对 `secrets.json` 的文件读取(Read/Grep 工具与 shell 命令一律拒绝)。 +- **不要尝试绕过。** 不要读取 `~/.desirecore/config/secrets.json`,不要在对话中 + 超出必要地回显用户提供的密钥,除 `POST /api/compute/secrets` 外不要在任何地方存放密钥。 +- 如果用户问「我现在的 key 是什么」,回答:密钥无法读回,只能替换; + 可引导用户到供应商设置页,那里有仅限用户本人的明文查看控件。 + +## 如何调用 API + +- 优先使用 `Bash` 工具 + `curl`。API 基础地址已注入到 system prompt 的 + 「本机 API」小节,直接引用即可。 +- Windows 无 Git Bash 时,用 `HttpRequest` 工具调用相同 URL。 + +## 工作流程 + +### 1. 查看当前配置 + +```bash +curl -s $BASE/api/compute/config +``` + +响应中的 `providers[]` 里 `apiKey` 是**掩码展示值**(前 4 位 + 圆点), +`hasApiKey: boolean` 表示是否已配置密钥。据此决定是新建 provider 还是更新现有的。 +掩码 `apiKey` 不是真实密钥,不要当作密钥使用。 + +### 2. 创建 provider(如需要) + +```bash +curl -s -X POST $BASE/api/compute/providers \ + -H 'Content-Type: application/json' \ + -d '{ + "provider": "deepseek", + "label": "DeepSeek", + "baseUrl": "https://api.deepseek.com", + "services": ["chat"], + "apiFormat": "openai-completions", + "priceCurrency": "CNY" + }' +``` + +必填字段:`provider`、`label`、`baseUrl`、`services`。响应返回创建的 provider +及其生成的 `id`——后续步骤要用。已知供应商预设与模型列表可通过 +`GET /api/compute/pi-providers` 和 `GET /api/compute/pi-models/:provider` 获取。 + +### 3. 设置 API Key(只写) + +向用户索取密钥。provider 已有 `apiKeyRef` 则复用;否则生成一个形如 +`key-<随机串>` 的引用名并挂到 provider 上: + +```bash +# 写入密钥(只写端点,没有对应的 GET) +curl -s -X POST $BASE/api/compute/secrets \ + -H 'Content-Type: application/json' \ + -d '{"ref": "key-abc123", "value": "<用户提供的API_KEY>"}' + +# 如果 provider 还没有 apiKeyRef,补挂上去 +curl -s -X PUT $BASE/api/compute/providers/ \ + -H 'Content-Type: application/json' \ + -d '{"apiKeyRef": "key-abc123"}' +``` + +### 4. 验证密钥 + +```bash +curl -s -X POST $BASE/api/compute/verify-key \ + -H 'Content-Type: application/json' \ + -d '{"provider": "deepseek", "baseUrl": "https://api.deepseek.com", "apiKeyRef": "key-abc123", "apiFormat": "openai-completions"}' +``` + +返回 `{ valid, latencyMs, errorMessage?, suggestedBaseUrl? }`。若返回 +`suggestedBaseUrl`,主动提议更新 provider 的 `baseUrl`。 + +### 5. 启用并填充模型 + +```bash +curl -s -X PUT $BASE/api/compute/providers/ \ + -H 'Content-Type: application/json' -d '{"enabled": true}' + +# 可选:从内置注册表同步模型列表 +curl -s -X POST $BASE/api/compute/sync-models/ +``` + +### 6. 刷新配置让 UI 生效 + +收尾必做: + +```bash +curl -s -X POST $BASE/api/compute/reload +``` + +该端点重新校验配置并向客户端 UI 广播刷新事件。把返回的 `providerCount` / +`enabledProviderCount` / `modelCount` 报告给用户作为完成确认。 + +## 端点速查 + +| 方法 | 路径 | 用途 | +| ---- | ---- | ---- | +| GET | `/api/compute/config` | 完整配置;`apiKey` 为掩码 + `hasApiKey` | +| POST | `/api/compute/providers` | 创建 provider | +| PUT | `/api/compute/providers/:id` | 局部更新(label/baseUrl/enabled/apiFormat/apiKeyRef/...) | +| DELETE | `/api/compute/providers/:id` | 删除 provider | +| POST | `/api/compute/secrets` | 写入密钥 `{ref, value}` —— **只写** | +| DELETE | `/api/compute/secrets/:ref` | 删除密钥 | +| POST | `/api/compute/verify-key` | 端到端验证密钥 | +| POST | `/api/compute/sync-models/:id` | 从注册表同步模型列表 | +| POST | `/api/compute/reload` | 重新校验配置 + 广播 UI 刷新 | +| GET | `/api/compute/pi-providers` | 已知供应商预设 | +| GET | `/api/compute/pi-models/:provider` | 预设供应商的已知模型 | + +## 错误处理 + +| 现象 | 原因 | 处理 | +| ---- | ---- | ---- | +| 创建时 400 | 缺必填字段 / 携带未知字段 | 修正请求体(schema 严格,`additionalProperties: false`) | +| PUT 时 404 | provider id 错误 | 重新 GET config 拿列表 | +| 验证 `valid: false` | 密钥错 / baseUrl 错 / apiFormat 错 | 把 `errorMessage` 转告用户;有 `suggestedBaseUrl` 则尝试 | +| 任何端点 403 | 误触凭证门控端点(明文查看) | 立即停止——该端点仅供人类用户的 UI 使用 | + +## 确认礼仪 + +- 覆盖已有密钥(`hasApiKey: true`)前,先向用户确认。 +- 删除 provider 或密钥前,先向用户确认。 +- 完成后向用户总结变更内容(provider、启用状态、模型数量),不要复述密钥值。