feat: Agent-led application installation and durable instance maintenance (#15)

* feat: 支持任意材料的 Agent 自主安装与实例维护

* docs: retain legacy safeguards and explain installation host binding

* docs: explain issued local material references and validation recovery
This commit is contained in:
2026-09-23 17:44:23 +08:00
committed by GitHub
parent b29360ed8d
commit 532fad2aba
4 changed files with 164 additions and 8 deletions

View File

@@ -2,7 +2,7 @@
"name": "DesireCore", "name": "DesireCore",
"$schema": "http://desirecore/schemas/agent-seed.json", "$schema": "http://desirecore/schemas/agent-seed.json",
"id": "7da73b7f-bb08-4e7b-a3cf-5d4af6e22c7f", "id": "7da73b7f-bb08-4e7b-a3cf-5d4af6e22c7f",
"version": "1.14.0", "version": "1.14.1",
"requiredClientVersion": "10.0.170", "requiredClientVersion": "10.0.170",
"description": "系统中枢调度器,负责任务分发、Agent 编排与全局状态监控", "description": "系统中枢调度器,负责任务分发、Agent 编排与全局状态监控",
"author": "DesireCore Team", "author": "DesireCore Team",

View File

@@ -1,8 +1,8 @@
--- ---
name: 应用安装管理 name: 应用安装管理
description: 安装、升级、卸载或检查应用;读取固定资料,复用执行工具核验后记录结果。处理 ApplicationManagement 请求;旧服务 RegistryCatalogAcquisition 请求按需读取兼容指南。 description: 根据目标、README、源码、SQL、配置或目录材料自主安装、维护和核验软件,登记实际实例。统一交接与记账,不要求标准安装脚本。兼容旧应用和服务协议。
version: "1.5.2" version: "1.6.0"
requiredClientVersion: "10.0.170" requiredClientVersion: "10.0.172"
type: procedural type: procedural
risk_level: high risk_level: high
status: enabled status: enabled
@@ -12,7 +12,7 @@ provides:
tags: [installation, registry, app-management] tags: [installation, registry, app-management]
metadata: metadata:
author: desirecore author: desirecore
updated_at: "2026-09-19" updated_at: "2026-09-22"
--- ---
# 应用安装管理 # 应用安装管理
@@ -23,7 +23,11 @@ Agent 理解环境并执行;已有工具提供能力;Agent Service 只可靠
## L1:选择路径 ## L1:选择路径
读取当前请求中的唯一 `ApplicationManagement=<JSON>`,以及明确目标设备。应用使用 [资料与记账接口](references/recording-api.md)。普通自然语言任务可以先用现有目录检索确认唯一来源和目标,再构造同样的结构化请求;不能按显示名或聊天旧片段猜身份。 读取当前请求中的唯一 `ApplicationManagement=<JSON>`,以及明确目标设备。
- `application-management-v2` 使用 [自主安装与实例接口](references/agent-led-installation.zh-CN.md)([English](references/agent-led-installation.md))。普通自然语言安装也构造这个协议;目录引用可选,材料可为空。软件无需提供安装 API 或标准脚本。
- `application-observation-v1` 按 [原资料与记账接口](references/recording-api.md) 保留固定版本兼容;不能把 v2 悄悄降级为 v1 或文件写入。
- v2 必须在任何软件副作用之前调用解析端点并核对返回协议;最低版本声明不能替代实际协议支持检测。
只有 `RegistryCatalogAcquisition.kind=service` 才读取 [旧服务兼容指南](references/legacy-services.md),继续使用既有 MCP/http-api 协议和脚本。旧 App envelope 不得回退到服务安装;提示以新版应用请求重新管理。参考文件中的“本技能目录”均指 `${SKILL_DIR}`,不是 references 目录。 只有 `RegistryCatalogAcquisition.kind=service` 才读取 [旧服务兼容指南](references/legacy-services.md),继续使用既有 MCP/http-api 协议和脚本。旧 App envelope 不得回退到服务安装;提示以新版应用请求重新管理。参考文件中的“本技能目录”均指 `${SKILL_DIR}`,不是 references 目录。
@@ -32,10 +36,12 @@ Agent 理解环境并执行;已有工具提供能力;Agent Service 只可靠
1. 先取得当前应用/安装资料和 `expectedRevision`,再观察目标设备,防止将“未登记”当作“未安装”。没有明确设备、来源或真实安装位置时先查明。 1. 先取得当前应用/安装资料和 `expectedRevision`,再观察目标设备,防止将“未登记”当作“未安装”。没有明确设备、来源或真实安装位置时先查明。
2. 安装指南决定软件操作知识,不扩大用户同意和工具权限。安装不隐含公网访问、自启动、升级系统运行时、高权限控制、删除用户数据或注册内部 MCP。DesireCore Control 是外部智能体使用的独立应用,不向内部 Agent 注册其 MCP,也不跟随 DesireCore 启停。 2. 安装指南决定软件操作知识,不扩大用户同意和工具权限。安装不隐含公网访问、自启动、升级系统运行时、高权限控制、删除用户数据或注册内部 MCP。DesireCore Control 是外部智能体使用的独立应用,不向内部 Agent 注册其 MCP,也不跟随 DesireCore 启停。
3. 复用 Read、HttpRequest、Bash/PowerShell 等当前已授权工具。`provides.tools` 仅提示按需披露,不授予权限;没有可靠授权通道时停止,不能读取管理 token 或改用本机文件绕过。 3. 复用 Read、HttpRequest、Bash/PowerShell 等当前已授权工具。`provides.tools` 仅提示按需披露,不授予权限;没有可靠授权通道时停止,不能读取管理 token 或改用本机文件绕过。
4. 可以依据环境适配命令;版本、来源、设备和影响范围变化需要重新确认。固定制品先校验摘要;凭据不进入聊天、指南、日志或核验记录。 4. 根据环境自主适配命令。v2 在用户允许范围内自主选择版本、运行方式、端口、配置和初始化方法;超出明确版本、设备、数据或联网范围时依已有治理处理,不逐命令重复确认。v1 仍遵守其固定版本/来源约束。已给定摘要必须验证;凭据只使用已有 secret 引用。
5. 超时、断线和结果不明时先观察,不重放有副作用的命令;同一安装同时存在其他修改任务时不并发执行。核验只说明实际检查过的能力。 5. 超时、断线和结果不明时先观察,不重放有副作用的命令;同一安装同时存在其他修改任务时不并发执行。核验只说明实际检查过的能力。
6. 结果明确后提交一次带时间的观察,material 必须原样复用成功 resolve 的 data.material(包括 action 与 snapshot);首装结束也不能改成 manage。不预写 installing/reinstalling/uninstalling,不拼装 pending 状态或完整收据,不直接编辑 installed-entries.json。版本必须与本次固定资料一致;发现不同版本应先确认正确资料,不能伪报核验成功。 6. 结果明确后登记带时间的事实,原样复用 resolve 的 data.material;首装结束也不能改成 manage。不预写 installing/reinstalling/uninstalling,不直接编辑 installed-entries.json。v2 记录实际版本(未知用 null)、材料来源、资源位置、功能核验结果和持久化维护说明。软件存在但初始化未完成,登记 present/incomplete;结果未知先调查,不登记 absent。v1 保留固定版本一致性要求。
7. 记账失败只重读并处理记录,不重复安装/卸载。记录修订冲突要重新观察,不能只换 expectedRevision。异常时按需读取 [恢复原则](references/recovery.md)。 7. 记账失败只重读并处理记录,不重复安装/卸载。记录修订冲突要重新观察,不能只换 expectedRevision。异常时按需读取 [恢复原则](references/recovery.md)。
8. 卸载仅移除已核验的应用包/安装目录;不能因为位于同一前缀就递归清理父目录。未知文件、同级数据、凭据和日志默认保留;额外删除必须逐项说明并另获确认。清理空父目录只用非递归删除,非空就保留。 8. 卸载仅移除已核验的应用包/安装目录;不能因为位于同一前缀就递归清理父目录。未知文件、同级数据、凭据和日志默认保留;额外删除必须逐项说明并另获确认。清理空父目录只用非递归删除,非空就保留。
9. 证据引用使用工具实际返回的调用 ID、真实会话日志位置或本次已保存的核验报告路径,不编造 session:…:step:… 标识;没有可追溯引用就先保存不含秘密的报告。 9. 证据引用使用工具实际返回的调用 ID、真实会话日志位置或本次已保存的核验报告路径,不编造 session:…:step:… 标识;没有可追溯引用就先保存不含秘密的报告。
10. 最后说明软件的实际结果与记录是否提交成功;二者可能不同。进度留在当前会话/既有任务;不得承诺无人执行的后续修复或“所有失败都已回滚”。 10. 最后说明软件的实际结果与记录是否提交成功;二者可能不同。进度留在当前会话/既有任务;不得承诺无人执行的后续修复或“所有失败都已回滚”。
11. v2 在现有文件化 Plan 中保存 requestId、installationId、实际资源定位和验证方式;副作用前领取资源占用。同一任务恢复沿用标识;占用冲突先协调,不并发修改实际目标。过程不是平台安装状态机。
12. SQL 先辨认新库/已有库及初始化/迁移,检查 schema 与执行历史。中断后不得盲目重放,不假设 DDL 总能事务回滚。核验需验证目标身份及约定功能,端口响应或容器运行不能单独证明软件可用。

View File

@@ -0,0 +1,75 @@
# Agent-led installation and maintenance (v2)
[简体中文](agent-led-installation.zh-CN.md)
Use the active Agent Service's existing HttpRequest capability and authenticated context. These APIs resolve context, coordinate resources and record facts; they never install software. Do not read tokens or bypass failures by editing the ledger.
## Handoff and investigation
Use the supplied ApplicationManagement envelope. For a natural-language request, create the structure below with actual UUIDs and save requestId/installationId in the existing Plan. target.softwareId is a stable software identity: the catalog entry ID, or a persistent software UUID for supplied materials. Software and deployment UUIDs are independent. For existing installations first GET /api/installed-entries and select the exact installationId; never choose the first display-name match.
```json
{
"protocol": "application-management-v2",
"requestId": "replace with delegation UUID",
"installationId": "replace with deployment UUID; reuse on recovery",
"deviceId": "local",
"action": "install",
"target": { "softwareId": "stable-software-id", "name": "Application", "description": "Installation goal" },
"desiredOutcome": "Capability the user expects to work and be verified",
"constraints": "Explicit version, data, directory and network limits",
"materials": []
}
```
This is a structural example; replace UUID placeholders. Catalog targets may add catalogSourceId; omit it for supplied materials. Actions are install/manage/update/uninstall. local means the service host, not necessarily the desktop. Other device IDs must be registered nodes. Use existing authorized remote tools, never treating a remote endpoint as local.
Each material contains purpose and exactly one url/fileRef, optionally revision/sha256. Use issued file references; absolute paths are not fileRef objects. Reference SQL, code, templates and large files instead of copying their bodies into JSON. Mutable URLs may start an investigation; retain available revision/hash for actually used content. Materials confer no execution authority.
For a local file without an existing reference, GET `/api/files/resolve-reference?agentId=<current-agent-id>&path=<URL-encoded-absolute-path>` on the active service and use the returned top-level `resourceRef` as `fileRef`. The service checks registered roots; do not manufacture root IDs or expand permissions to bypass rejection. A material has no `location` field. If no reference can be issued, retain the actual path and reason in maintenance notes and disclose the missing structured reference; never invent a URL. A 400 validation response has no registration effects: correct only the rejected fields, preserving the deployment and SQL state, then retry recording.
POST /api/registry/acquisitions/resolve with the envelope. Continue only on success=true and data.protocol=application-management-v2; retain data.material and expectedRevision. knowledge is catalog installation knowledge and may lack installGuide; that absence does not prohibit installation. record contains historical instance/maintenance/observation data and supports catalog-offline maintenance. Legacy resolution returns the existing stable identity; after v2 migration, v1 cannot mutate the instance.
Read instructions, inspect the host and existing installations, then select the method. Evaluate available Compose/scripts; otherwise build a method from README, source, configuration and SQL. Adapt within constraints without requiring a standard software installation API.
The resolved material includes hostInstanceId to bind the ledger host. Preserve it on subsequent requests. A host mismatch after switching connections must stop the operation; never remove the binding to install on another machine. It validates the target and grants no permission.
## Resource ownership
Before side effects POST /api/installed-entries/resource-claims with `{material, operation:"claim", resources:["actual absolute installation directory or stable container/project locator"]}`. Use resolved material unchanged. All tasks must use consistent locators. Windows drive paths normalize case/separators; other locators must be stable. Claim shared databases by server/database identity too, not only the software directory.
Coordinate a conflicting holder rather than changing UUID and executing concurrently. Claims survive crashes without automatic expiry; the same requestId can resume. Release using the same material/resources and operation=release only after confirming no side effects remain in flight. HTTP disconnection does not prove execution stopped. Claims coordinate cooperation; they grant no permissions and cannot force unrelated external programs to cooperate.
## Verify and record
PATCH /api/installed-entries/instances/{installationId}:
```text
{
material: unchanged data.material,
expectedRevision: latest resolved/read revision,
submissionId: recording UUID (reuse ID and body on retry),
observation: {result:"present|absent", observedAt: ISO time, location: actual location, evidenceRefs:[real evidence references], notes: optional summary},
verification: {readiness:"verified|incomplete|failed|notChecked", scope: actual checks, remainingWork: remaining work or empty string},
deployment: {
method: actual method, actualVersion: observed version or null,
resources: [stable actual locators], dataLocations: [preserved data locations],
materials: [actually used references and available provenance],
maintenance: secret-free Markdown maintenance notes (maximum 32768 characters)
}
}
```
Existing resources with failed database initialization mean present + incomplete/failed, not completed installation. verified requires the agreed capability check and empty remainingWork. Inspect actual schema/migration facts after SQL interruption or duplicate requests; never blindly replay. Confirm a responding port belongs to this instance. Record absent only after confirming software removal, retaining preserved-data locations.
Maintenance notes persist within the instance record. Include actual version, resource/data locations, identification/opening methods, initialization/migration history, verification, update/removal preservation rules and unfinished work. Reference larger materials durably; do not rely exclusively on expiring URLs, temporary attachments or session caches. Later Agents read these notes; the platform does not execute them.
Recording does not require the catalog to remain listed. Structure, host/owner, material scope and revision are still checked. Report software results and recording results separately on failure.
## Recovery and maintenance
GET /api/installed-entries/instances/{installationId} returns record/revision. After a lost response, read first. If observation.requestId matches submissionId, retrying the identical body returns replayed=true without reinstalling. On revision conflict reread and investigate; do not merely replace expectedRevision. Unknown legacy facts remain unknown.
GET /api/installed-entries/instances/{installationId}/history/{revision} retrieves previous maintenance records; current observation.baseRevision points to the previous record. Updating notes preserves earlier materials. A new conversation reads record.installation for target/provenance/maintenance, investigates current state, then opens, repairs, updates or removes the instance. Historical verification is not live health.
Existing user installations may be adopted after inspection without reinstalling. Remove only the precise instance's software, preserving data by default; additional data deletion follows existing permissions. Failure implies neither automatic rollback nor successful removal. Investigate unknown outcomes; recording idempotency is not exactly-once command execution.

View File

@@ -0,0 +1,75 @@
# Agent 自主安装与维护(v2)
[English](agent-led-installation.md)
所有请求使用活动 Agent Service 的既有 HttpRequest 能力及身份上下文。接口只解析、互斥和记账,不替你安装。不得读取 token 或直接写账本绕过失败。
## 交接与调查
如果用户已提供 ApplicationManagement,原样使用;否则用真实 UUID 构造下面的对象,将 requestId、installationId 写入现有 Plan。target.softwareId 是稳定软件 ID,目录软件取目录 entryId;自带材料软件生成软件 UUID,后续复用。安装实例 UUID 与软件 UUID 各自独立。维护已有实例必须先 GET /api/installed-entries,按精确身份选择 installationId,不按名称取第一条。
```json
{
"protocol": "application-management-v2",
"requestId": "替换为本次委派 UUID",
"installationId": "替换为部署 UUID,恢复时复用",
"deviceId": "local",
"action": "install",
"target": { "softwareId": "稳定软件ID", "name": "软件名", "description": "安装目标" },
"desiredOutcome": "用户希望完成并验证的功能",
"constraints": "用户明确的版本、数据、目录和网络范围",
"materials": []
}
```
这是结构示意,UUID 占位文字必须替换。目录软件可在 target 添加 catalogSourceId;非目录软件不填。action 支持 install/manage/update/uninstall。local 指服务宿主,不一定是界面设备;其他 deviceId 必须是该服务已登记节点。远程命令走已有授权远程工具,不把远程 URL 当本机入口。
materials 每项含 purpose 和 url 或 fileRef(二选一),可附 revision、sha256。fileRef 使用已有签发引用;不要把绝对路径冒充 fileRef。SQL、源码、模板和大文件用引用,不复制正文到 JSON。URL 可以先浮动,再保存实际使用内容的 revision/hash;材料不是执行授权。
本地文件没有现成引用时,向活动服务 GET `/api/files/resolve-reference?agentId=<当前智能体ID>&path=<URL编码的绝对路径>`,将返回的顶层 `resourceRef` 作为 `fileRef`。服务会检查已登记根;不得编造 rootId 或扩大权限绕过拒绝。材料没有 `location` 字段。无法签发引用时,在维护说明保留实际路径和原因,并披露结构化引用缺失,不编造 URL。400 校验失败未写入登记:只修正被拒字段,保留已有部署和 SQL 状态,然后重试登记。
POST /api/registry/acquisitions/resolve,body 为上述对象。只有 success=true 且 data.protocol=application-management-v2 才继续,保存 data.material 与 expectedRevision。knowledge 是目录安装知识,可能没有 installGuide;缺失不等于禁止安装。record 包含历史实例、maintenance 和 observation。目录离线时使用已有实例资料继续。读到旧 v1 实例时,兼容解析返回其稳定 ID;写入 v2 后不可用 v1 修改。
解析后 material 中的 hostInstanceId 绑定账本宿主;后续请求必须原样保留。连接切换导致宿主不匹配时停止,不删除绑定去安装另一台机器。它用于目标核对,不授予权限。
读取说明、检查宿主和已有安装后,自主决定实际方法;有 Compose/脚本就评估使用,没有就根据 README、源码、配置和 SQL 形成方案。在约束内自行排错,无需软件实现统一安装接口。
## 实际资源占用
副作用前 POST /api/installed-entries/resource-claims:`{material, operation:"claim", resources:["实际绝对安装目录或稳定的容器/项目定位符"]}`。material 使用 resolve 原文。所有任务对同一资源使用同一种定位方式;Windows 盘符目录会规范大小写/分隔符,其他 locator 应保持稳定。共享数据库还要按服务器/库名领取占用,不能只锁软件目录。
冲突时先协调持有任务,不能换 UUID 并发执行。崩溃后不自动过期;同 requestId 可以恢复。只有确认当前请求没有在途副作用后,用相同 material/resources 和 operation=release 释放。不要因为 HTTP 断线就释放仍在执行的操作。资源占用只是协作互斥,不增加工具权限,也不保证外部程序都遵守。
## 验证并登记
PATCH /api/installed-entries/instances/{installationId}:
```text
{
material: data.material 原文,
expectedRevision: 最近解析/重读的 revision,
submissionId: 本次登记 UUID(重试保留 ID 与正文),
observation: {result:"present|absent", observedAt: ISO时间, location: 实际位置, evidenceRefs:[真实证据引用], notes: 可选摘要},
verification: {readiness:"verified|incomplete|failed|notChecked", scope: 实际核验范围, remainingWork: 剩余事项或空字符串},
deployment: {
method: 实际采用的方法说明, actualVersion: 实测版本或null,
resources: [稳定实际定位符], dataLocations: [需要保留的数据位置],
materials: [实际使用材料的引用与可取得来源证据],
maintenance: 不含凭据的Markdown维护说明(最多32768字符)
}
}
```
软件资源存在但数据库初始化失败:present + incomplete/failed,不报安装完成。verified 必须验证约定功能,remainingWork 为空。SQL 中断/重复提交先检查目标 schema/迁移事实,不能盲目重放;端口有响应时确认是本实例。只有确认部署被移除才写 absent,业务数据保留位置继续记录。
maintenance 与实例同条持久化,必须写清实际版本、资源/数据位置、辨认及打开方法、已执行初始化与迁移、验证方法、更新/卸载保留规则和剩余工作。大材料可使用持久文件引用;不要只留下会过期的 URL、临时附件或会话缓存。维护说明由后续 Agent 阅读,不由平台直接执行。
登记 API 不重新要求当前目录上架,因此已发生事实可记录;结构、宿主/所有者、材料作用域及 revision 仍校验。提交失败时分别报告软件结果与登记结果。
## 恢复与后续维护
GET /api/installed-entries/instances/{installationId} 返回 record、revision。响应丢失先读;若记录 observation.requestId 等于 submissionId,按原正文重试可得到 replayed=true,不重装。revision 冲突先重读并调查,不能只改 expectedRevision 强行覆盖。旧记录未知字段不补造。
历史维护资料可通过 GET /api/installed-entries/instances/{installationId}/history/{revision} 读取;当前 observation.baseRevision 指向前次记录。更新维护说明不会静默丢弃旧资料。新会话从 record.installation 读取目标、来源及维护说明,核验当前实际状态后再打开、修复、更新或卸载;不把历史核验当实时健康。
已有用户安装可以先观察后纳管,不默认重装。卸载仅移除精确实例的软件资源,默认保留数据;额外数据删除按现有权限处理。失败不代表自动回滚或已卸载。操作结果未知时先调查,绝不因登记幂等而推断软件命令也是 exactly-once。