@craftsamo/agent-github 0.1.0 → 0.2.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/.antigravity-plugin/plugin.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.mcp.json +8 -0
- package/README.md +62 -25
- package/dist/cli.js +130 -21
- package/dist/mcp.js +88 -39
- package/dist/opencode.js +143 -40
- package/mcp.json +1 -1
- package/mcp_config.json +1 -1
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/plugin.yaml +1 -1
- package/src/hermes/agent_github_hermes/approval.py +18 -14
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "GitHub tools for coding agents: issues, project boards, pull requests, repositories, releases and Actions.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "craftsamo",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"repository": "https://github.com/craftsamo/agent-github",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"mcpServers": {
|
|
13
|
-
"github": {
|
|
13
|
+
"agent-github": {
|
|
14
14
|
"command": "node",
|
|
15
15
|
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/mcp.js"]
|
|
16
16
|
}
|
package/.mcp.json
ADDED
package/README.md
CHANGED
|
@@ -15,6 +15,9 @@ agent harness in the form that suits it best.
|
|
|
15
15
|
| Hermes Agent | native plugin (Python, calls the command line) | the release commit, as the SHA |
|
|
16
16
|
| other MCP host | MCP server from npm | the version in the package |
|
|
17
17
|
|
|
18
|
+
0.2.0 renamed the MCP server from `github` to `agent-github`, so allow rules
|
|
19
|
+
and MCP configurations written for 0.1.0 change.
|
|
20
|
+
|
|
18
21
|
The tools need [Node.js](https://nodejs.org/) 24 or later and the
|
|
19
22
|
[GitHub CLI](https://cli.github.com/), authenticated as you.
|
|
20
23
|
[`docs/conventions.md`](docs/conventions.md) describes how the tools are named
|
|
@@ -42,7 +45,8 @@ OpenCode V2 takes the package and its options in `opencode.json`:
|
|
|
42
45
|
"package": "@craftsamo/agent-github@<version>",
|
|
43
46
|
"options": { "toolsets": ["issues", "pull_requests", "projects"] }
|
|
44
47
|
}
|
|
45
|
-
]
|
|
48
|
+
],
|
|
49
|
+
"permissions": [{ "action": "github_*", "resource": "*", "effect": "ask" }]
|
|
46
50
|
}
|
|
47
51
|
```
|
|
48
52
|
|
|
@@ -50,12 +54,25 @@ OpenCode V1 takes the package as a string, or as a pair with its options:
|
|
|
50
54
|
|
|
51
55
|
```json
|
|
52
56
|
{
|
|
53
|
-
"plugin": [["@craftsamo/agent-github@<version>", { "toolsets": ["issues", "pull_requests", "projects"] }]]
|
|
57
|
+
"plugin": [["@craftsamo/agent-github@<version>", { "toolsets": ["issues", "pull_requests", "projects"] }]],
|
|
58
|
+
"permission": { "github_*": "ask" }
|
|
54
59
|
}
|
|
55
60
|
```
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
OpenCode allows any action no rule names, so the plugin's request is granted
|
|
63
|
+
silently unless a rule says `ask`. Read tools never ask, so the `github_*` glob
|
|
64
|
+
is safe.
|
|
65
|
+
|
|
66
|
+
V1 registers no skills. Unpack the package and copy its `skills/*` folders into
|
|
67
|
+
`~/.config/opencode/skills/`:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
npm pack @craftsamo/agent-github@<version>
|
|
71
|
+
tar -xzf craftsamo-agent-github-<version>.tgz
|
|
72
|
+
mkdir -p ~/.config/opencode/skills
|
|
73
|
+
cp -r package/skills/* ~/.config/opencode/skills/
|
|
74
|
+
rm -rf package craftsamo-agent-github-<version>.tgz
|
|
75
|
+
```
|
|
59
76
|
|
|
60
77
|
### Claude Code
|
|
61
78
|
|
|
@@ -71,6 +88,10 @@ codex plugin marketplace add craftsamo/agent-github --ref v<version>
|
|
|
71
88
|
codex plugin add agent-github@craftsamo
|
|
72
89
|
```
|
|
73
90
|
|
|
91
|
+
Codex starts the MCP server in the plugin's install directory, so name issues
|
|
92
|
+
as `owner/repo#N` or pass `repo` (a bare number fails there with a message saying
|
|
93
|
+
so).
|
|
94
|
+
|
|
74
95
|
### Grok Build
|
|
75
96
|
|
|
76
97
|
```sh
|
|
@@ -89,10 +110,11 @@ agy plugin install https://github.com/craftsamo/agent-github/tree/v<version>
|
|
|
89
110
|
|
|
90
111
|
### Hermes Agent
|
|
91
112
|
|
|
92
|
-
Hermes installs a commit, not a tag:
|
|
113
|
+
Hermes installs a commit, not a tag, and the plugin installs disabled:
|
|
93
114
|
|
|
94
115
|
```sh
|
|
95
116
|
hermes plugins install craftsamo/agent-github --ref <sha>
|
|
117
|
+
hermes plugins enable agent-github
|
|
96
118
|
```
|
|
97
119
|
|
|
98
120
|
### Any other MCP host
|
|
@@ -102,7 +124,7 @@ Add the server to the host's MCP configuration. Flags go in `args`:
|
|
|
102
124
|
```json
|
|
103
125
|
{
|
|
104
126
|
"mcpServers": {
|
|
105
|
-
"github": {
|
|
127
|
+
"agent-github": {
|
|
106
128
|
"command": "npx",
|
|
107
129
|
"args": ["-y", "@craftsamo/agent-github@<version>", "--toolsets", "issues,pull_requests,projects"]
|
|
108
130
|
}
|
|
@@ -112,7 +134,8 @@ Add the server to the host's MCP configuration. Flags go in `args`:
|
|
|
112
134
|
|
|
113
135
|
## Tools and skills
|
|
114
136
|
|
|
115
|
-
Each toolset comes with a skill that tells an agent how to use its tools.
|
|
137
|
+
Each toolset comes with a skill that tells an agent how to use its tools. A
|
|
138
|
+
toolset with no tools yet registers none (0.2.0 ships the `issues` tools).
|
|
116
139
|
|
|
117
140
|
### Issues (`issues`)
|
|
118
141
|
|
|
@@ -131,19 +154,28 @@ The skill is [`github-issues`](skills/github-issues/SKILL.md). An issue's kind
|
|
|
131
154
|
is the organization's Issue Type of that name when it defines one, otherwise a
|
|
132
155
|
`type:<kind>` label.
|
|
133
156
|
|
|
134
|
-
##
|
|
157
|
+
## Reads and writes
|
|
158
|
+
|
|
159
|
+
Every read tool is named `github_<domain>_read`. Reads can run unasked; writes
|
|
160
|
+
are confirmed by the harness.
|
|
161
|
+
|
|
162
|
+
| Harness | Reads without asking |
|
|
163
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
164
|
+
| OpenCode | always; the plugin asks only before a write |
|
|
165
|
+
| Claude Code | the rule `mcp__plugin_agent-github_agent-github__*_read` in `permissions.allow` of `~/.claude/settings.json` or a project |
|
|
166
|
+
| Codex | always; Codex runs tools that declare `readOnlyHint` unasked, as the read tools do |
|
|
167
|
+
| Grok Build | `grok --allow 'MCPTool(agent-github__*_read)'` |
|
|
168
|
+
| Antigravity | an Allow rule `mcp(agent-github/<tool>)` for each read tool; not yet verified |
|
|
169
|
+
| Hermes | always; the plugin asks only before a write |
|
|
135
170
|
|
|
136
|
-
|
|
137
|
-
harness.
|
|
171
|
+
Where a write is asked about, and where it is not:
|
|
138
172
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
| Antigravity | an Allow rule `mcp(github/<tool>)` for each read tool; not yet verified |
|
|
146
|
-
| Hermes | always; the plugin asks only before a write |
|
|
173
|
+
- **OpenCode** grants any action no rule names, so a write runs unasked unless
|
|
174
|
+
a rule asks for it: add the `github_*` rule shown under [OpenCode](#opencode).
|
|
175
|
+
- **Codex** under `codex exec`, and **Grok Build** under `grok -p`, refuse a
|
|
176
|
+
write they cannot ask about, unless it is allowed beforehand.
|
|
177
|
+
- **Hermes** `hermes chat -q` refuses a write it cannot ask about; `hermes -z`
|
|
178
|
+
and `--yolo` skip approval, so writes then run unasked.
|
|
147
179
|
|
|
148
180
|
## Settings
|
|
149
181
|
|
|
@@ -174,9 +206,13 @@ Lists are comma-separated in a flag or a variable. Where each harness reads them
|
|
|
174
206
|
exclude_tools: [github_pr_merge]
|
|
175
207
|
```
|
|
176
208
|
|
|
177
|
-
- **
|
|
178
|
-
|
|
179
|
-
|
|
209
|
+
- **Claude Code and Antigravity** start the plugin's server without flags; Claude
|
|
210
|
+
Code passes the client's environment, so set the variables in the environment
|
|
211
|
+
the harness runs in.
|
|
212
|
+
- **Codex and Grok Build** pass no environment to a plugin's MCP server, so the
|
|
213
|
+
`AGENT_GITHUB_*` variables have no effect there. To change settings in Codex,
|
|
214
|
+
add the server under `[mcp_servers]` in Codex's config with flags in `args` (as
|
|
215
|
+
in [Any other MCP host](#any-other-mcp-host)) instead of using the plugin.
|
|
180
216
|
|
|
181
217
|
## Layout
|
|
182
218
|
|
|
@@ -188,11 +224,12 @@ Lists are comma-separated in a flag or a variable. Where each harness reads them
|
|
|
188
224
|
- `src/hermes/`, `plugin.yaml` and `__init__.py` — the Hermes plugin.
|
|
189
225
|
- `skills/` — one skill per toolset, `skills/<name>/SKILL.md`, which every
|
|
190
226
|
harness that takes skills loads from the package or plugin root.
|
|
191
|
-
- `plugin.json`, `mcp.json`, `.claude-plugin/`, `.agents/plugins/`,
|
|
227
|
+
- `plugin.json`, `mcp.json`, `.mcp.json`, `.claude-plugin/`, `.agents/plugins/`,
|
|
192
228
|
`.antigravity-plugin/` and `mcp_config.json` — the plugin manifests of the
|
|
193
|
-
other harnesses.
|
|
194
|
-
|
|
195
|
-
|
|
229
|
+
other harnesses. The root `.mcp.json` is the configuration Grok Build reads
|
|
230
|
+
(with `${CLAUDE_PLUGIN_ROOT}`, the variable both Grok Build and Claude Code
|
|
231
|
+
expand); when working on this repository in Claude Code, decline the project
|
|
232
|
+
MCP server it offers from that file.
|
|
196
233
|
|
|
197
234
|
How a release is made is in [`RELEASING.md`](RELEASING.md).
|
|
198
235
|
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,13 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
// src/entry/package-root.ts
|
|
9
|
+
import { dirname } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
function packageRoot(bundleUrl) {
|
|
12
|
+
return dirname(dirname(fileURLToPath(bundleUrl)));
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
// node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/external.js
|
|
9
16
|
var external_exports = {};
|
|
10
17
|
__export(external_exports, {
|
|
@@ -20205,13 +20212,13 @@ async function ensureLabel(repo, name, ctx) {
|
|
|
20205
20212
|
function isTypeFailure(error62) {
|
|
20206
20213
|
return isToolError(error62) && TYPE_FAILURE_CODES.includes(error62.code) && TYPE_MENTION.test(error62.message);
|
|
20207
20214
|
}
|
|
20208
|
-
async function withKindFallback(kind, placement,
|
|
20215
|
+
async function withKindFallback(kind, placement, attempt2) {
|
|
20209
20216
|
try {
|
|
20210
|
-
return { placement, result: await
|
|
20217
|
+
return { placement, result: await attempt2(placement) };
|
|
20211
20218
|
} catch (error62) {
|
|
20212
20219
|
if (placement.via !== "type" || !isTypeFailure(error62)) throw error62;
|
|
20213
20220
|
const fallback = labelKind(kind);
|
|
20214
|
-
return { placement: fallback, result: await
|
|
20221
|
+
return { placement: fallback, result: await attempt2(fallback) };
|
|
20215
20222
|
}
|
|
20216
20223
|
}
|
|
20217
20224
|
async function kindFlags(placement, repo, ctx) {
|
|
@@ -20513,6 +20520,8 @@ async function readSubIssues(parent, ctx) {
|
|
|
20513
20520
|
}
|
|
20514
20521
|
|
|
20515
20522
|
// src/core/refs.ts
|
|
20523
|
+
import { realpath } from "node:fs/promises";
|
|
20524
|
+
import { isAbsolute, relative, sep } from "node:path";
|
|
20516
20525
|
var DEFAULT_HOST = "github.com";
|
|
20517
20526
|
var SSH_ALIAS_HOST = "ssh.github.com";
|
|
20518
20527
|
var GIT_CONFIG_ENV = ["GIT_CONFIG_GLOBAL", "GIT_CONFIG_SYSTEM", "GIT_CONFIG_NOSYSTEM"];
|
|
@@ -20596,11 +20605,25 @@ function gitEnv() {
|
|
|
20596
20605
|
}
|
|
20597
20606
|
return { ...env, GIT_TERMINAL_PROMPT: "0" };
|
|
20598
20607
|
}
|
|
20599
|
-
async function
|
|
20608
|
+
async function isWithin(dir, root) {
|
|
20609
|
+
try {
|
|
20610
|
+
const path = relative(await realpath(root), await realpath(dir));
|
|
20611
|
+
return path === "" || !(path === ".." || path.startsWith(`..${sep}`) || isAbsolute(path));
|
|
20612
|
+
} catch {
|
|
20613
|
+
return false;
|
|
20614
|
+
}
|
|
20615
|
+
}
|
|
20616
|
+
async function repoFromOrigin(cwd, signal, ownDir) {
|
|
20600
20617
|
const env = gitEnv();
|
|
20601
|
-
const unresolved = (why) => invalid(
|
|
20602
|
-
`Cannot tell which repository to use: ${why}. Run the call inside a clone of a GitHub repository, or pass \`repo\` as owner/name
|
|
20618
|
+
const unresolved = (why, advice = "") => invalid(
|
|
20619
|
+
`Cannot tell which repository to use: ${why}. Run the call inside a clone of a GitHub repository, or pass \`repo\` as owner/name.${advice}`
|
|
20603
20620
|
);
|
|
20621
|
+
if (ownDir !== void 0 && await isWithin(cwd, ownDir)) {
|
|
20622
|
+
throw unresolved(
|
|
20623
|
+
`${cwd} is where these tools are installed, not a project`,
|
|
20624
|
+
" An issue can be given as `owner/repo#N`."
|
|
20625
|
+
);
|
|
20626
|
+
}
|
|
20604
20627
|
let result;
|
|
20605
20628
|
try {
|
|
20606
20629
|
result = await exec(["git", "remote", "get-url", "origin"], { cwd, env, signal });
|
|
@@ -20615,7 +20638,10 @@ async function repoFromOrigin(cwd, signal) {
|
|
|
20615
20638
|
return repo;
|
|
20616
20639
|
}
|
|
20617
20640
|
async function resolveRepo(repo, ctx) {
|
|
20618
|
-
return repo === void 0 || repo.trim() === "" ? repoFromOrigin(ctx.cwd, ctx.signal) : parseRepo(repo);
|
|
20641
|
+
return repo === void 0 || repo.trim() === "" ? repoFromOrigin(ctx.cwd, ctx.signal, ctx.ownDir) : parseRepo(repo);
|
|
20642
|
+
}
|
|
20643
|
+
function isBareNumber(ref) {
|
|
20644
|
+
return BARE_NUMBER_PATTERN.test(ref.trim());
|
|
20619
20645
|
}
|
|
20620
20646
|
function parseNumber(digits, ref) {
|
|
20621
20647
|
const number4 = Number.parseInt(digits, 10);
|
|
@@ -20666,10 +20692,9 @@ async function parseNumberRef(ref, repoArg, ctx, options = {}) {
|
|
|
20666
20692
|
}
|
|
20667
20693
|
|
|
20668
20694
|
// src/core/github/issue-refs.ts
|
|
20669
|
-
var BARE_NUMBER = /^#?\d+$/;
|
|
20670
20695
|
async function resolveRelatedIssue(ref, target, ctx) {
|
|
20671
20696
|
const text = ref.trim();
|
|
20672
|
-
return parseNumberRef(text,
|
|
20697
|
+
return parseNumberRef(text, isBareNumber(text) ? target.full : void 0, ctx, { accept: "issue" });
|
|
20673
20698
|
}
|
|
20674
20699
|
function issueLabel(issue2) {
|
|
20675
20700
|
return `${issue2.repo.full}#${issue2.number}`;
|
|
@@ -20697,6 +20722,10 @@ function defineTool(spec) {
|
|
|
20697
20722
|
if (!(spec.output instanceof external_exports.ZodObject)) {
|
|
20698
20723
|
throw new Error(`Tool "${spec.id}" must have an object output schema, since a result is an object.`);
|
|
20699
20724
|
}
|
|
20725
|
+
const unknownTarget = Object.keys(spec.targets ?? {}).find((name) => !Object.hasOwn(spec.input.shape, name));
|
|
20726
|
+
if (unknownTarget !== void 0) {
|
|
20727
|
+
throw new Error(`Tool "${spec.id}" declares the target "${unknownTarget}", which is not one of its arguments.`);
|
|
20728
|
+
}
|
|
20700
20729
|
return spec;
|
|
20701
20730
|
}
|
|
20702
20731
|
var CLASS_HINTS = {
|
|
@@ -20802,6 +20831,7 @@ var StepErrors = class {
|
|
|
20802
20831
|
// src/core/issues/write-support.ts
|
|
20803
20832
|
var REPO_DESCRIPTION = "owner/name; defaults to the working tree's repository (its origin). Used for a bare number.";
|
|
20804
20833
|
var ISSUE_DESCRIPTION = "The issue, as 12, #12, owner/repo#12 or its URL.";
|
|
20834
|
+
var ISSUE_TARGETS = { issue: "issue", repo: "repo" };
|
|
20805
20835
|
var LIST_SYNTAX = /[,"\r\n]/;
|
|
20806
20836
|
var URL_LINE = /^https?:\/\/\S+$/;
|
|
20807
20837
|
function invalid2(message) {
|
|
@@ -20871,6 +20901,7 @@ var issueClose = defineTool({
|
|
|
20871
20901
|
].join(" "),
|
|
20872
20902
|
toolset: "issues",
|
|
20873
20903
|
class: "overwrite",
|
|
20904
|
+
targets: ISSUE_TARGETS,
|
|
20874
20905
|
input: input2,
|
|
20875
20906
|
output: output2,
|
|
20876
20907
|
async execute(args, ctx) {
|
|
@@ -20927,6 +20958,7 @@ var issueComment = defineTool({
|
|
|
20927
20958
|
].join(" "),
|
|
20928
20959
|
toolset: "issues",
|
|
20929
20960
|
class: "add",
|
|
20961
|
+
targets: ISSUE_TARGETS,
|
|
20930
20962
|
input: input3,
|
|
20931
20963
|
output: output3,
|
|
20932
20964
|
async execute(args, ctx) {
|
|
@@ -21044,6 +21076,7 @@ var issueCreate = defineTool({
|
|
|
21044
21076
|
].join(" "),
|
|
21045
21077
|
toolset: "issues",
|
|
21046
21078
|
class: "add",
|
|
21079
|
+
targets: { repo: "repo", parent: "issue", blocked_by: "issues" },
|
|
21047
21080
|
input: input4,
|
|
21048
21081
|
output: output4,
|
|
21049
21082
|
async execute(args, ctx) {
|
|
@@ -21191,6 +21224,7 @@ var issueDevelop = defineTool({
|
|
|
21191
21224
|
].join(" "),
|
|
21192
21225
|
toolset: "issues",
|
|
21193
21226
|
class: "idempotent",
|
|
21227
|
+
targets: { ...ISSUE_TARGETS, branch_repo: "repo" },
|
|
21194
21228
|
input: input5,
|
|
21195
21229
|
output: output5,
|
|
21196
21230
|
async execute(args, ctx) {
|
|
@@ -21338,6 +21372,7 @@ var issueEdit = defineTool({
|
|
|
21338
21372
|
].join(" "),
|
|
21339
21373
|
toolset: "issues",
|
|
21340
21374
|
class: "overwrite",
|
|
21375
|
+
targets: ISSUE_TARGETS,
|
|
21341
21376
|
input: input6,
|
|
21342
21377
|
output: output6,
|
|
21343
21378
|
async execute(args, ctx) {
|
|
@@ -21362,14 +21397,14 @@ var issueEdit = defineTool({
|
|
|
21362
21397
|
if (change.removeMilestone) flags.push("--remove-milestone");
|
|
21363
21398
|
const named = new Set([...change.addLabels, ...change.removeLabels].map((label) => label.toLowerCase()));
|
|
21364
21399
|
const swapped = (where) => where.via === "label" ? otherKindLabels(current?.labels ?? [], where.name).filter((label) => !named.has(label.toLowerCase())).flatMap((label) => ["--remove-label", label]) : [];
|
|
21365
|
-
const
|
|
21400
|
+
const attempt2 = async (where) => editIssue(
|
|
21366
21401
|
target,
|
|
21367
21402
|
issue2.number,
|
|
21368
21403
|
where ? [...flags, ...await kindFlags(where, target, ctx), ...swapped(where)] : flags,
|
|
21369
21404
|
ctx,
|
|
21370
21405
|
body
|
|
21371
21406
|
);
|
|
21372
|
-
const applied = kind ? await withKindFallback(kind.name, kind.placement,
|
|
21407
|
+
const applied = kind ? await withKindFallback(kind.name, kind.placement, attempt2) : { placement: void 0, result: await attempt2() };
|
|
21373
21408
|
return {
|
|
21374
21409
|
repo: target.full,
|
|
21375
21410
|
issue: issue2.number,
|
|
@@ -21696,6 +21731,16 @@ var issueRelate = defineTool({
|
|
|
21696
21731
|
].join(" "),
|
|
21697
21732
|
toolset: "issues",
|
|
21698
21733
|
class: "idempotent",
|
|
21734
|
+
targets: {
|
|
21735
|
+
...ISSUE_TARGETS,
|
|
21736
|
+
parent: "issue",
|
|
21737
|
+
add_sub_issues: "issues",
|
|
21738
|
+
remove_sub_issues: "issues",
|
|
21739
|
+
add_blocked_by: "issues",
|
|
21740
|
+
remove_blocked_by: "issues",
|
|
21741
|
+
add_blocking: "issues",
|
|
21742
|
+
remove_blocking: "issues"
|
|
21743
|
+
},
|
|
21699
21744
|
input: input8,
|
|
21700
21745
|
output: output8,
|
|
21701
21746
|
async execute(args, ctx) {
|
|
@@ -21794,6 +21839,7 @@ var issueReopen = defineTool({
|
|
|
21794
21839
|
].join(" "),
|
|
21795
21840
|
toolset: "issues",
|
|
21796
21841
|
class: "overwrite",
|
|
21842
|
+
targets: ISSUE_TARGETS,
|
|
21797
21843
|
input: input9,
|
|
21798
21844
|
output: output9,
|
|
21799
21845
|
async execute(args, ctx) {
|
|
@@ -21824,17 +21870,69 @@ var ALL_TOOLS = [
|
|
|
21824
21870
|
issueDevelop
|
|
21825
21871
|
];
|
|
21826
21872
|
|
|
21827
|
-
// src/
|
|
21828
|
-
var
|
|
21829
|
-
|
|
21830
|
-
|
|
21831
|
-
if (repo !== void 0 && typeof repo !== "string") return ANY_RESOURCE;
|
|
21873
|
+
// src/core/targets.ts
|
|
21874
|
+
var ANY_TARGET = "*";
|
|
21875
|
+
var ISSUE_ARGUMENT = "issue";
|
|
21876
|
+
async function attempt(fn) {
|
|
21832
21877
|
try {
|
|
21833
|
-
return
|
|
21878
|
+
return await fn();
|
|
21834
21879
|
} catch (error62) {
|
|
21835
21880
|
if (isAbortError(error62)) throw error62;
|
|
21836
|
-
return
|
|
21881
|
+
return void 0;
|
|
21882
|
+
}
|
|
21883
|
+
}
|
|
21884
|
+
function isBlank(value) {
|
|
21885
|
+
return typeof value === "string" && value.trim() === "";
|
|
21886
|
+
}
|
|
21887
|
+
function ownRepository(spec, args, ctx) {
|
|
21888
|
+
const repo = args.repo;
|
|
21889
|
+
const issue2 = args[ISSUE_ARGUMENT];
|
|
21890
|
+
let pending;
|
|
21891
|
+
async function resolve() {
|
|
21892
|
+
if (spec.targets?.[ISSUE_ARGUMENT] === "issue" && typeof issue2 === "string" && !isBareNumber(issue2)) {
|
|
21893
|
+
const named = await attempt(() => parseNumberRef(issue2, void 0, ctx, { accept: "issue" }));
|
|
21894
|
+
if (named) return named.repo;
|
|
21895
|
+
}
|
|
21896
|
+
if (repo !== void 0 && typeof repo !== "string") return void 0;
|
|
21897
|
+
return attempt(() => resolveRepo(repo, ctx));
|
|
21898
|
+
}
|
|
21899
|
+
return () => pending ??= resolve();
|
|
21900
|
+
}
|
|
21901
|
+
async function issueRepository(value, own2, ctx) {
|
|
21902
|
+
if (typeof value !== "string") return void 0;
|
|
21903
|
+
const bare = isBareNumber(value);
|
|
21904
|
+
const repoArg = bare ? (await own2())?.full : void 0;
|
|
21905
|
+
if (bare && repoArg === void 0) return void 0;
|
|
21906
|
+
return attempt(async () => (await parseNumberRef(value, repoArg, ctx, { accept: "issue" })).repo);
|
|
21907
|
+
}
|
|
21908
|
+
async function targetRepository(kind, value, own2, ctx) {
|
|
21909
|
+
if (kind !== "repo") return issueRepository(value, own2, ctx);
|
|
21910
|
+
return typeof value === "string" ? attempt(() => parseRepo(value)) : void 0;
|
|
21911
|
+
}
|
|
21912
|
+
async function writeTargets(spec, args, ctx) {
|
|
21913
|
+
const given3 = typeof args === "object" && args !== null ? args : {};
|
|
21914
|
+
const own2 = ownRepository(spec, given3, ctx);
|
|
21915
|
+
const found = /* @__PURE__ */ new Set();
|
|
21916
|
+
const add = (repo) => found.add(repo ? repo.full.toLowerCase() : ANY_TARGET);
|
|
21917
|
+
add(await own2());
|
|
21918
|
+
for (const [name, kind] of Object.entries(spec.targets ?? {})) {
|
|
21919
|
+
const value = given3[name];
|
|
21920
|
+
if (value === void 0) continue;
|
|
21921
|
+
if (kind === "issues" && !Array.isArray(value)) {
|
|
21922
|
+
add(void 0);
|
|
21923
|
+
continue;
|
|
21924
|
+
}
|
|
21925
|
+
for (const item of kind === "issues" ? value : [value]) {
|
|
21926
|
+
if (!isBlank(item)) add(await targetRepository(kind, item, own2, ctx));
|
|
21927
|
+
}
|
|
21837
21928
|
}
|
|
21929
|
+
const repos = [...found].filter((repo) => repo !== ANY_TARGET).sort();
|
|
21930
|
+
return found.has(ANY_TARGET) ? [...repos, ANY_TARGET] : repos;
|
|
21931
|
+
}
|
|
21932
|
+
|
|
21933
|
+
// src/entry/permission.ts
|
|
21934
|
+
function permissionResources(spec, args, ctx) {
|
|
21935
|
+
return writeTargets(spec, args, ctx);
|
|
21838
21936
|
}
|
|
21839
21937
|
|
|
21840
21938
|
// src/entry/settings.ts
|
|
@@ -22014,7 +22112,11 @@ async function runTool(command, io) {
|
|
|
22014
22112
|
const spec = command.selected.find((candidate) => candidate.id === command.toolId);
|
|
22015
22113
|
if (!spec) return writeError(io, "invalid_argument", `Unknown tool "${command.toolId}".`);
|
|
22016
22114
|
try {
|
|
22017
|
-
const result = await invoke(spec, await readArguments(io), {
|
|
22115
|
+
const result = await invoke(spec, await readArguments(io), {
|
|
22116
|
+
cwd: command.cwd,
|
|
22117
|
+
ownDir: io.ownDir,
|
|
22118
|
+
signal: io.signal
|
|
22119
|
+
});
|
|
22018
22120
|
writeJson(io, { result });
|
|
22019
22121
|
return EXIT_OK;
|
|
22020
22122
|
} catch (error62) {
|
|
@@ -22026,9 +22128,15 @@ async function runTool(command, io) {
|
|
|
22026
22128
|
}
|
|
22027
22129
|
}
|
|
22028
22130
|
async function targetOf(command, io) {
|
|
22131
|
+
const spec = io.specs.find((candidate) => candidate.id === command.toolId);
|
|
22132
|
+
if (!spec) return writeError(io, "invalid_argument", `Unknown tool "${command.toolId}".`);
|
|
22029
22133
|
try {
|
|
22030
|
-
const
|
|
22031
|
-
|
|
22134
|
+
const resources = await permissionResources(spec, await readArguments(io), {
|
|
22135
|
+
cwd: command.cwd,
|
|
22136
|
+
ownDir: io.ownDir,
|
|
22137
|
+
signal: io.signal
|
|
22138
|
+
});
|
|
22139
|
+
writeJson(io, { resources });
|
|
22032
22140
|
return EXIT_OK;
|
|
22033
22141
|
} catch (error62) {
|
|
22034
22142
|
if (isToolError(error62)) return writeError(io, error62.code, error62.message);
|
|
@@ -22076,6 +22184,7 @@ async function main() {
|
|
|
22076
22184
|
process.exitCode = await runCli(process.argv.slice(2), {
|
|
22077
22185
|
specs: ALL_TOOLS,
|
|
22078
22186
|
env: process.env,
|
|
22187
|
+
ownDir: packageRoot(import.meta.url),
|
|
22079
22188
|
readStdin,
|
|
22080
22189
|
stdout: (text) => process.stdout.write(text),
|
|
22081
22190
|
stderr: (text) => process.stderr.write(text),
|