@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.
- package/README.md +69 -0
- package/dist/acp/client.d.ts +182 -0
- package/dist/acp/client.d.ts.map +1 -0
- package/dist/acp/client.js +432 -0
- package/dist/acp/client.js.map +1 -0
- package/dist/acp/index.d.ts +5 -0
- package/dist/acp/index.d.ts.map +1 -0
- package/dist/acp/index.js +3 -0
- package/dist/acp/index.js.map +1 -0
- package/dist/acp/run.d.ts +41 -0
- package/dist/acp/run.d.ts.map +1 -0
- package/dist/acp/run.js +32 -0
- package/dist/acp/run.js.map +1 -0
- package/dist/apply.d.ts +15 -6
- package/dist/apply.d.ts.map +1 -1
- package/dist/apply.js +78 -49
- package/dist/apply.js.map +1 -1
- package/dist/chat/chat.d.ts +108 -0
- package/dist/chat/chat.d.ts.map +1 -0
- package/dist/chat/chat.js +221 -0
- package/dist/chat/chat.js.map +1 -0
- package/dist/chat/discovery.d.ts +30 -0
- package/dist/chat/discovery.d.ts.map +1 -0
- package/dist/chat/discovery.js +68 -0
- package/dist/chat/discovery.js.map +1 -0
- package/dist/chat/frontmatter.d.ts +12 -0
- package/dist/chat/frontmatter.d.ts.map +1 -0
- package/dist/chat/frontmatter.js +11 -0
- package/dist/chat/frontmatter.js.map +1 -0
- package/dist/chat/index.d.ts +16 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +11 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/registry.d.ts +73 -0
- package/dist/chat/registry.d.ts.map +1 -0
- package/dist/chat/registry.js +118 -0
- package/dist/chat/registry.js.map +1 -0
- package/dist/chat/resolve-agent.d.ts +39 -0
- package/dist/chat/resolve-agent.d.ts.map +1 -0
- package/dist/chat/resolve-agent.js +36 -0
- package/dist/chat/resolve-agent.js.map +1 -0
- package/dist/chat/suggest.d.ts +20 -0
- package/dist/chat/suggest.d.ts.map +1 -0
- package/dist/chat/suggest.js +55 -0
- package/dist/chat/suggest.js.map +1 -0
- package/dist/cli.js +627 -75
- package/dist/cli.js.map +1 -1
- package/dist/clone.d.ts +21 -3
- package/dist/clone.d.ts.map +1 -1
- package/dist/clone.js +240 -12
- package/dist/clone.js.map +1 -1
- package/dist/copilot/mcp.d.ts +48 -0
- package/dist/copilot/mcp.d.ts.map +1 -0
- package/dist/copilot/mcp.js +146 -0
- package/dist/copilot/mcp.js.map +1 -0
- package/dist/copilot/resolve.d.ts +33 -0
- package/dist/copilot/resolve.d.ts.map +1 -0
- package/dist/copilot/resolve.js +96 -0
- package/dist/copilot/resolve.js.map +1 -0
- package/dist/copilot/spawn.d.ts +51 -0
- package/dist/copilot/spawn.d.ts.map +1 -0
- package/dist/copilot/spawn.js +132 -0
- package/dist/copilot/spawn.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/launch/index.d.ts +10 -0
- package/dist/launch/index.d.ts.map +1 -0
- package/dist/launch/index.js +9 -0
- package/dist/launch/index.js.map +1 -0
- package/dist/launch/stage.d.ts +62 -0
- package/dist/launch/stage.d.ts.map +1 -0
- package/dist/launch/stage.js +108 -0
- package/dist/launch/stage.js.map +1 -0
- package/dist/manifest.d.ts +165 -18
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +980 -225
- package/dist/manifest.js.map +1 -1
- package/dist/renderers/claude.d.ts +5 -0
- package/dist/renderers/claude.d.ts.map +1 -1
- package/dist/renderers/claude.js +17 -3
- package/dist/renderers/claude.js.map +1 -1
- package/dist/renderers/copilot.d.ts +1 -1
- package/dist/renderers/copilot.d.ts.map +1 -1
- package/dist/renderers/copilot.js +205 -22
- package/dist/renderers/copilot.js.map +1 -1
- package/dist/repo-clone.js +17 -11
- package/dist/repo-clone.js.map +1 -1
- package/dist/resolve-template.d.ts +12 -4
- package/dist/resolve-template.d.ts.map +1 -1
- package/dist/resolve-template.js +39 -8
- package/dist/resolve-template.js.map +1 -1
- package/dist/run/index.d.ts +4 -0
- package/dist/run/index.d.ts.map +1 -0
- package/dist/run/index.js +2 -0
- package/dist/run/index.js.map +1 -0
- package/dist/run/run.d.ts +143 -0
- package/dist/run/run.d.ts.map +1 -0
- package/dist/run/run.js +406 -0
- package/dist/run/run.js.map +1 -0
- package/dist/search-registry.d.ts +10 -3
- package/dist/search-registry.d.ts.map +1 -1
- package/dist/search-registry.js +16 -16
- package/dist/search-registry.js.map +1 -1
- package/dist/sessions/index.d.ts +16 -0
- package/dist/sessions/index.d.ts.map +1 -0
- package/dist/sessions/index.js +15 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/store.d.ts +56 -0
- package/dist/sessions/store.d.ts.map +1 -0
- package/dist/sessions/store.js +220 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/sessions/types.d.ts +62 -0
- package/dist/sessions/types.d.ts.map +1 -0
- package/dist/sessions/types.js +5 -0
- package/dist/sessions/types.js.map +1 -0
- package/dist/skill-fetcher.d.ts.map +1 -1
- package/dist/skill-fetcher.js +5 -6
- package/dist/skill-fetcher.js.map +1 -1
- package/dist/types.d.ts +123 -41
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -1
- package/dist/util/binary-cache.d.ts +53 -0
- package/dist/util/binary-cache.d.ts.map +1 -0
- package/dist/util/binary-cache.js +211 -0
- package/dist/util/binary-cache.js.map +1 -0
- package/dist/util/frontmatter.d.ts +53 -0
- package/dist/util/frontmatter.d.ts.map +1 -0
- package/dist/util/frontmatter.js +85 -0
- package/dist/util/frontmatter.js.map +1 -0
- package/dist/util/loom-home.d.ts +19 -0
- package/dist/util/loom-home.d.ts.map +1 -0
- package/dist/util/loom-home.js +37 -0
- package/dist/util/loom-home.js.map +1 -0
- package/dist/util/workspace-folder.d.ts +29 -0
- package/dist/util/workspace-folder.d.ts.map +1 -0
- package/dist/util/workspace-folder.js +43 -0
- package/dist/util/workspace-folder.js.map +1 -0
- package/dist/validate.d.ts +7 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +90 -17
- package/dist/validate.js.map +1 -1
- package/package.json +31 -2
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace + agent discovery for `loom <agent>` and `loom agents`.
|
|
3
|
+
*
|
|
4
|
+
* - `findWorkspaceRoot(cwd)`: walk up the directory tree looking for a
|
|
5
|
+
* `.github/agents/` directory. Matches git's "find-root" ergonomics so
|
|
6
|
+
* users don't have to be at the exact workspace root.
|
|
7
|
+
* - `listWorkspaceAgents(workspaceDir)`: enumerate `.agent.md` files under
|
|
8
|
+
* `.github/agents/` with their parsed frontmatter metadata.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
11
|
+
import { dirname, join, resolve } from 'node:path';
|
|
12
|
+
import { parseAgentFrontmatter } from './frontmatter.js';
|
|
13
|
+
/**
|
|
14
|
+
* Walk up from `cwd` looking for a directory that contains `.github/agents/`.
|
|
15
|
+
* Returns the absolute path of that directory, or null if no such ancestor
|
|
16
|
+
* exists (including the filesystem root).
|
|
17
|
+
*/
|
|
18
|
+
export function findWorkspaceRoot(cwd) {
|
|
19
|
+
let current = resolve(cwd);
|
|
20
|
+
// Guard against infinite loops on edge cases where dirname() is a no-op.
|
|
21
|
+
let safety = 64;
|
|
22
|
+
while (safety-- > 0) {
|
|
23
|
+
const candidate = join(current, '.github', 'agents');
|
|
24
|
+
if (existsSync(candidate)) {
|
|
25
|
+
try {
|
|
26
|
+
if (statSync(candidate).isDirectory())
|
|
27
|
+
return current;
|
|
28
|
+
}
|
|
29
|
+
catch { /* ignore and keep walking */ }
|
|
30
|
+
}
|
|
31
|
+
const parent = dirname(current);
|
|
32
|
+
if (parent === current)
|
|
33
|
+
return null;
|
|
34
|
+
current = parent;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* List all agents in a workspace's `.github/agents/` directory.
|
|
40
|
+
* Returns an empty array if the directory doesn't exist.
|
|
41
|
+
*/
|
|
42
|
+
export function listWorkspaceAgents(workspaceDir) {
|
|
43
|
+
const agentDir = join(workspaceDir, '.github', 'agents');
|
|
44
|
+
if (!existsSync(agentDir))
|
|
45
|
+
return [];
|
|
46
|
+
let entries;
|
|
47
|
+
try {
|
|
48
|
+
entries = readdirSync(agentDir);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
const agents = [];
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
if (!entry.endsWith('.agent.md'))
|
|
56
|
+
continue;
|
|
57
|
+
const agentId = entry.slice(0, -'.agent.md'.length);
|
|
58
|
+
const agentFilePath = join(agentDir, entry);
|
|
59
|
+
agents.push({
|
|
60
|
+
agentId,
|
|
61
|
+
agentFilePath,
|
|
62
|
+
metadata: parseAgentFrontmatter(agentFilePath),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
agents.sort((a, b) => a.agentId.localeCompare(b.agentId));
|
|
66
|
+
return agents;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/chat/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAYzD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,yEAAyE;IACzE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,OAAO,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;oBAAE,OAAO,OAAO,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC,CAAC,6BAA6B,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAyB,EAAE,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC;YAAE,SAAS;QAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC;YACV,OAAO;YACP,aAAa;YACb,QAAQ,EAAE,qBAAqB,CAAC,aAAa,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backwards-compatible re-exports of the frontmatter parser.
|
|
3
|
+
*
|
|
4
|
+
* The implementation lives under `src/util/frontmatter.ts` because every
|
|
5
|
+
* layer (chat, run, renderers, manifest) needs it — having it here forced
|
|
6
|
+
* renderers and util code to depend on a chat module. Existing imports
|
|
7
|
+
* from `./chat/frontmatter.js` still work via these re-exports, but new
|
|
8
|
+
* code should import from `../util/frontmatter.js`.
|
|
9
|
+
*/
|
|
10
|
+
export { parseFrontmatterRaw, stripFrontmatter, parseAgentFrontmatter, } from '../util/frontmatter.js';
|
|
11
|
+
export type { AgentMetadata } from '../util/frontmatter.js';
|
|
12
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/chat/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backwards-compatible re-exports of the frontmatter parser.
|
|
3
|
+
*
|
|
4
|
+
* The implementation lives under `src/util/frontmatter.ts` because every
|
|
5
|
+
* layer (chat, run, renderers, manifest) needs it — having it here forced
|
|
6
|
+
* renderers and util code to depend on a chat module. Existing imports
|
|
7
|
+
* from `./chat/frontmatter.js` still work via these re-exports, but new
|
|
8
|
+
* code should import from `../util/frontmatter.js`.
|
|
9
|
+
*/
|
|
10
|
+
export { parseFrontmatterRaw, stripFrontmatter, parseAgentFrontmatter, } from '../util/frontmatter.js';
|
|
11
|
+
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/chat/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public exports for the chat module.
|
|
3
|
+
* See `chat.ts` for behavior.
|
|
4
|
+
*/
|
|
5
|
+
export { chat, buildChatCommand, defaultPreChatBanner } from './chat.js';
|
|
6
|
+
export type { ChatOptions, ChatResult, LaunchRuntimeKind, PreLaunchInfo, } from './chat.js';
|
|
7
|
+
export { resolveAgentInWorkspace } from './resolve-agent.js';
|
|
8
|
+
export type { ResolvedAgentRef, ResolveAgentOptions } from './resolve-agent.js';
|
|
9
|
+
export { findWorkspaceRoot, listWorkspaceAgents } from './discovery.js';
|
|
10
|
+
export type { WorkspaceAgentInfo } from './discovery.js';
|
|
11
|
+
export { parseAgentFrontmatter } from './frontmatter.js';
|
|
12
|
+
export type { AgentMetadata } from './frontmatter.js';
|
|
13
|
+
export { suggestClosest, levenshtein } from './suggest.js';
|
|
14
|
+
export { resolveAgentFromRegistry, listRegistryAgentIds, listRegistryAgents, } from './registry.js';
|
|
15
|
+
export type { RegistryAgentHit, RegistryAgentListing, ResolveAgentFromRegistryOptions, } from './registry.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACzE,YAAY,EACV,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACxE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public exports for the chat module.
|
|
3
|
+
* See `chat.ts` for behavior.
|
|
4
|
+
*/
|
|
5
|
+
export { chat, buildChatCommand, defaultPreChatBanner } from './chat.js';
|
|
6
|
+
export { resolveAgentInWorkspace } from './resolve-agent.js';
|
|
7
|
+
export { findWorkspaceRoot, listWorkspaceAgents } from './discovery.js';
|
|
8
|
+
export { parseAgentFrontmatter } from './frontmatter.js';
|
|
9
|
+
export { suggestClosest, levenshtein } from './suggest.js';
|
|
10
|
+
export { resolveAgentFromRegistry, listRegistryAgentIds, listRegistryAgents, } from './registry.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAQzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry resolution for `loom <agent>`.
|
|
3
|
+
*
|
|
4
|
+
* When an agent id doesn't match an in-workspace `.github/agents/<id>.agent.md`
|
|
5
|
+
* file, we fall back to configured Loom registries. The registry index lists
|
|
6
|
+
* templates and their nested agents; we search it for an exact agent-id hit
|
|
7
|
+
* and return enough information for the launch code to stage the template
|
|
8
|
+
* into a session workspace via `applyTemplate`.
|
|
9
|
+
*
|
|
10
|
+
* This is deliberately *resolution only* — no staging, no filesystem writes
|
|
11
|
+
* beyond what `resolveRegistryIndexPaths` already does when it auto-clones a
|
|
12
|
+
* registry.
|
|
13
|
+
*/
|
|
14
|
+
import type { AgentRegistryEntry, RegistryTemplateEntry } from '../types.js';
|
|
15
|
+
export interface RegistryAgentHit {
|
|
16
|
+
/** Registry name (as configured in ~/.loom/config.yaml). */
|
|
17
|
+
registryName: string;
|
|
18
|
+
/** Absolute path to the registry root (the dir containing index.yaml). */
|
|
19
|
+
registryRoot: string;
|
|
20
|
+
/** Id of the template that contains the matched agent. */
|
|
21
|
+
templateId: string;
|
|
22
|
+
/** Absolute path to the template directory (contains manifest.yaml). */
|
|
23
|
+
templatePath: string;
|
|
24
|
+
/** The matched agent id (== requested id). */
|
|
25
|
+
agentId: string;
|
|
26
|
+
/** Frontmatter/index metadata for the matched agent, when available. */
|
|
27
|
+
agent: AgentRegistryEntry;
|
|
28
|
+
/** Template metadata, for UX. */
|
|
29
|
+
template: RegistryTemplateEntry;
|
|
30
|
+
}
|
|
31
|
+
export interface ResolveAgentFromRegistryOptions {
|
|
32
|
+
/** The agent id to resolve (exact match against index entries). */
|
|
33
|
+
agentId: string;
|
|
34
|
+
/** Override `~/.loom` config dir (tests, power users). */
|
|
35
|
+
configDir?: string;
|
|
36
|
+
/** Override workspace dir used for registry cache. */
|
|
37
|
+
workspaceDir?: string;
|
|
38
|
+
/** Inject an exec fn to suppress real git clones during tests. */
|
|
39
|
+
execFn?: (cmd: string) => void;
|
|
40
|
+
/** Limit resolution to a single named registry. */
|
|
41
|
+
registryName?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Walk all configured registries searching for a template whose nested
|
|
45
|
+
* agents include an exact match for `agentId`.
|
|
46
|
+
*
|
|
47
|
+
* Returns the first hit (deterministic: registries are iterated in config
|
|
48
|
+
* order). Returns an object describing the match or null if none found.
|
|
49
|
+
*
|
|
50
|
+
* Side effects: `resolveRegistryIndexPaths` may auto-clone registries that
|
|
51
|
+
* aren't yet cached. Callers that want a pure lookup must pre-populate the
|
|
52
|
+
* cache.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveAgentFromRegistry(options: ResolveAgentFromRegistryOptions): Promise<RegistryAgentHit | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Discover all agent ids offered across configured registries — used for
|
|
57
|
+
* fuzzy suggestions when an exact match fails. Registry errors are swallowed.
|
|
58
|
+
*/
|
|
59
|
+
export declare function listRegistryAgentIds(options?: Omit<ResolveAgentFromRegistryOptions, 'agentId'>): Promise<string[]>;
|
|
60
|
+
export interface RegistryAgentListing {
|
|
61
|
+
agentId: string;
|
|
62
|
+
agentName?: string;
|
|
63
|
+
description?: string;
|
|
64
|
+
registryName: string;
|
|
65
|
+
templateId: string;
|
|
66
|
+
tags?: string[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Discover all agents across configured registries with enough metadata to
|
|
70
|
+
* render a "what could I launch?" listing. Registry errors are swallowed.
|
|
71
|
+
*/
|
|
72
|
+
export declare function listRegistryAgents(options?: Omit<ResolveAgentFromRegistryOptions, 'agentId'>): Promise<RegistryAgentListing[]>;
|
|
73
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/chat/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAiB,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE5F,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,EAAE,kBAAkB,CAAC;IAC1B,iCAAiC;IACjC,QAAQ,EAAE,qBAAqB,CAAC;CACjC;AAED,MAAM,WAAW,+BAA+B;IAC9C,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAuClC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,IAAI,CAAC,+BAA+B,EAAE,SAAS,CAAM,GAC7D,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,IAAI,CAAC,+BAA+B,EAAE,SAAS,CAAM,GAC7D,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAiCjC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry resolution for `loom <agent>`.
|
|
3
|
+
*
|
|
4
|
+
* When an agent id doesn't match an in-workspace `.github/agents/<id>.agent.md`
|
|
5
|
+
* file, we fall back to configured Loom registries. The registry index lists
|
|
6
|
+
* templates and their nested agents; we search it for an exact agent-id hit
|
|
7
|
+
* and return enough information for the launch code to stage the template
|
|
8
|
+
* into a session workspace via `applyTemplate`.
|
|
9
|
+
*
|
|
10
|
+
* This is deliberately *resolution only* — no staging, no filesystem writes
|
|
11
|
+
* beyond what `resolveRegistryIndexPaths` already does when it auto-clones a
|
|
12
|
+
* registry.
|
|
13
|
+
*/
|
|
14
|
+
import { readFile } from 'node:fs/promises';
|
|
15
|
+
import { dirname } from 'node:path';
|
|
16
|
+
import yaml from 'js-yaml';
|
|
17
|
+
import { resolveRegistryIndexPaths } from '../search-registry.js';
|
|
18
|
+
import { resolveTemplatePath } from '../clone.js';
|
|
19
|
+
/**
|
|
20
|
+
* Walk all configured registries searching for a template whose nested
|
|
21
|
+
* agents include an exact match for `agentId`.
|
|
22
|
+
*
|
|
23
|
+
* Returns the first hit (deterministic: registries are iterated in config
|
|
24
|
+
* order). Returns an object describing the match or null if none found.
|
|
25
|
+
*
|
|
26
|
+
* Side effects: `resolveRegistryIndexPaths` may auto-clone registries that
|
|
27
|
+
* aren't yet cached. Callers that want a pure lookup must pre-populate the
|
|
28
|
+
* cache.
|
|
29
|
+
*/
|
|
30
|
+
export async function resolveAgentFromRegistry(options) {
|
|
31
|
+
const indexPaths = await resolveRegistryIndexPaths({
|
|
32
|
+
registryName: options.registryName,
|
|
33
|
+
workspaceDir: options.workspaceDir,
|
|
34
|
+
configDir: options.configDir,
|
|
35
|
+
execFn: options.execFn,
|
|
36
|
+
});
|
|
37
|
+
for (const { name, path: indexPath } of indexPaths) {
|
|
38
|
+
let index;
|
|
39
|
+
try {
|
|
40
|
+
const raw = await readFile(indexPath, 'utf-8');
|
|
41
|
+
index = yaml.load(raw);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (!index || !Array.isArray(index.templates))
|
|
47
|
+
continue;
|
|
48
|
+
for (const tmpl of index.templates) {
|
|
49
|
+
if (!tmpl.agents)
|
|
50
|
+
continue;
|
|
51
|
+
const match = tmpl.agents.find((a) => a.id === options.agentId);
|
|
52
|
+
if (!match)
|
|
53
|
+
continue;
|
|
54
|
+
// registryRoot is the directory containing index.yaml.
|
|
55
|
+
const registryRoot = dirname(indexPath);
|
|
56
|
+
const templatePath = resolveTemplatePath(registryRoot, tmpl.id);
|
|
57
|
+
return {
|
|
58
|
+
registryName: name,
|
|
59
|
+
registryRoot,
|
|
60
|
+
templateId: tmpl.id,
|
|
61
|
+
templatePath,
|
|
62
|
+
agentId: options.agentId,
|
|
63
|
+
agent: match,
|
|
64
|
+
template: tmpl,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Discover all agent ids offered across configured registries — used for
|
|
72
|
+
* fuzzy suggestions when an exact match fails. Registry errors are swallowed.
|
|
73
|
+
*/
|
|
74
|
+
export async function listRegistryAgentIds(options = {}) {
|
|
75
|
+
const listings = await listRegistryAgents(options);
|
|
76
|
+
return Array.from(new Set(listings.map((l) => l.agentId))).sort();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Discover all agents across configured registries with enough metadata to
|
|
80
|
+
* render a "what could I launch?" listing. Registry errors are swallowed.
|
|
81
|
+
*/
|
|
82
|
+
export async function listRegistryAgents(options = {}) {
|
|
83
|
+
const indexPaths = await resolveRegistryIndexPaths({
|
|
84
|
+
registryName: options.registryName,
|
|
85
|
+
workspaceDir: options.workspaceDir,
|
|
86
|
+
configDir: options.configDir,
|
|
87
|
+
execFn: options.execFn,
|
|
88
|
+
}).catch(() => []);
|
|
89
|
+
const out = [];
|
|
90
|
+
for (const { name, path: indexPath } of indexPaths) {
|
|
91
|
+
try {
|
|
92
|
+
const raw = await readFile(indexPath, 'utf-8');
|
|
93
|
+
const index = yaml.load(raw);
|
|
94
|
+
if (!index || !Array.isArray(index.templates))
|
|
95
|
+
continue;
|
|
96
|
+
for (const tmpl of index.templates) {
|
|
97
|
+
if (!tmpl.agents)
|
|
98
|
+
continue;
|
|
99
|
+
for (const a of tmpl.agents) {
|
|
100
|
+
out.push({
|
|
101
|
+
agentId: a.id,
|
|
102
|
+
agentName: a.name,
|
|
103
|
+
description: a.description,
|
|
104
|
+
registryName: name,
|
|
105
|
+
templateId: tmpl.id,
|
|
106
|
+
tags: a.tags,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// skip unreadable index
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
out.sort((x, y) => x.agentId.localeCompare(y.agentId));
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/chat/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAiClD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAwC;IAExC,MAAM,UAAU,GAAG,MAAM,yBAAyB,CAAC;QACjD,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,UAAU,EAAE,CAAC;QACnD,IAAI,KAAgC,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC/C,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAkB,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;YAAE,SAAS;QAExD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,SAAS;YAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;YAChE,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,uDAAuD;YACvD,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YACxC,MAAM,YAAY,GAAG,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAChE,OAAO;gBACL,YAAY,EAAE,IAAI;gBAClB,YAAY;gBACZ,UAAU,EAAE,IAAI,CAAC,EAAE;gBACnB,YAAY;gBACZ,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,IAAI;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAA4D,EAAE;IAE9D,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC;AAWD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAA4D,EAAE;IAE9D,MAAM,UAAU,GAAG,MAAM,yBAAyB,CAAC;QACjD,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAA2C,CAAC,CAAC;IAE5D,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,UAAU,EAAE,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAA8B,CAAC;YAC1D,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,SAAS;YACxD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACnC,IAAI,CAAC,IAAI,CAAC,MAAM;oBAAE,SAAS;gBAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC5B,GAAG,CAAC,IAAI,CAAC;wBACP,OAAO,EAAE,CAAC,CAAC,EAAE;wBACb,SAAS,EAAE,CAAC,CAAC,IAAI;wBACjB,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,YAAY,EAAE,IAAI;wBAClB,UAAU,EAAE,IAAI,CAAC,EAAE;wBACnB,IAAI,EAAE,CAAC,CAAC,IAAI;qBACb,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Resolution for `loom <agent>`
|
|
3
|
+
*
|
|
4
|
+
* MVP: in-workspace resolution only.
|
|
5
|
+
* Walks up from `cwd` to find the nearest workspace (directory containing
|
|
6
|
+
* `.github/agents/`) and looks for `<id>.agent.md` there.
|
|
7
|
+
*
|
|
8
|
+
* Future layers (not yet implemented):
|
|
9
|
+
* - Installed shortname lookup via ~/.loom/workspaces.yaml
|
|
10
|
+
* - Registry-reference resolution (requires agent-definitions adapter)
|
|
11
|
+
*/
|
|
12
|
+
export interface ResolvedAgentRef {
|
|
13
|
+
/** Agent id (slug from filename) */
|
|
14
|
+
agentId: string;
|
|
15
|
+
/** Absolute path to the `.agent.md` file */
|
|
16
|
+
agentFilePath: string;
|
|
17
|
+
/** Absolute path to the workspace root (dir containing `.github/`) */
|
|
18
|
+
workspaceDir: string;
|
|
19
|
+
/** Resolution layer that produced the match */
|
|
20
|
+
source: 'workspace';
|
|
21
|
+
}
|
|
22
|
+
export interface ResolveAgentOptions {
|
|
23
|
+
/** Agent id to resolve (filename stem before `.agent.md`) */
|
|
24
|
+
agentId: string;
|
|
25
|
+
/** Directory to search from (typically process.cwd()) */
|
|
26
|
+
cwd: string;
|
|
27
|
+
/**
|
|
28
|
+
* If true, only look in `cwd` itself (no walk-up). Used for tests and
|
|
29
|
+
* for callers that need strict resolution semantics.
|
|
30
|
+
*/
|
|
31
|
+
strictCwd?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve an agent id against the current workspace.
|
|
35
|
+
* Returns `null` if not found (caller decides whether to fall through
|
|
36
|
+
* to installed-shortname or registry layers in future iterations).
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveAgentInWorkspace(options: ResolveAgentOptions): ResolvedAgentRef | null;
|
|
39
|
+
//# sourceMappingURL=resolve-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-agent.d.ts","sourceRoot":"","sources":["../../src/chat/resolve-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,GAC3B,gBAAgB,GAAG,IAAI,CAkBzB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Resolution for `loom <agent>`
|
|
3
|
+
*
|
|
4
|
+
* MVP: in-workspace resolution only.
|
|
5
|
+
* Walks up from `cwd` to find the nearest workspace (directory containing
|
|
6
|
+
* `.github/agents/`) and looks for `<id>.agent.md` there.
|
|
7
|
+
*
|
|
8
|
+
* Future layers (not yet implemented):
|
|
9
|
+
* - Installed shortname lookup via ~/.loom/workspaces.yaml
|
|
10
|
+
* - Registry-reference resolution (requires agent-definitions adapter)
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync } from 'node:fs';
|
|
13
|
+
import { join, resolve } from 'node:path';
|
|
14
|
+
import { findWorkspaceRoot } from './discovery.js';
|
|
15
|
+
/**
|
|
16
|
+
* Resolve an agent id against the current workspace.
|
|
17
|
+
* Returns `null` if not found (caller decides whether to fall through
|
|
18
|
+
* to installed-shortname or registry layers in future iterations).
|
|
19
|
+
*/
|
|
20
|
+
export function resolveAgentInWorkspace(options) {
|
|
21
|
+
const { agentId, cwd, strictCwd = false } = options;
|
|
22
|
+
if (!agentId || !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(agentId)) {
|
|
23
|
+
throw new Error(`Invalid agent id: "${agentId}". Must match [a-zA-Z0-9][a-zA-Z0-9._-]*`);
|
|
24
|
+
}
|
|
25
|
+
const workspaceDir = strictCwd ? resolve(cwd) : (findWorkspaceRoot(cwd) ?? resolve(cwd));
|
|
26
|
+
const agentFilePath = join(workspaceDir, '.github', 'agents', `${agentId}.agent.md`);
|
|
27
|
+
if (!existsSync(agentFilePath))
|
|
28
|
+
return null;
|
|
29
|
+
return {
|
|
30
|
+
agentId,
|
|
31
|
+
agentFilePath,
|
|
32
|
+
workspaceDir,
|
|
33
|
+
source: 'workspace',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=resolve-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-agent.js","sourceRoot":"","sources":["../../src/chat/resolve-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAyBnD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA4B;IAE5B,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IACpD,IAAI,CAAC,OAAO,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,sBAAsB,OAAO,0CAA0C,CACxE,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACzF,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,WAAW,CAAC,CAAC;IACrF,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,OAAO;QACL,OAAO;QACP,aAAa;QACb,YAAY;QACZ,MAAM,EAAE,WAAW;KACpB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fuzzy suggestion helper for "agent not found" errors.
|
|
3
|
+
* Uses classic Levenshtein distance — small, fast, dependency-free,
|
|
4
|
+
* and adequate for the small candidate sets we deal with (dozens of
|
|
5
|
+
* agents per workspace at most).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Compute the Levenshtein edit distance between two strings.
|
|
9
|
+
* Case-insensitive comparison.
|
|
10
|
+
*/
|
|
11
|
+
export declare function levenshtein(a: string, b: string): number;
|
|
12
|
+
/**
|
|
13
|
+
* Return up to `limit` candidates from `options` that are closest to `query`,
|
|
14
|
+
* ordered by distance ascending. Candidates with distance greater than
|
|
15
|
+
* `maxDistance` are excluded. When `maxDistance` is unset, defaults to
|
|
16
|
+
* max(2, ceil(query.length / 2)) — tolerates roughly half the characters
|
|
17
|
+
* wrong but at least two edits.
|
|
18
|
+
*/
|
|
19
|
+
export declare function suggestClosest(query: string, options: readonly string[], limit?: number, maxDistance?: number): string[];
|
|
20
|
+
//# sourceMappingURL=suggest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/chat/suggest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BxD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,SAAI,EACT,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,EAAE,CASV"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fuzzy suggestion helper for "agent not found" errors.
|
|
3
|
+
* Uses classic Levenshtein distance — small, fast, dependency-free,
|
|
4
|
+
* and adequate for the small candidate sets we deal with (dozens of
|
|
5
|
+
* agents per workspace at most).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Compute the Levenshtein edit distance between two strings.
|
|
9
|
+
* Case-insensitive comparison.
|
|
10
|
+
*/
|
|
11
|
+
export function levenshtein(a, b) {
|
|
12
|
+
const s1 = a.toLowerCase();
|
|
13
|
+
const s2 = b.toLowerCase();
|
|
14
|
+
const m = s1.length;
|
|
15
|
+
const n = s2.length;
|
|
16
|
+
if (m === 0)
|
|
17
|
+
return n;
|
|
18
|
+
if (n === 0)
|
|
19
|
+
return m;
|
|
20
|
+
// Two-row DP to keep memory to O(min(m,n)).
|
|
21
|
+
let prev = new Array(n + 1);
|
|
22
|
+
let curr = new Array(n + 1);
|
|
23
|
+
for (let j = 0; j <= n; j++)
|
|
24
|
+
prev[j] = j;
|
|
25
|
+
for (let i = 1; i <= m; i++) {
|
|
26
|
+
curr[0] = i;
|
|
27
|
+
for (let j = 1; j <= n; j++) {
|
|
28
|
+
const cost = s1.charCodeAt(i - 1) === s2.charCodeAt(j - 1) ? 0 : 1;
|
|
29
|
+
curr[j] = Math.min(curr[j - 1] + 1, // insert
|
|
30
|
+
prev[j] + 1, // delete
|
|
31
|
+
prev[j - 1] + cost);
|
|
32
|
+
}
|
|
33
|
+
[prev, curr] = [curr, prev];
|
|
34
|
+
}
|
|
35
|
+
return prev[n];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Return up to `limit` candidates from `options` that are closest to `query`,
|
|
39
|
+
* ordered by distance ascending. Candidates with distance greater than
|
|
40
|
+
* `maxDistance` are excluded. When `maxDistance` is unset, defaults to
|
|
41
|
+
* max(2, ceil(query.length / 2)) — tolerates roughly half the characters
|
|
42
|
+
* wrong but at least two edits.
|
|
43
|
+
*/
|
|
44
|
+
export function suggestClosest(query, options, limit = 3, maxDistance) {
|
|
45
|
+
const threshold = maxDistance ?? Math.max(2, Math.ceil(query.length / 2));
|
|
46
|
+
const scored = [];
|
|
47
|
+
for (const option of options) {
|
|
48
|
+
const d = levenshtein(query, option);
|
|
49
|
+
if (d <= threshold)
|
|
50
|
+
scored.push({ option, d });
|
|
51
|
+
}
|
|
52
|
+
scored.sort((a, b) => a.d - b.d || a.option.localeCompare(b.option));
|
|
53
|
+
return scored.slice(0, limit).map((s) => s.option);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=suggest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.js","sourceRoot":"","sources":["../../src/chat/suggest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAS;IAC9C,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3B,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IACpB,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IACpB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEtB,4CAA4C;IAC5C,IAAI,IAAI,GAAG,IAAI,KAAK,CAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,IAAI,KAAK,CAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAChB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAS,SAAS;YACjC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAa,SAAS;YACjC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CACnB,CAAC;QACJ,CAAC;QACD,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,OAA0B,EAC1B,KAAK,GAAG,CAAC,EACT,WAAoB;IAEpB,MAAM,SAAS,GAAG,WAAW,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAyC,EAAE,CAAC;IACxD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACrD,CAAC"}
|