@agent-loom/loom 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +69 -0
  2. package/dist/acp/client.d.ts +182 -0
  3. package/dist/acp/client.d.ts.map +1 -0
  4. package/dist/acp/client.js +432 -0
  5. package/dist/acp/client.js.map +1 -0
  6. package/dist/acp/index.d.ts +5 -0
  7. package/dist/acp/index.d.ts.map +1 -0
  8. package/dist/acp/index.js +3 -0
  9. package/dist/acp/index.js.map +1 -0
  10. package/dist/acp/run.d.ts +41 -0
  11. package/dist/acp/run.d.ts.map +1 -0
  12. package/dist/acp/run.js +32 -0
  13. package/dist/acp/run.js.map +1 -0
  14. package/dist/apply.d.ts +15 -6
  15. package/dist/apply.d.ts.map +1 -1
  16. package/dist/apply.js +78 -49
  17. package/dist/apply.js.map +1 -1
  18. package/dist/chat/chat.d.ts +108 -0
  19. package/dist/chat/chat.d.ts.map +1 -0
  20. package/dist/chat/chat.js +221 -0
  21. package/dist/chat/chat.js.map +1 -0
  22. package/dist/chat/discovery.d.ts +30 -0
  23. package/dist/chat/discovery.d.ts.map +1 -0
  24. package/dist/chat/discovery.js +68 -0
  25. package/dist/chat/discovery.js.map +1 -0
  26. package/dist/chat/frontmatter.d.ts +12 -0
  27. package/dist/chat/frontmatter.d.ts.map +1 -0
  28. package/dist/chat/frontmatter.js +11 -0
  29. package/dist/chat/frontmatter.js.map +1 -0
  30. package/dist/chat/index.d.ts +16 -0
  31. package/dist/chat/index.d.ts.map +1 -0
  32. package/dist/chat/index.js +11 -0
  33. package/dist/chat/index.js.map +1 -0
  34. package/dist/chat/registry.d.ts +73 -0
  35. package/dist/chat/registry.d.ts.map +1 -0
  36. package/dist/chat/registry.js +118 -0
  37. package/dist/chat/registry.js.map +1 -0
  38. package/dist/chat/resolve-agent.d.ts +39 -0
  39. package/dist/chat/resolve-agent.d.ts.map +1 -0
  40. package/dist/chat/resolve-agent.js +36 -0
  41. package/dist/chat/resolve-agent.js.map +1 -0
  42. package/dist/chat/suggest.d.ts +20 -0
  43. package/dist/chat/suggest.d.ts.map +1 -0
  44. package/dist/chat/suggest.js +55 -0
  45. package/dist/chat/suggest.js.map +1 -0
  46. package/dist/cli.js +627 -75
  47. package/dist/cli.js.map +1 -1
  48. package/dist/clone.d.ts +21 -3
  49. package/dist/clone.d.ts.map +1 -1
  50. package/dist/clone.js +240 -12
  51. package/dist/clone.js.map +1 -1
  52. package/dist/copilot/mcp.d.ts +48 -0
  53. package/dist/copilot/mcp.d.ts.map +1 -0
  54. package/dist/copilot/mcp.js +146 -0
  55. package/dist/copilot/mcp.js.map +1 -0
  56. package/dist/copilot/resolve.d.ts +33 -0
  57. package/dist/copilot/resolve.d.ts.map +1 -0
  58. package/dist/copilot/resolve.js +96 -0
  59. package/dist/copilot/resolve.js.map +1 -0
  60. package/dist/copilot/spawn.d.ts +51 -0
  61. package/dist/copilot/spawn.d.ts.map +1 -0
  62. package/dist/copilot/spawn.js +132 -0
  63. package/dist/copilot/spawn.js.map +1 -0
  64. package/dist/index.d.ts +19 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +15 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/launch/index.d.ts +10 -0
  69. package/dist/launch/index.d.ts.map +1 -0
  70. package/dist/launch/index.js +9 -0
  71. package/dist/launch/index.js.map +1 -0
  72. package/dist/launch/stage.d.ts +62 -0
  73. package/dist/launch/stage.d.ts.map +1 -0
  74. package/dist/launch/stage.js +108 -0
  75. package/dist/launch/stage.js.map +1 -0
  76. package/dist/manifest.d.ts +165 -18
  77. package/dist/manifest.d.ts.map +1 -1
  78. package/dist/manifest.js +980 -225
  79. package/dist/manifest.js.map +1 -1
  80. package/dist/renderers/claude.d.ts +5 -0
  81. package/dist/renderers/claude.d.ts.map +1 -1
  82. package/dist/renderers/claude.js +17 -3
  83. package/dist/renderers/claude.js.map +1 -1
  84. package/dist/renderers/copilot.d.ts +1 -1
  85. package/dist/renderers/copilot.d.ts.map +1 -1
  86. package/dist/renderers/copilot.js +205 -22
  87. package/dist/renderers/copilot.js.map +1 -1
  88. package/dist/repo-clone.js +17 -11
  89. package/dist/repo-clone.js.map +1 -1
  90. package/dist/resolve-template.d.ts +12 -4
  91. package/dist/resolve-template.d.ts.map +1 -1
  92. package/dist/resolve-template.js +39 -8
  93. package/dist/resolve-template.js.map +1 -1
  94. package/dist/run/index.d.ts +4 -0
  95. package/dist/run/index.d.ts.map +1 -0
  96. package/dist/run/index.js +2 -0
  97. package/dist/run/index.js.map +1 -0
  98. package/dist/run/run.d.ts +143 -0
  99. package/dist/run/run.d.ts.map +1 -0
  100. package/dist/run/run.js +406 -0
  101. package/dist/run/run.js.map +1 -0
  102. package/dist/search-registry.d.ts +10 -3
  103. package/dist/search-registry.d.ts.map +1 -1
  104. package/dist/search-registry.js +16 -16
  105. package/dist/search-registry.js.map +1 -1
  106. package/dist/sessions/index.d.ts +16 -0
  107. package/dist/sessions/index.d.ts.map +1 -0
  108. package/dist/sessions/index.js +15 -0
  109. package/dist/sessions/index.js.map +1 -0
  110. package/dist/sessions/store.d.ts +56 -0
  111. package/dist/sessions/store.d.ts.map +1 -0
  112. package/dist/sessions/store.js +220 -0
  113. package/dist/sessions/store.js.map +1 -0
  114. package/dist/sessions/types.d.ts +62 -0
  115. package/dist/sessions/types.d.ts.map +1 -0
  116. package/dist/sessions/types.js +5 -0
  117. package/dist/sessions/types.js.map +1 -0
  118. package/dist/skill-fetcher.d.ts.map +1 -1
  119. package/dist/skill-fetcher.js +5 -6
  120. package/dist/skill-fetcher.js.map +1 -1
  121. package/dist/types.d.ts +123 -41
  122. package/dist/types.d.ts.map +1 -1
  123. package/dist/types.js +12 -0
  124. package/dist/types.js.map +1 -1
  125. package/dist/util/binary-cache.d.ts +53 -0
  126. package/dist/util/binary-cache.d.ts.map +1 -0
  127. package/dist/util/binary-cache.js +211 -0
  128. package/dist/util/binary-cache.js.map +1 -0
  129. package/dist/util/frontmatter.d.ts +53 -0
  130. package/dist/util/frontmatter.d.ts.map +1 -0
  131. package/dist/util/frontmatter.js +85 -0
  132. package/dist/util/frontmatter.js.map +1 -0
  133. package/dist/util/loom-home.d.ts +19 -0
  134. package/dist/util/loom-home.d.ts.map +1 -0
  135. package/dist/util/loom-home.js +37 -0
  136. package/dist/util/loom-home.js.map +1 -0
  137. package/dist/util/workspace-folder.d.ts +29 -0
  138. package/dist/util/workspace-folder.d.ts.map +1 -0
  139. package/dist/util/workspace-folder.js +43 -0
  140. package/dist/util/workspace-folder.js.map +1 -0
  141. package/dist/validate.d.ts +7 -1
  142. package/dist/validate.d.ts.map +1 -1
  143. package/dist/validate.js +90 -17
  144. package/dist/validate.js.map +1 -1
  145. package/package.json +31 -2
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Staging — materialize a registry-resolved agent into a session workspace.
3
+ *
4
+ * The staging flow:
5
+ * 1. Generate a session id + compute the staged workspace path
6
+ * 2. Create the session record pointing at that workspace
7
+ * 3. Apply the registry template into `<session.dir>/workspace/`
8
+ * 4. Return a `ResolvedAgentRef` pointing at the staged agent file so the
9
+ * launch machinery can spawn against it unchanged.
10
+ *
11
+ * Manifest repos are cloned in `'auto'` mode by default — real-work agents
12
+ * (CRI triage, pool investigations, ...) reference these repos at runtime
13
+ * and a session without them stalls immediately. Lightweight callers can
14
+ * pass `cloneRepos: 'none'` to skip.
15
+ *
16
+ * Located under `src/launch/` (not `src/chat/`) so library consumers like
17
+ * `loom run`, the planned `startSpecialist` (#76), and `loom-peers-mcp`
18
+ * (#77) can stage without pulling in chat-only modules.
19
+ */
20
+ import { existsSync, readdirSync } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { applyTemplate } from '../apply.js';
23
+ import { createCraftFetcher } from '../skill-fetcher.js';
24
+ import { createSession, finalizeSession, generateSessionId, sessionsRoot, sessionWorkspaceDir, } from '../sessions/index.js';
25
+ /**
26
+ * Stage a registry-resolved agent into a new session workspace, ready to launch.
27
+ * Throws if `applyTemplate` fails to produce the expected agent file.
28
+ */
29
+ export async function stageRegistryAgent(options) {
30
+ const { hit, sessionName, runtime = 'copilot', onProgress, cloneRepos = 'auto', cloneMode, promptFn, linkFn, } = options;
31
+ // Precompute id + staged workspace path so the session's meta points at the
32
+ // actual location (not a placeholder we'd have to patch up afterwards).
33
+ const id = generateSessionId(hit.agentId);
34
+ const stagedWs = sessionWorkspaceDir(join(sessionsRoot(), id));
35
+ const session = createSession({
36
+ id,
37
+ agentId: hit.agentId,
38
+ agentName: hit.agent.name,
39
+ runtime,
40
+ workspaceDir: stagedWs,
41
+ origin: 'staged',
42
+ name: sessionName,
43
+ });
44
+ const stageStart = Date.now();
45
+ // Wrap the rest in try/catch so a thrown applyTemplate (or a missing
46
+ // agent file afterwards) doesn't leave an orphan `running` session in
47
+ // ~/.loom/sessions/. Failed stagings should appear as `errored` so
48
+ // `loom sessions list` reflects reality.
49
+ try {
50
+ // Apply the template. We select only the requested agent when the template
51
+ // has multiple; otherwise all nested agents get rendered (cheap, harmless).
52
+ await applyTemplate({
53
+ templateDir: hit.templatePath,
54
+ registryRoot: hit.registryRoot,
55
+ outputDir: stagedWs,
56
+ target: runtime,
57
+ skillFetcher: createCraftFetcher(),
58
+ agents: [hit.agentId],
59
+ cloneRepos: cloneRepos === 'none' ? undefined : cloneRepos,
60
+ cloneMode: cloneMode === 'partial' ? 'partial' : undefined,
61
+ promptFn,
62
+ linkFn,
63
+ onProgress,
64
+ });
65
+ // Discover what applyTemplate actually produced. The rendered filename is
66
+ // derived from the agent's frontmatter `name`, which may differ from the
67
+ // manifest's `agent.id` that the registry indexes under. Since we pass
68
+ // `agents: [hit.agentId]` above, only one agent is rendered — pick it.
69
+ const agentsDir = join(stagedWs, '.github', 'agents');
70
+ const expected = join(agentsDir, `${hit.agentId}.agent.md`);
71
+ let agentFilePath = expected;
72
+ let resolvedAgentId = hit.agentId;
73
+ if (!existsSync(expected)) {
74
+ const candidates = existsSync(agentsDir)
75
+ ? readdirSync(agentsDir).filter((f) => f.endsWith('.agent.md'))
76
+ : [];
77
+ if (candidates.length === 1) {
78
+ agentFilePath = join(agentsDir, candidates[0]);
79
+ // Strip the ".agent.md" suffix to get the effective id for downstream use.
80
+ resolvedAgentId = candidates[0].replace(/\.agent\.md$/, '');
81
+ }
82
+ else {
83
+ throw new Error(`Staging succeeded but could not resolve an agent file under ${agentsDir}.\n` +
84
+ ` Template: ${hit.templateId} (${hit.registryName})\n` +
85
+ ` Looked for: ${hit.agentId}.agent.md\n` +
86
+ ` Found: ${candidates.length === 0 ? '(none)' : candidates.join(', ')}`);
87
+ }
88
+ }
89
+ return {
90
+ session,
91
+ agent: {
92
+ agentId: resolvedAgentId,
93
+ agentFilePath,
94
+ workspaceDir: stagedWs,
95
+ source: 'workspace',
96
+ },
97
+ };
98
+ }
99
+ catch (err) {
100
+ finalizeSession(session, {
101
+ exitCode: null,
102
+ durationMs: Date.now() - stageStart,
103
+ status: 'errored',
104
+ });
105
+ throw err;
106
+ }
107
+ }
108
+ //# sourceMappingURL=stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage.js","sourceRoot":"","sources":["../../src/launch/stage.ts"],"names":[],"mappings":"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"}
@@ -4,38 +4,185 @@
4
4
  * Parses manifest.yaml files and resolves $ref / file / registry references
5
5
  * to produce a fully resolved manifest ready for rendering.
6
6
  */
7
- import type { Manifest, AgentManifest, ResolvedManifest } from './types.js';
7
+ import type { Manifest, ResolvedManifest, ResolvedSkill, ResolvedAgent, ResolvedMcp, SkillEntry, AgentEntry, McpEntry } from './types.js';
8
8
  /**
9
- * Parse a manifest.yaml file into a typed Manifest object.
9
+ * Validate that `name` is safe to use as a single filesystem path
10
+ * component (skill dir, prompt filename, agent slug). Frontmatter
11
+ * `name:` values flow into renderer paths; a malicious template can
12
+ * declare `name: ../../../.vscode/pwned` and have the renderer write
13
+ * outside the workspace. This helper closes that vector at the
14
+ * resolver layer so renderers never see an unsafe name.
10
15
  */
11
- export declare function parseManifest(manifestPath: string): Promise<Manifest>;
16
+ export declare function isSafePathSegment(name: string): boolean;
17
+ /**
18
+ * Resolve `ref` against `root`, then assert the result stays under
19
+ * `root` after symlink resolution. Throws on escape (absolute paths,
20
+ * `..` traversal, symlinks pointing out). Use for every manifest-
21
+ * controlled relative path before reading or writing it.
22
+ *
23
+ * Skips the realpath check if the file does not yet exist (e.g. a
24
+ * renderer about to write to it); returns the lexically-resolved path
25
+ * in that case. Callers that need realpath safety on an existing file
26
+ * should call after stat.
27
+ */
28
+ export declare function safeJoinUnder(root: string, ref: string): Promise<string>;
29
+ /**
30
+ * Parse a manifest into a typed Manifest object.
31
+ *
32
+ * Accepts either:
33
+ * - A path to a manifest file (`.../manifest.yaml` or `.../dobby.yaml`)
34
+ * - A path to a directory containing one of those filenames
35
+ *
36
+ * When given a directory, prefers `manifest.yaml`; falls back to
37
+ * `dobby.yaml` (with a one-time deprecation note). If both are
38
+ * present, prefers `manifest.yaml` and warns.
39
+ *
40
+ * Per U5/U6, field-name and layout aliases are normalized at parse time:
41
+ * - `mcpServers:` -> `mcp:`
42
+ * - `sparseCheckout:` -> `paths:` (+ `sparse: true`)
43
+ * - `team:` -> `template:`
44
+ * - flat top-level resources -> wrapped in synthetic `contents:`
45
+ * Each kind of alias triggers a once-per-session deprecation warning.
46
+ * See normalizeManifestAliases.
47
+ */
48
+ export declare function parseManifest(pathOrDir: string): Promise<Manifest>;
49
+ /**
50
+ * Resolve a path-or-directory argument into the actual manifest file path.
51
+ *
52
+ * - If the path is a file, returns it unchanged.
53
+ * - If the path is a directory, probes `manifest.yaml` first (canonical),
54
+ * then `dobby.yaml` (legacy alias). Logs a one-time deprecation
55
+ * warning when falling back to `dobby.yaml`.
56
+ * - Throws if neither is found.
57
+ *
58
+ * Exported so callers (e.g. validate.ts) can probe for a manifest using
59
+ * the same rules without re-reading the file.
60
+ */
61
+ export declare function resolveManifestPath(pathOrDir: string): Promise<string>;
62
+ /**
63
+ * Walk a freshly-loaded manifest YAML object and rename dobby-style
64
+ * field names to loom's canonical names. The input object is shallow-
65
+ * cloned; the caller's object is never mutated. Each alias triggers a
66
+ * one-time deprecation warning per session.
67
+ *
68
+ * Aliases supported:
69
+ * - top-level `team:` -> `template:` (only when `template:` absent)
70
+ * - top-level `mcpServers:` -> `mcp:` (also recognized inside `contents:`)
71
+ * - per-repo entry: `sparseCheckout:` -> `paths:` (also sets
72
+ * `sparse: true` when no explicit `sparse:` key is given)
73
+ * - flat layout: top-level `instructions:` / `skills:` / `agents:` /
74
+ * `mcp:` / `repos:` / `prompts:` are hoisted into a synthetic
75
+ * `contents:` block when `contents:` is absent. Per U6, this
76
+ * collapses the dobby-format flat layout into the canonical
77
+ * contents:-wrapped layout that resolveManifest expects.
78
+ *
79
+ * Filename-level aliases (e.g. dobby.yaml -> manifest.yaml) are
80
+ * handled in `resolveManifestPath` before this function runs.
81
+ */
82
+ export declare function normalizeManifestAliases(raw: unknown, sourcePath?: string): unknown;
83
+ /**
84
+ * Test-only: clear the once-per-session dedup so subsequent calls log
85
+ * again. Production code should never need to call this.
86
+ */
87
+ export declare function _resetAliasDeprecationsForTest(): void;
12
88
  /**
13
89
  * Resolve all $ref, file, and registry references in a parsed manifest.
14
90
  *
91
+ * The returned `ResolvedManifest.mcp` carries TEAM-LEVEL MCPs only.
92
+ * Per-agent MCPs (from each agent file's frontmatter `mcp-servers:`
93
+ * block) live on each `ResolvedAgent.mcp` instead -- populated by
94
+ * `resolveAgentEntries` directly during resolution. The copilot
95
+ * renderer reads them to emit per-agent `mcp-servers:` frontmatter
96
+ * blocks (loom#122 / loom#127). U4.5 collapsed the legacy nested
97
+ * `agents/<id>/manifest.yaml` mode into the agent file's own
98
+ * frontmatter -- the resolver now reads one file per agent.
99
+ *
15
100
  * @param manifest - Parsed manifest (from parseManifest)
16
101
  * @param templateDir - Absolute path to the template directory (contains manifest.yaml)
17
102
  * @param registryRoot - Absolute path to the registry root (contains shared/)
18
103
  */
19
- export declare function resolveManifest(manifest: Manifest, templateDir: string, registryRoot: string): Promise<ResolvedManifest>;
104
+ export interface ResolveManifestOptions {
105
+ /**
106
+ * Optional agent selection from `loom apply --agent`. When set, legacy
107
+ * nested agent manifest contents are merged only for selected agents so
108
+ * agent-specific repos/skills do not leak into small selected-agent applies.
109
+ */
110
+ agents?: string[];
111
+ }
112
+ export declare function resolveManifest(manifest: Manifest, templateDir: string, registryRoot: string, options?: ResolveManifestOptions): Promise<ResolvedManifest>;
113
+ /**
114
+ * Resolve a list of skill entries (registry / file / discover) into
115
+ * `ResolvedSkill[]`. Exposed so adapters (e.g. the dobby adapter) can
116
+ * pump entries through the same code path used by `resolveManifest`
117
+ * rather than re-implementing skill discovery.
118
+ *
119
+ * Each entry expands to zero, one, or many ResolvedSkill values:
120
+ * - `registry:` -> 1 entry (registry coordinates only, no content)
121
+ * - `file:` -> 1 entry (SKILL.md content + extra files)
122
+ * - `discover:` -> N entries (one per immediate subdirectory of each
123
+ * listed dir that contains a SKILL.md). Within a discover entry,
124
+ * later paths override earlier ones on duplicate skill names
125
+ * (preserving "team skills override shared skills" semantics).
126
+ *
127
+ * No cross-entry deduplication is performed -- callers that need it
128
+ * apply their own pass after concatenating the result.
129
+ */
130
+ export declare function resolveSkillEntries(entries: SkillEntry[], templateDir: string, log?: (msg: string) => void): Promise<ResolvedSkill[]>;
20
131
  /**
21
- * Parse an agent manifest.yaml file (per-agent within a team template).
132
+ * Resolve a list of agent entries (file: or discover:) into
133
+ * `ResolvedAgent[]`. Exposed so adapters (e.g. the dobby adapter) can
134
+ * pump entries through the same code path used by `resolveManifest`
135
+ * rather than re-implementing agent loading + frontmatter parsing.
136
+ *
137
+ * Each entry expands to zero, one, or many ResolvedAgent values:
138
+ * - `file:` -> 1 entry (read agent.md, parse frontmatter for ALL
139
+ * metadata: name, description, model, tools, mcp-servers).
140
+ * - `discover:` -> N entries (one per immediate subdir containing
141
+ * an `*.agent.md`). Within a discover entry, later paths
142
+ * override earlier ones on duplicate agent ids.
143
+ *
144
+ * Per U4, the .agent.md frontmatter is the only source of agent
145
+ * metadata. Manifest entries declare routing (the file path) only;
146
+ * model/tools overrides at the entry level are not honored. Per U4.5,
147
+ * the same applies to per-agent MCPs: an agent file's frontmatter
148
+ * `mcp-servers:` block is the single source of per-agent MCP
149
+ * declarations. The block is a map keyed by server id; each value
150
+ * carries the same fields as a top-level inline MCP entry (type,
151
+ * command, args, url, env, binary, ...).
152
+ *
153
+ * Across the entries array, later entries override earlier ones on
154
+ * duplicate agent ids -- so caller order encodes precedence
155
+ * (consistent with U2's skill-discovery rule).
22
156
  */
23
- export declare function parseAgentManifest(manifestPath: string): Promise<AgentManifest>;
157
+ export declare function resolveAgentEntries(entries: AgentEntry[], templateDir: string, log?: (msg: string) => void, registryRoot?: string): Promise<ResolvedAgent[]>;
24
158
  /**
25
- * Discover nested agent directories within a template.
26
- * Returns agent directory names if the template has an agents/ subdirectory
27
- * where each subdir contains a manifest.yaml.
159
+ * Derive the stable agent identifier from a source file path. This
160
+ * is the slug callers use to look the agent up at launch time and
161
+ * the basename of the rendered `.agent.md` file. Two layouts:
162
+ *
163
+ * - Loom nested layout: `agents/<id>/agent.md` -> id = `<id>`
164
+ * - Dobby / flat layout: `<id>.agent.md` -> id = `<id>`
165
+ *
166
+ * The function picks the parent dir name when it looks like a
167
+ * loom-nested layout (parent dir is non-trivial and not `agents/`);
168
+ * otherwise it falls back to the basename without the `.agent.md`
169
+ * extension.
28
170
  */
29
- export declare function discoverNestedAgents(templateDir: string): Promise<string[]>;
171
+ export declare function deriveAgentIdFromSourcePath(sourcePath: string): string;
30
172
  /**
31
- * Merge a team manifest with one or more agent manifests to produce
32
- * a combined manifest ready for resolving.
173
+ * Resolve a list of MCP entries (shared $ref or inline) into
174
+ * `ResolvedMcp[]`. Exposed for adapters that resolve per-agent MCP
175
+ * blocks separately from the team-level ones (loom#127).
176
+ *
177
+ * Inline entries with a `binary:` block (and no explicit `command`) are
178
+ * routed through the binary cache: on first use the asset is fetched
179
+ * from the GitHub release into ~/.loom/mcp-binaries/ and the absolute
180
+ * cache path becomes the resolved `command`. If resolution fails the
181
+ * entry passes through with an undefined command and downstream
182
+ * launch surfaces a clear error.
33
183
  *
34
- * Merge rules:
35
- * - repos: agent only (team repos are NOT included)
36
- * - mcp, instructions, skills, prompts, prerequisites: union (team + agent)
37
- * - agents: built from agent.md files in selected agents
38
- * - targets: inherited from team
184
+ * Pure: reads YAML for $ref entries, no provenance tagging, no
185
+ * dedup. The caller decides how to combine results.
39
186
  */
40
- export declare function mergeTeamAndAgentManifests(teamManifest: Manifest, agentManifests: AgentManifest[], agentDirs: string[]): Manifest;
187
+ export declare function resolveMcpEntries(entries: McpEntry[], registryRoot: string, log?: (msg: string) => void): Promise<ResolvedMcp[]>;
41
188
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EACb,gBAAgB,EAmBjB,MAAM,YAAY,CAAC;AAYpB;;GAEG;AACH,wBAAsB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAK3E;AAMD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAgRD;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAIrF;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,QAAQ,EACtB,cAAc,EAAE,aAAa,EAAE,EAC/B,SAAS,EAAE,MAAM,EAAE,GAClB,QAAQ,CAuDV"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAEhB,aAAa,EAEb,aAAa,EACb,WAAW,EASX,UAAU,EACV,UAAU,EACV,QAAQ,EAMT,MAAM,YAAY,CAAC;AAyBpB;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASvD;AAaD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B9E;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAMxE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgC5E;AAwCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,OAAO,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CA2FT;AAqDD;;;GAGG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAMD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAkC3B;AAmKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,UAAU,EAAE,EACrB,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,GACpC,OAAO,CAAC,aAAa,EAAE,CAAC,CAyC1B;AA0JD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,UAAU,EAAE,EACrB,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,EACrC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAwD1B;AAoND;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAOtE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,QAAQ,EAAE,EACnB,YAAY,EAAE,MAAM,EACpB,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,GACpC,OAAO,CAAC,WAAW,EAAE,CAAC,CAoDxB"}