Skill Wiki v0.1.0

文档 / implementation / runtime

本页目录

Runtime —— loader 与 resolver

@skill-wiki/runtime 读磁盘上的编译产物,把 metadata 加投影路径喂给 MCP server。 它从来不读 chunk 正文。

模块

模块角色
atom-loader.ts按原子读 atom.yamlgraph.yaml,不读 chunks。
index-loader.ts解析 _index.xml,构建内存里的 atom map。
projection-resolver.ts给一对 (atom, level),返回磁盘路径。
domain-config.ts递归发现 domain.yaml,再加上 DomainRegistry。
edge-walker.ts在内存边图上做 BFS / DFS。

启动时序

async function boot(primeDir: string) {
  // 1. Discover domain plugins.
  const domains = await discoverDomains(primeDir);
  for (const d of domains) DomainRegistry.register(d);

  // 2. Parse the index.
  const index = await loadIndex(`${primeDir}/_index.xml`);

  // 3. Build the in-memory graph.
  //    Atoms map id → metadata; no chunk content read here.
  const graph = buildGraph(index);

  return { domains, index, graph };
}

"永不读 chunk 内容"这条规矩

运行时契约把 chunks/{summary,core,full}.md 划在运行时之外。原因有三:

  • 跟 agent 的工作方式一致。agent 自带 Read 工具。在运行时再造一份只会引来格式漂移和缓存 bug。
  • 内存有界。chunk 内容随 corpus 大小膨胀,metadata 加 index 不会(哪怕 1k 个原子也才约 50 KB)。
  • 热重载。运行时可以热重载 index,又不必动 agent 已经看到的具体原子。
// packages/runtime/src/atom-loader.ts
//
// IMPORTANT: This module NEVER reads chunks/*.md content.
// It only reads _index.xml and atom.yaml (metadata).
// Chunk content is exclusively for the agent to pull via the Read tool.

边遍历器

MCP server 用它来满足 contract 解析、走 requires 链:

function walkRequires(seed: AtomMeta, depth = 5): AtomMeta[] {
  const out: AtomMeta[] = [];
  const seen = new Set<string>([seed.id]);
  const queue: [AtomMeta, number][] = [[seed, 0]];
  while (queue.length > 0) {
    const [atom, d] = queue.shift()!;
    if (d >= depth) continue;
    for (const edge of atom.edges) {
      if (edge.verb !== 'requires' || seen.has(edge.target)) continue;
      const target = byId.get(edge.target);
      if (!target) continue;
      seen.add(target.id);
      out.push(target);
      queue.push([target, d + 1]);
    }
  }
  return out;
}

对外 API

import { Runtime } from "@skill-wiki/runtime";

const rt = await Runtime.boot({ primeDir: "/path/to/compiled" });

// Lookup
const atom = rt.lookup("@recipes/method-pan-sauce");

// Resolve a projection (returns a path, NOT content)
const path = rt.resolveProjection(atom.id, "core");

// Walk
const deps = rt.walkRequires(atom);

// Domains
console.log(rt.domains);                  // [DomainConfig, ...]