@sentry/dotagents 0.3.0 → 0.4.0
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 +73 -15
- package/dist/agents/definitions/claude.d.ts +4 -0
- package/dist/agents/definitions/claude.d.ts.map +1 -0
- package/dist/agents/definitions/claude.js +28 -0
- package/dist/agents/definitions/claude.js.map +1 -0
- package/dist/agents/definitions/codex.d.ts +4 -0
- package/dist/agents/definitions/codex.d.ts.map +1 -0
- package/dist/agents/definitions/codex.js +21 -0
- package/dist/agents/definitions/codex.js.map +1 -0
- package/dist/agents/definitions/cursor.d.ts +4 -0
- package/dist/agents/definitions/cursor.d.ts.map +1 -0
- package/dist/agents/definitions/cursor.js +45 -0
- package/dist/agents/definitions/cursor.js.map +1 -0
- package/dist/agents/definitions/helpers.d.ts +14 -0
- package/dist/agents/definitions/helpers.d.ts.map +1 -0
- package/dist/agents/definitions/helpers.js +39 -0
- package/dist/agents/definitions/helpers.js.map +1 -0
- package/dist/agents/definitions/opencode.d.ts +4 -0
- package/dist/agents/definitions/opencode.d.ts.map +1 -0
- package/dist/agents/definitions/opencode.js +33 -0
- package/dist/agents/definitions/opencode.js.map +1 -0
- package/dist/agents/definitions/vscode.d.ts +4 -0
- package/dist/agents/definitions/vscode.d.ts.map +1 -0
- package/dist/agents/definitions/vscode.js +31 -0
- package/dist/agents/definitions/vscode.js.map +1 -0
- package/dist/agents/errors.d.ts +9 -0
- package/dist/agents/errors.d.ts.map +1 -0
- package/dist/agents/errors.js +14 -0
- package/dist/agents/errors.js.map +1 -0
- package/dist/agents/hook-writer.d.ts +26 -0
- package/dist/agents/hook-writer.d.ts.map +1 -0
- package/dist/agents/hook-writer.js +105 -0
- package/dist/agents/hook-writer.js.map +1 -0
- package/dist/agents/hook-writer.test.d.ts +2 -0
- package/dist/agents/hook-writer.test.d.ts.map +1 -0
- package/dist/agents/hook-writer.test.js +155 -0
- package/dist/agents/hook-writer.test.js.map +1 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/mcp-writer.d.ts +21 -0
- package/dist/agents/mcp-writer.d.ts.map +1 -0
- package/dist/agents/mcp-writer.js +115 -0
- package/dist/agents/mcp-writer.js.map +1 -0
- package/dist/agents/mcp-writer.test.d.ts +2 -0
- package/dist/agents/mcp-writer.test.d.ts.map +1 -0
- package/dist/agents/mcp-writer.test.js +146 -0
- package/dist/agents/mcp-writer.test.js.map +1 -0
- package/dist/agents/registry.d.ts +4 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +14 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/registry.test.d.ts +2 -0
- package/dist/agents/registry.test.d.ts.map +1 -0
- package/dist/agents/registry.test.js +144 -0
- package/dist/agents/registry.test.js.map +1 -0
- package/dist/agents/types.d.ts +88 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/cli/commands/add.d.ts.map +1 -1
- package/dist/cli/commands/add.js +6 -2
- package/dist/cli/commands/add.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +29 -9
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +16 -0
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/commands/install.d.ts +4 -0
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +83 -69
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/install.test.js +44 -0
- package/dist/cli/commands/install.test.js.map +1 -1
- package/dist/cli/commands/sync.d.ts +3 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/commands/sync.js +61 -3
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/commands/sync.test.js +35 -0
- package/dist/cli/commands/sync.test.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +4 -1
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +7 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/loader.test.js +21 -0
- package/dist/config/loader.test.js.map +1 -1
- package/dist/config/schema.d.ts +63 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +39 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/config/schema.test.js +156 -0
- package/dist/config/schema.test.js.map +1 -1
- package/dist/config/writer.d.ts +1 -1
- package/dist/config/writer.d.ts.map +1 -1
- package/dist/config/writer.js +7 -2
- package/dist/config/writer.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/trust/index.d.ts +2 -0
- package/dist/trust/index.d.ts.map +1 -0
- package/dist/trust/index.js +2 -0
- package/dist/trust/index.js.map +1 -0
- package/dist/trust/validator.d.ts +25 -0
- package/dist/trust/validator.d.ts.map +1 -0
- package/dist/trust/validator.js +86 -0
- package/dist/trust/validator.js.map +1 -0
- package/dist/trust/validator.test.d.ts +2 -0
- package/dist/trust/validator.test.d.ts.map +1 -0
- package/dist/trust/validator.test.js +145 -0
- package/dist/trust/validator.test.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ A package manager for `.agents` directories. Declare agent skill dependencies in
|
|
|
6
6
|
|
|
7
7
|
**One source of truth.** Skills live in `.agents/skills/` and symlink into `.claude/skills/`, `.cursor/skills/`, or wherever your tools expect them. No copy-pasting between directories.
|
|
8
8
|
|
|
9
|
-
**Reproducible.** `agents.lock` pins exact commits and integrity hashes. `dotagents install --frozen` in CI guarantees everyone runs the same skills.
|
|
9
|
+
**Reproducible.** `agents.lock` pins exact commits and integrity hashes. `npx @sentry/dotagents install --frozen` in CI guarantees everyone runs the same skills.
|
|
10
10
|
|
|
11
11
|
**Shareable.** Skills are just directories with a `SKILL.md`. Host them in any git repo, discover them automatically, install with one command.
|
|
12
12
|
|
|
@@ -14,13 +14,13 @@ A package manager for `.agents` directories. Declare agent skill dependencies in
|
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
# Initialize a new project
|
|
17
|
-
npx dotagents init
|
|
17
|
+
npx @sentry/dotagents init
|
|
18
18
|
|
|
19
19
|
# Add a skill from a GitHub repo
|
|
20
|
-
npx dotagents add getsentry/skills --name find-bugs
|
|
20
|
+
npx @sentry/dotagents add getsentry/skills --name find-bugs
|
|
21
21
|
|
|
22
22
|
# Install all declared skills
|
|
23
|
-
npx dotagents install
|
|
23
|
+
npx @sentry/dotagents install
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
This creates an `agents.toml`:
|
|
@@ -28,6 +28,7 @@ This creates an `agents.toml`:
|
|
|
28
28
|
```toml
|
|
29
29
|
version = 1
|
|
30
30
|
gitignore = false
|
|
31
|
+
agents = ["claude"]
|
|
31
32
|
|
|
32
33
|
[[skills]]
|
|
33
34
|
name = "find-bugs"
|
|
@@ -40,13 +41,13 @@ And a lockfile (`agents.lock`) pinning the exact commit and integrity hash.
|
|
|
40
41
|
|
|
41
42
|
| Command | Description |
|
|
42
43
|
|---------|-------------|
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
44
|
+
| `init` | Create `agents.toml` and `.agents/skills/` |
|
|
45
|
+
| `add <source>` | Add a skill dependency |
|
|
46
|
+
| `remove <name>` | Remove a skill |
|
|
47
|
+
| `install` | Install all dependencies from `agents.toml` |
|
|
48
|
+
| `update [name]` | Update skills to latest versions |
|
|
49
|
+
| `list` | Show installed skills and their status |
|
|
50
|
+
| `sync` | Reconcile gitignore, symlinks, and verify state |
|
|
50
51
|
|
|
51
52
|
## Source Formats
|
|
52
53
|
|
|
@@ -68,19 +69,76 @@ name = "local"
|
|
|
68
69
|
source = "path:./my-skills/local-skill" # Local directory
|
|
69
70
|
```
|
|
70
71
|
|
|
72
|
+
## Agent Targets
|
|
73
|
+
|
|
74
|
+
The `agents` field tells dotagents which tools to configure. It handles skills symlinks, MCP config files, and hook config files for each agent.
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
agents = ["claude", "cursor"]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Supported agents: `claude`, `cursor`, `codex`, `vscode`, `opencode`.
|
|
81
|
+
|
|
82
|
+
## MCP Servers
|
|
83
|
+
|
|
84
|
+
Declare MCP servers once in `agents.toml` and dotagents generates the correct config file for each agent during `install` and `sync`.
|
|
85
|
+
|
|
86
|
+
```toml
|
|
87
|
+
agents = ["claude", "cursor"]
|
|
88
|
+
|
|
89
|
+
# Stdio transport
|
|
90
|
+
[[mcp]]
|
|
91
|
+
name = "github"
|
|
92
|
+
command = "npx"
|
|
93
|
+
args = ["-y", "@modelcontextprotocol/server-github"]
|
|
94
|
+
env = ["GITHUB_TOKEN"]
|
|
95
|
+
|
|
96
|
+
# HTTP transport
|
|
97
|
+
[[mcp]]
|
|
98
|
+
name = "remote-api"
|
|
99
|
+
url = "https://mcp.example.com/sse"
|
|
100
|
+
headers = { Authorization = "Bearer tok" }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Each server uses either `command` (stdio) or `url` (HTTP), not both. The `env` field lists environment variable names to pass through from the user's environment.
|
|
104
|
+
|
|
105
|
+
## Hooks
|
|
106
|
+
|
|
107
|
+
Declare hooks once in `agents.toml` and dotagents writes the correct hook config for each agent that supports them.
|
|
108
|
+
|
|
109
|
+
```toml
|
|
110
|
+
agents = ["claude"]
|
|
111
|
+
|
|
112
|
+
[[hooks]]
|
|
113
|
+
event = "PreToolUse"
|
|
114
|
+
matcher = "Bash"
|
|
115
|
+
command = "my-lint-check"
|
|
116
|
+
|
|
117
|
+
[[hooks]]
|
|
118
|
+
event = "Stop"
|
|
119
|
+
command = "notify-done"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
| Field | Required | Description |
|
|
123
|
+
|-------|----------|-------------|
|
|
124
|
+
| `event` | Yes | `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, or `Stop` |
|
|
125
|
+
| `matcher` | No | Filter to specific tool names (e.g. `Bash`, `Write`) |
|
|
126
|
+
| `command` | Yes | Shell command to run when the hook fires |
|
|
127
|
+
|
|
71
128
|
## How It Works
|
|
72
129
|
|
|
73
130
|
1. Skills are declared in `agents.toml` at the project root
|
|
74
|
-
2. `
|
|
131
|
+
2. `install` clones repos, discovers skills by convention, and copies them into `.agents/skills/`
|
|
75
132
|
3. `agents.lock` records the resolved commit and a SHA-256 integrity hash
|
|
76
133
|
4. By default (`gitignore = false`), skills are checked into git so collaborators get them immediately. Set `gitignore = true` to auto-generate `.agents/.gitignore` and exclude managed skills instead.
|
|
77
|
-
5. Symlinks connect `.agents/skills/` to wherever your tools look (configured via `
|
|
134
|
+
5. Symlinks connect `.agents/skills/` to wherever your tools look (configured via the `agents` field)
|
|
135
|
+
6. MCP and hook configs are generated for each declared agent
|
|
78
136
|
|
|
79
137
|
## Checking In Skills
|
|
80
138
|
|
|
81
|
-
By default, `
|
|
139
|
+
By default, `init` sets `gitignore = false` so installed skills are committed to git. This means anyone cloning the repo gets skills immediately — they only need dotagents when adding or updating skills.
|
|
82
140
|
|
|
83
|
-
To gitignore managed skills instead (collaborators must run `
|
|
141
|
+
To gitignore managed skills instead (collaborators must run `install`), set `gitignore = true` in `agents.toml` or remove the field entirely (it defaults to `true` when absent for backward compatibility).
|
|
84
142
|
|
|
85
143
|
## Contributing
|
|
86
144
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/agents/definitions/claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,QAAA,MAAM,MAAM,EAAE,eAuBb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { envRecord, httpServer, serializeClaudeHooks } from "./helpers.js";
|
|
2
|
+
const claude = {
|
|
3
|
+
id: "claude",
|
|
4
|
+
displayName: "Claude Code",
|
|
5
|
+
configDir: ".claude",
|
|
6
|
+
skillsParentDir: ".claude",
|
|
7
|
+
mcp: {
|
|
8
|
+
filePath: ".mcp.json",
|
|
9
|
+
rootKey: "mcpServers",
|
|
10
|
+
format: "json",
|
|
11
|
+
shared: false,
|
|
12
|
+
},
|
|
13
|
+
serializeServer(s) {
|
|
14
|
+
if (s.url)
|
|
15
|
+
return httpServer(s);
|
|
16
|
+
const env = envRecord(s.env, (k) => `\${${k}}`);
|
|
17
|
+
return [s.name, { command: s.command, args: s.args ?? [], ...(env && { env }) }];
|
|
18
|
+
},
|
|
19
|
+
hooks: {
|
|
20
|
+
filePath: ".claude/settings.json",
|
|
21
|
+
rootKey: "hooks",
|
|
22
|
+
format: "json",
|
|
23
|
+
shared: true,
|
|
24
|
+
},
|
|
25
|
+
serializeHooks: serializeClaudeHooks,
|
|
26
|
+
};
|
|
27
|
+
export default claude;
|
|
28
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/agents/definitions/claude.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE3E,MAAM,MAAM,GAAoB;IAC9B,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,aAAa;IAC1B,SAAS,EAAE,SAAS;IACpB,eAAe,EAAE,SAAS;IAC1B,GAAG,EAAE;QACH,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,YAAY;QACrB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,KAAK;KACd;IACD,eAAe,CAAC,CAAC;QACf,IAAI,CAAC,CAAC,GAAG;YAAE,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,uBAAuB;QACjC,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,IAAI;KACb;IACD,cAAc,EAAE,oBAAoB;CACrC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/agents/definitions/codex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,QAAA,MAAM,KAAK,EAAE,eAgBZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { UnsupportedFeature } from "../errors.js";
|
|
2
|
+
import claude from "./claude.js";
|
|
3
|
+
const codex = {
|
|
4
|
+
...claude,
|
|
5
|
+
id: "codex",
|
|
6
|
+
displayName: "Codex",
|
|
7
|
+
configDir: ".codex",
|
|
8
|
+
skillsParentDir: ".codex",
|
|
9
|
+
mcp: {
|
|
10
|
+
filePath: ".codex/config.toml",
|
|
11
|
+
rootKey: "mcp_servers",
|
|
12
|
+
format: "toml",
|
|
13
|
+
shared: true,
|
|
14
|
+
},
|
|
15
|
+
hooks: undefined,
|
|
16
|
+
serializeHooks() {
|
|
17
|
+
throw new UnsupportedFeature("codex", "hooks");
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export default codex;
|
|
21
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/agents/definitions/codex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,KAAK,GAAoB;IAC7B,GAAG,MAAM;IACT,EAAE,EAAE,OAAO;IACX,WAAW,EAAE,OAAO;IACpB,SAAS,EAAE,QAAQ;IACnB,eAAe,EAAE,QAAQ;IACzB,GAAG,EAAE;QACH,QAAQ,EAAE,oBAAoB;QAC9B,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,IAAI;KACb;IACD,KAAK,EAAE,SAAS;IAChB,cAAc;QACZ,MAAM,IAAI,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/agents/definitions/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,aAAa,CAAC;AAepE,QAAA,MAAM,MAAM,EAAE,eA+Bb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import claude from "./claude.js";
|
|
2
|
+
/**
|
|
3
|
+
* Maps universal hook events to Cursor event names.
|
|
4
|
+
* PreToolUse maps to both beforeShellExecution and beforeMCPExecution.
|
|
5
|
+
*/
|
|
6
|
+
const CURSOR_EVENT_MAP = {
|
|
7
|
+
PreToolUse: ["beforeShellExecution", "beforeMCPExecution"],
|
|
8
|
+
PostToolUse: ["afterFileEdit"],
|
|
9
|
+
UserPromptSubmit: ["beforeSubmitPrompt"],
|
|
10
|
+
Stop: ["stop"],
|
|
11
|
+
};
|
|
12
|
+
const cursor = {
|
|
13
|
+
...claude,
|
|
14
|
+
id: "cursor",
|
|
15
|
+
displayName: "Cursor",
|
|
16
|
+
configDir: ".cursor",
|
|
17
|
+
skillsParentDir: ".cursor",
|
|
18
|
+
mcp: {
|
|
19
|
+
filePath: ".cursor/mcp.json",
|
|
20
|
+
rootKey: "mcpServers",
|
|
21
|
+
format: "json",
|
|
22
|
+
shared: false,
|
|
23
|
+
},
|
|
24
|
+
hooks: {
|
|
25
|
+
filePath: ".cursor/hooks.json",
|
|
26
|
+
rootKey: "hooks",
|
|
27
|
+
format: "json",
|
|
28
|
+
shared: false,
|
|
29
|
+
extraFields: { version: 1 },
|
|
30
|
+
},
|
|
31
|
+
serializeHooks(hooks) {
|
|
32
|
+
const result = {};
|
|
33
|
+
for (const h of hooks) {
|
|
34
|
+
const cursorEvents = CURSOR_EVENT_MAP[h.event];
|
|
35
|
+
for (const ce of cursorEvents) {
|
|
36
|
+
const list = result[ce] ?? [];
|
|
37
|
+
list.push({ command: h.command });
|
|
38
|
+
result[ce] = list;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
export default cursor;
|
|
45
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../src/agents/definitions/cursor.ts"],"names":[],"mappings":"AAEA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC;;;GAGG;AACH,MAAM,gBAAgB,GAAgC;IACpD,UAAU,EAAE,CAAC,sBAAsB,EAAE,oBAAoB,CAAC;IAC1D,WAAW,EAAE,CAAC,eAAe,CAAC;IAC9B,gBAAgB,EAAE,CAAC,oBAAoB,CAAC;IACxC,IAAI,EAAE,CAAC,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,GAAoB;IAC9B,GAAG,MAAM;IACT,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,QAAQ;IACrB,SAAS,EAAE,SAAS;IACpB,eAAe,EAAE,SAAS;IAC1B,GAAG,EAAE;QACH,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,YAAY;QACrB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,KAAK;KACd;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,oBAAoB;QAC9B,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;KAC5B;IACD,cAAc,CAAC,KAAwB;QACrC,MAAM,MAAM,GAA8B,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC/C,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAI,MAAM,CAAC,EAAE,CAAe,IAAI,EAAE,CAAC;gBAC7C,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;YACpB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { McpDeclaration, HookDeclaration } from "../types.js";
|
|
2
|
+
export declare function envRecord(env: string[] | undefined, template: (key: string) => string): Record<string, string> | undefined;
|
|
3
|
+
export declare function httpServer(s: McpDeclaration, type?: string): [string, unknown];
|
|
4
|
+
/**
|
|
5
|
+
* Serialize hooks into Claude Code / VS Code settings.json format.
|
|
6
|
+
*
|
|
7
|
+
* Output shape:
|
|
8
|
+
* {
|
|
9
|
+
* "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "..." }] }],
|
|
10
|
+
* "Stop": [{ "hooks": [{ "type": "command", "command": "..." }] }]
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
export declare function serializeClaudeHooks(hooks: HookDeclaration[]): Record<string, unknown>;
|
|
14
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/agents/definitions/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnE,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EAAE,GAAG,SAAS,EACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAKpC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAS9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUtF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function envRecord(env, template) {
|
|
2
|
+
if (!env || env.length === 0)
|
|
3
|
+
return undefined;
|
|
4
|
+
const rec = {};
|
|
5
|
+
for (const key of env)
|
|
6
|
+
rec[key] = template(key);
|
|
7
|
+
return rec;
|
|
8
|
+
}
|
|
9
|
+
export function httpServer(s, type) {
|
|
10
|
+
return [
|
|
11
|
+
s.name,
|
|
12
|
+
{
|
|
13
|
+
...(type && { type }),
|
|
14
|
+
url: s.url,
|
|
15
|
+
...(s.headers && { headers: s.headers }),
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Serialize hooks into Claude Code / VS Code settings.json format.
|
|
21
|
+
*
|
|
22
|
+
* Output shape:
|
|
23
|
+
* {
|
|
24
|
+
* "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "..." }] }],
|
|
25
|
+
* "Stop": [{ "hooks": [{ "type": "command", "command": "..." }] }]
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
export function serializeClaudeHooks(hooks) {
|
|
29
|
+
const result = {};
|
|
30
|
+
for (const h of hooks) {
|
|
31
|
+
const entry = {
|
|
32
|
+
...(h.matcher && { matcher: h.matcher }),
|
|
33
|
+
hooks: [{ type: "command", command: h.command }],
|
|
34
|
+
};
|
|
35
|
+
(result[h.event] ??= []).push(entry);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/agents/definitions/helpers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CACvB,GAAyB,EACzB,QAAiC;IAEjC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,GAAG;QAAE,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAiB,EAAE,IAAa;IACzD,OAAO;QACL,CAAC,CAAC,IAAI;QACN;YACE,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC;YACrB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SACzC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAwB;IAC3D,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG;YACZ,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SACjD,CAAC;QACF,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/agents/definitions/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,QAAA,MAAM,QAAQ,EAAE,eA2Bf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { UnsupportedFeature } from "../errors.js";
|
|
2
|
+
import { envRecord, httpServer } from "./helpers.js";
|
|
3
|
+
const opencode = {
|
|
4
|
+
id: "opencode",
|
|
5
|
+
displayName: "OpenCode",
|
|
6
|
+
configDir: ".claude",
|
|
7
|
+
skillsParentDir: ".claude",
|
|
8
|
+
mcp: {
|
|
9
|
+
filePath: "opencode.json",
|
|
10
|
+
rootKey: "mcp",
|
|
11
|
+
format: "json",
|
|
12
|
+
shared: true,
|
|
13
|
+
},
|
|
14
|
+
serializeServer(s) {
|
|
15
|
+
if (s.url)
|
|
16
|
+
return httpServer(s, "remote");
|
|
17
|
+
const env = envRecord(s.env, (k) => `\${${k}}`);
|
|
18
|
+
return [
|
|
19
|
+
s.name,
|
|
20
|
+
{
|
|
21
|
+
type: "local",
|
|
22
|
+
command: [s.command, ...(s.args ?? [])],
|
|
23
|
+
...(env && { environment: env }),
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
},
|
|
27
|
+
hooks: undefined,
|
|
28
|
+
serializeHooks() {
|
|
29
|
+
throw new UnsupportedFeature("opencode", "hooks");
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
export default opencode;
|
|
33
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/agents/definitions/opencode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,QAAQ,GAAoB;IAChC,EAAE,EAAE,UAAU;IACd,WAAW,EAAE,UAAU;IACvB,SAAS,EAAE,SAAS;IACpB,eAAe,EAAE,SAAS;IAC1B,GAAG,EAAE;QACH,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,IAAI;KACb;IACD,eAAe,CAAC,CAAC;QACf,IAAI,CAAC,CAAC,GAAG;YAAE,OAAO,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO;YACL,CAAC,CAAC,IAAI;YACN;gBACE,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,CAAC,CAAC,CAAC,OAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBACxC,GAAG,CAAC,GAAG,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;aACjC;SACF,CAAC;IACJ,CAAC;IACD,KAAK,EAAE,SAAS;IAChB,cAAc;QACZ,MAAM,IAAI,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;CACF,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vscode.d.ts","sourceRoot":"","sources":["../../../src/agents/definitions/vscode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,QAAA,MAAM,MAAM,EAAE,eA0Bb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { envRecord, httpServer, serializeClaudeHooks } from "./helpers.js";
|
|
2
|
+
const vscode = {
|
|
3
|
+
id: "vscode",
|
|
4
|
+
displayName: "VS Code Copilot",
|
|
5
|
+
configDir: ".vscode",
|
|
6
|
+
skillsParentDir: ".vscode",
|
|
7
|
+
mcp: {
|
|
8
|
+
filePath: ".vscode/mcp.json",
|
|
9
|
+
rootKey: "servers",
|
|
10
|
+
format: "json",
|
|
11
|
+
shared: false,
|
|
12
|
+
},
|
|
13
|
+
serializeServer(s) {
|
|
14
|
+
if (s.url)
|
|
15
|
+
return httpServer(s, "sse");
|
|
16
|
+
const env = envRecord(s.env, (k) => `\${input:${k}}`);
|
|
17
|
+
return [
|
|
18
|
+
s.name,
|
|
19
|
+
{ type: "stdio", command: s.command, args: s.args ?? [], ...(env && { env }) },
|
|
20
|
+
];
|
|
21
|
+
},
|
|
22
|
+
hooks: {
|
|
23
|
+
filePath: ".claude/settings.json",
|
|
24
|
+
rootKey: "hooks",
|
|
25
|
+
format: "json",
|
|
26
|
+
shared: true,
|
|
27
|
+
},
|
|
28
|
+
serializeHooks: serializeClaudeHooks,
|
|
29
|
+
};
|
|
30
|
+
export default vscode;
|
|
31
|
+
//# sourceMappingURL=vscode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vscode.js","sourceRoot":"","sources":["../../../src/agents/definitions/vscode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE3E,MAAM,MAAM,GAAoB;IAC9B,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,iBAAiB;IAC9B,SAAS,EAAE,SAAS;IACpB,eAAe,EAAE,SAAS;IAC1B,GAAG,EAAE;QACH,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,KAAK;KACd;IACD,eAAe,CAAC,CAAC;QACf,IAAI,CAAC,CAAC,GAAG;YAAE,OAAO,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACtD,OAAO;YACL,CAAC,CAAC,IAAI;YACN,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE;SAC/E,CAAC;IACJ,CAAC;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,uBAAuB;QACjC,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,IAAI;KACb;IACD,cAAc,EAAE,oBAAoB;CACrC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when an agent does not support a requested feature (e.g. hooks).
|
|
3
|
+
*/
|
|
4
|
+
export declare class UnsupportedFeature extends Error {
|
|
5
|
+
readonly agentId: string;
|
|
6
|
+
readonly feature: string;
|
|
7
|
+
constructor(agentId: string, feature: string);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/agents/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM;gBADf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM;CAKlC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when an agent does not support a requested feature (e.g. hooks).
|
|
3
|
+
*/
|
|
4
|
+
export class UnsupportedFeature extends Error {
|
|
5
|
+
agentId;
|
|
6
|
+
feature;
|
|
7
|
+
constructor(agentId, feature) {
|
|
8
|
+
super(`Agent "${agentId}" does not support ${feature}`);
|
|
9
|
+
this.agentId = agentId;
|
|
10
|
+
this.feature = feature;
|
|
11
|
+
this.name = "UnsupportedFeature";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/agents/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEzB;IACA;IAFlB,YACkB,OAAe,EACf,OAAe;QAE/B,KAAK,CAAC,UAAU,OAAO,sBAAsB,OAAO,EAAE,CAAC,CAAC;QAHxC,YAAO,GAAP,OAAO,CAAQ;QACf,YAAO,GAAP,OAAO,CAAQ;QAG/B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { HookDeclaration } from "./types.js";
|
|
2
|
+
import type { HookConfig } from "../config/schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Convert HookConfig entries (from agents.toml) to universal HookDeclarations.
|
|
5
|
+
*/
|
|
6
|
+
export declare function toHookDeclarations(configs: HookConfig[]): HookDeclaration[];
|
|
7
|
+
export interface HookWriteWarning {
|
|
8
|
+
agent: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Write hook config files for each agent.
|
|
13
|
+
* - Dedicated files (shared=false): written fresh each time.
|
|
14
|
+
* - Shared files (shared=true): read existing, merge hooks under the root key, write back.
|
|
15
|
+
* - Agents that don't support hooks: collected as warnings.
|
|
16
|
+
*/
|
|
17
|
+
export declare function writeHookConfigs(projectRoot: string, agentIds: string[], hooks: HookDeclaration[]): Promise<HookWriteWarning[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Verify hook configs exist and contain expected hook data.
|
|
20
|
+
* Returns a list of issues found.
|
|
21
|
+
*/
|
|
22
|
+
export declare function verifyHookConfigs(projectRoot: string, agentIds: string[], hooks: HookDeclaration[]): Promise<{
|
|
23
|
+
agent: string;
|
|
24
|
+
issue: string;
|
|
25
|
+
}[]>;
|
|
26
|
+
//# sourceMappingURL=hook-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-writer.d.ts","sourceRoot":"","sources":["../../src/agents/hook-writer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,eAAe,EAAE,CAM3E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,EAAE,eAAe,EAAE,GACvB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA+B7B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,EAAE,eAAe,EAAE,GACvB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAmC7C"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { getAgent } from "./registry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Convert HookConfig entries (from agents.toml) to universal HookDeclarations.
|
|
7
|
+
*/
|
|
8
|
+
export function toHookDeclarations(configs) {
|
|
9
|
+
return configs.map((h) => ({
|
|
10
|
+
event: h.event,
|
|
11
|
+
...(h.matcher && { matcher: h.matcher }),
|
|
12
|
+
command: h.command,
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Write hook config files for each agent.
|
|
17
|
+
* - Dedicated files (shared=false): written fresh each time.
|
|
18
|
+
* - Shared files (shared=true): read existing, merge hooks under the root key, write back.
|
|
19
|
+
* - Agents that don't support hooks: collected as warnings.
|
|
20
|
+
*/
|
|
21
|
+
export async function writeHookConfigs(projectRoot, agentIds, hooks) {
|
|
22
|
+
const warnings = [];
|
|
23
|
+
if (hooks.length === 0)
|
|
24
|
+
return warnings;
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
for (const id of agentIds) {
|
|
27
|
+
const agent = getAgent(id);
|
|
28
|
+
if (!agent)
|
|
29
|
+
continue;
|
|
30
|
+
if (!agent.hooks) {
|
|
31
|
+
warnings.push({ agent: id, message: `Agent "${agent.displayName}" does not support hooks` });
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const serialized = agent.serializeHooks(hooks);
|
|
35
|
+
const spec = agent.hooks;
|
|
36
|
+
if (seen.has(spec.filePath))
|
|
37
|
+
continue;
|
|
38
|
+
seen.add(spec.filePath);
|
|
39
|
+
const filePath = join(projectRoot, spec.filePath);
|
|
40
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
41
|
+
if (spec.shared) {
|
|
42
|
+
await mergeWrite(filePath, spec, serialized);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
await freshWrite(filePath, spec, serialized);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return warnings;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Verify hook configs exist and contain expected hook data.
|
|
52
|
+
* Returns a list of issues found.
|
|
53
|
+
*/
|
|
54
|
+
export async function verifyHookConfigs(projectRoot, agentIds, hooks) {
|
|
55
|
+
if (hooks.length === 0)
|
|
56
|
+
return [];
|
|
57
|
+
const issues = [];
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
for (const id of agentIds) {
|
|
60
|
+
const agent = getAgent(id);
|
|
61
|
+
if (!agent)
|
|
62
|
+
continue;
|
|
63
|
+
// Skip agents that don't support hooks
|
|
64
|
+
if (!agent.hooks)
|
|
65
|
+
continue;
|
|
66
|
+
const spec = agent.hooks;
|
|
67
|
+
if (seen.has(spec.filePath))
|
|
68
|
+
continue;
|
|
69
|
+
seen.add(spec.filePath);
|
|
70
|
+
const filePath = join(projectRoot, spec.filePath);
|
|
71
|
+
if (!existsSync(filePath)) {
|
|
72
|
+
issues.push({ agent: id, issue: `Hook config missing: ${spec.filePath}` });
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const existing = await readExisting(filePath);
|
|
77
|
+
const hooksSection = existing[spec.rootKey];
|
|
78
|
+
if (!hooksSection || typeof hooksSection !== "object") {
|
|
79
|
+
issues.push({ agent: id, issue: `Hook config missing "${spec.rootKey}" key in ${spec.filePath}` });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
issues.push({ agent: id, issue: `Failed to read hook config: ${spec.filePath}` });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return issues;
|
|
87
|
+
}
|
|
88
|
+
// --- Internal helpers ---
|
|
89
|
+
async function freshWrite(filePath, spec, serialized) {
|
|
90
|
+
const doc = {
|
|
91
|
+
...spec.extraFields,
|
|
92
|
+
[spec.rootKey]: serialized,
|
|
93
|
+
};
|
|
94
|
+
await writeFile(filePath, JSON.stringify(doc, null, 2) + "\n", "utf-8");
|
|
95
|
+
}
|
|
96
|
+
async function mergeWrite(filePath, spec, serialized) {
|
|
97
|
+
const existing = existsSync(filePath) ? await readExisting(filePath) : {};
|
|
98
|
+
existing[spec.rootKey] = serialized;
|
|
99
|
+
await writeFile(filePath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
100
|
+
}
|
|
101
|
+
async function readExisting(filePath) {
|
|
102
|
+
const raw = await readFile(filePath, "utf-8");
|
|
103
|
+
return JSON.parse(raw);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=hook-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-writer.js","sourceRoot":"","sources":["../../src/agents/hook-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-writer.test.d.ts","sourceRoot":"","sources":["../../src/agents/hook-writer.test.ts"],"names":[],"mappings":""}
|