Merge branch 'stack/agent-profiles-3-wire' into stack/agent-profiles-5-web-ui

# Conflicts:
#	apps/cli/tests/web-agent-presets.e2e.ts
#	packages/host/apiproxy/tests/api-proxy-agent-preset.spec.ts
This commit is contained in:
Yichen Jiang
2026-08-09 22:48:47 +08:00
44 changed files with 809 additions and 236 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/self-modification/repository-plugin/README.md
README.md: 794d176dc69bf45ca61472e081bf2bf623851761
README.zh.md: 6d8428e6baa75fe37fefa2d2c55ae73ca450dc1a
README.md: 666f00e02b9ab33bff348df6b4ff90e3f3bfecc7
README.zh.md: b09f68bc17a4eb08df6ecbb3782e14bf26fb7d7f

View File

@@ -122,7 +122,6 @@ Stable registrations preserve the owning surface's normal prefix behavior. Loadi
## Known Limitations and Deferred Work
- **Skill contributions do not reach preset-composed sessions** — `dsh.skills` mounts a host-plane provider into the host `skills` registry, but a composition whose agent plane lives behind agent presets moves that registry into each preset's private realm: the wrapper then has no host registry to wait on, and a host-registered catalog would not reach any session's model-facing skill surface either. Until the skills registry grows the host+per-scope layering the tools registry has (or repository skills are delivered as directories a preset's provider scans), a preset-composed deployment should not declare `dsh.skills`; MCP and entry contributions are unaffected because the tools registry is host-plane and layered.
- **No code sandbox** — `dsh.entry`, npm dependencies, and package lifecycle scripts execute with the DSH host's authority; repository trust is mandatory.
- **Entry-only service dependencies are not pre-gated** — the generated wrapper cannot declare an entry module's `inject` before importing it. Any service beyond those implied by Skills or MCP must already exist when the wrapper mounts the entry, or that repository generation rejects.
- **No MCP authentication protocol** — static headers may use environment expansion, but OAuth-bearing definitions reject and private-server login flows are not implemented here.

View File

@@ -122,7 +122,6 @@ Namespace 插件:具名导出 `name``inject``apply`、准备阶段常量
## 已知限制与暂缓事项
- **skill 贡献到达不了由 preset 组装的会话**`dsh.skills` 会把一个宿主面 provider 挂进宿主 `skills` 注册表,而 agent 面移入 agent preset 的组合把该注册表搬进了每个 preset 的私有 realm此时包装层没有可等待的宿主注册表即便注册进宿主目录也到不了任何会话面向模型的 skill 面。在 skills 注册表获得 tools 注册表那样的宿主+按作用域分层(或 repository skill 改为以目录交付、由 preset 的 provider 扫描之前preset 组装的部署不应声明 `dsh.skills`MCP 与入口贡献不受影响,因为 tools 注册表在宿主面且分层。
- **没有代码沙箱**`dsh.entry`、NPM 依赖和包生命周期脚本以 DSH 宿主权限执行;必须信任该 repository。
- **入口专用服务依赖不会预先门控**:生成的包装层无法在导入入口模块前声明其 `inject`。除 skill 或 MCP 隐含的服务外,其他任何服务在包装层挂载入口时都必须已经存在,否则该 repository generation 会被拒绝。
- **没有 MCP 认证协议**:静态 header 可以使用环境变量展开,但带 OAuth 的定义会被拒绝,私有 server 登录流程不在此实现。

View File

@@ -916,27 +916,27 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
},
{
key: 'skills',
summary: 'Registry of skill providers.',
summary: 'Layered registry of skill providers, the host+per-scope shape the tools registry established.',
methods: [
{
signature: 'registerProvider(create: (control: SkillProviderControl) => SkillProvider): () => void',
jsDoc: '/**\n * Register a borrowed same-process provider synchronously during plugin apply. Duplicate and\n * reserved names throw; remote initialization belongs in `list()`. Fiber disposal unregisters\n * the provider and invalidates catalog caches.\n * @param create - synchronous factory receiving this registration\'s lifecycle and invalidation control.\n * @returns the exact Cordis effect disposer that unregisters this provider;\n * composite effects may yield it directly to preserve teardown ordering.\n */',
jsDoc: '/**\n * Register a borrowed same-process provider synchronously during plugin\n * apply, into the calling context\'s layer: a scoped context (an agent\n * preset\'s standing mount) registers for that scope alone, an unscoped\n * context registers globally. Duplicate names within one layer and reserved\n * names throw; remote initialization belongs in `list()`. Fiber disposal\n * unregisters the provider and invalidates catalog caches.\n * @param create - synchronous factory receiving this registration\'s lifecycle and invalidation control.\n * @returns the exact Cordis effect disposer that unregisters this provider;\n * composite effects may yield it directly to preserve teardown ordering.\n */',
},
{
signature: 'register(skill: SkillRegistration): () => void',
jsDoc: '/**\n * Register a borrowed readonly runtime skill. Project entries outrank runtime entries, which\n * outrank user entries. Same-name runtime entries are first-wins; a duplicate logs a warning and\n * receives a no-op disposer so it cannot remove the winner.\n * @param skill - the skill definition input; omitted invocation and provider fields receive defaults.\n * @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.\n */',
jsDoc: '/**\n * Register a borrowed readonly runtime skill into the calling context\'s\n * layer. Project entries outrank runtime entries, which outrank user\n * entries, within one layer. Same-name runtime entries in one layer are\n * first-wins; a duplicate logs a warning and receives a no-op disposer so\n * it cannot remove the winner.\n * @param skill - the skill definition input; omitted invocation and provider fields receive defaults.\n * @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.\n */',
},
{
signature: 'async list(options: SkillLookupOptions = {}): Promise<SkillSummary[]>',
jsDoc: '/**\n * List invocation-neutral skill summaries for a workspace. Consumers apply\n * model or user invocation policy at their operational boundary. Lookup\n * options and provider candidates are readonly same-process values borrowed\n * throughout discovery.\n * @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.\n * @returns all sorted winning summaries.\n */',
signature: 'async list(options: SkillViewOptions = {}): Promise<SkillSummary[]>',
jsDoc: '/**\n * List invocation-neutral skill summaries for a workspace. Consumers apply\n * model or user invocation policy at their operational boundary. Lookup\n * options and provider candidates are readonly same-process values borrowed\n * throughout discovery.\n * @param options - view options; `scope` selects the viewing agent\'s layers, `cwd` selects project roots, and `signal` cancels discovery.\n * @returns all sorted winning summaries.\n */',
},
{
signature: 'async snapshot(options: SkillLookupOptions = {}): Promise<SkillCatalogSnapshot>',
jsDoc: '/**\n * Observe the current invocation-neutral catalog and whether discovery completed within a stable revision.\n * Incomplete observations are never cached, allowing consumers to retain last-good state and\n * retry on their next request boundary.\n * @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.\n * @returns sorted summaries plus discovery-completeness state.\n */',
signature: 'async snapshot(options: SkillViewOptions = {}): Promise<SkillCatalogSnapshot>',
jsDoc: '/**\n * Observe the current invocation-neutral catalog and whether discovery completed within a stable revision.\n * Incomplete observations are never cached, allowing consumers to retain last-good state and\n * retry on their next request boundary.\n * @param options - view options; `scope` selects the viewing agent\'s layers, `cwd` selects project roots, and `signal` cancels discovery.\n * @returns sorted summaries plus discovery-completeness state.\n */',
},
{
signature: 'async get(name: string, options: SkillLookupOptions = {}): Promise<SkillDefinition | undefined>',
jsDoc: '/**\n * Load and validate the winning candidate, passing its opaque discovery locator back to the\n * provider. Cancellation is rechecked after selection, including cache hits, and raced against\n * loading so an uncooperative provider cannot hang the caller.\n * @param name - kebab-case skill name.\n * @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.\n * @returns the full skill, including body content, or `undefined`.\n */',
signature: 'async get(name: string, options: SkillViewOptions = {}): Promise<SkillDefinition | undefined>',
jsDoc: '/**\n * Load and validate the winning candidate, passing its opaque discovery locator back to the\n * provider. Cancellation is rechecked after selection, including cache hits, and raced against\n * loading so an uncooperative provider cannot hang the caller.\n * @param name - kebab-case skill name.\n * @param options - view options; `scope` selects the viewing agent\'s layers,\n * `cwd` selects workspace-sensitive skills, and `signal` cancels work.\n * @returns the full skill, including body content, or `undefined`.\n */',
},
],
},
@@ -2849,6 +2849,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'SkillSummary',
declaration: 'export interface SkillSummary {\n readonly name: string;\n readonly description: string;\n readonly whenToUse?: string;\n readonly invocation: SkillInvocationPolicy;\n readonly source: SkillSource;\n readonly provider: string;\n readonly resourceBase?: SkillResourceBase;\n}',
},
{
name: 'SkillViewOptions',
declaration: 'export interface SkillViewOptions extends SkillLookupOptions {\n readonly scope?: ScopeKey | undefined;\n}',
},
{
name: 'SpillLocator',
declaration: 'export type SpillLocator = Branded<\'SpillLocator\'>;',