@ghx-dev/core 0.2.1 → 0.3.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/.claude-plugin/plugin.json +1 -1
- package/README.md +68 -231
- package/dist/{chunk-M5PJLKL5.js → chunk-7A73AXLY.js} +104 -14
- package/dist/chunk-7A73AXLY.js.map +1 -0
- package/dist/{chunk-HEHONZTO.js → chunk-C2KRRSSX.js} +1 -1
- package/dist/chunk-C2KRRSSX.js.map +1 -0
- package/dist/cli/index.js +23 -29
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +168 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/{issue-mutations-OW464JP3.js → issue-mutations-DIWPF3JH.js} +2 -2
- package/dist/{issue-queries-ORG3VPK4.js → issue-queries-YQL65J7X.js} +2 -2
- package/dist/{pr-mutations-WOTG6FAB.js → pr-mutations-BVHDCAPR.js} +2 -2
- package/dist/{pr-queries-6CJJW7BT.js → pr-queries-NUL2UZJB.js} +2 -2
- package/dist/{project-QFSCYDDW.js → project-3ZSPVIOC.js} +2 -2
- package/dist/{release-33236BBA.js → release-IQCWD655.js} +2 -2
- package/dist/{repo-M6DKCWBG.js → repo-JF47JAZG.js} +2 -2
- package/package.json +5 -5
- package/skills/using-ghx/SKILL.md +24 -4
- package/dist/chunk-HEHONZTO.js.map +0 -1
- package/dist/chunk-M5PJLKL5.js.map +0 -1
- /package/dist/{issue-mutations-OW464JP3.js.map → issue-mutations-DIWPF3JH.js.map} +0 -0
- /package/dist/{issue-queries-ORG3VPK4.js.map → issue-queries-YQL65J7X.js.map} +0 -0
- /package/dist/{pr-mutations-WOTG6FAB.js.map → pr-mutations-BVHDCAPR.js.map} +0 -0
- /package/dist/{pr-queries-6CJJW7BT.js.map → pr-queries-NUL2UZJB.js.map} +0 -0
- /package/dist/{project-QFSCYDDW.js.map → project-3ZSPVIOC.js.map} +0 -0
- /package/dist/{release-33236BBA.js.map → release-IQCWD655.js.map} +0 -0
- /package/dist/{repo-M6DKCWBG.js.map → repo-JF47JAZG.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,283 +1,120 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">@ghx-dev/core</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<img src="https://raw.githubusercontent.com/aryeko/ghx/main/assets/branding/social/ghx-social-dark-1280x640.png" alt="ghx social preview" width="480">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
+
<p align="center">
|
|
8
|
+
A typed GitHub execution router that gives AI agents deterministic, token-efficient access to the GitHub API.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
7
11
|
[](https://www.npmjs.com/package/@ghx-dev/core)
|
|
8
12
|
[](https://www.npmjs.com/package/@ghx-dev/core)
|
|
9
13
|
[](https://github.com/aryeko/ghx/actions/workflows/ci-main.yml)
|
|
10
14
|
[](https://codecov.io/gh/aryeko/ghx)
|
|
11
15
|
[](https://github.com/aryeko/ghx/blob/main/LICENSE)
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Alternative package managers:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
pnpm add @ghx-dev/core
|
|
40
|
-
# or
|
|
41
|
-
yarn add @ghx-dev/core
|
|
17
|
+
## Why ghx?
|
|
18
|
+
|
|
19
|
+
When AI agents use the `gh` CLI directly, they waste thousands of tokens on research, trial-and-error formatting, and guessing JSON parsing paths. **ghx eliminates this waste** by providing a stable, structured execution layer.
|
|
20
|
+
|
|
21
|
+
> **100% success rate, 73% fewer tool calls, 18% fewer active tokens, 54% lower latency** compared to raw CLI usage ([measured across 30 runs](https://github.com/aryeko/ghx/blob/main/docs/eval-report.md) on standard PR workflows with Codex 5.3).
|
|
22
|
+
|
|
23
|
+
```mermaid
|
|
24
|
+
sequenceDiagram
|
|
25
|
+
participant Agent
|
|
26
|
+
participant ghx as ghx
|
|
27
|
+
participant GH as GitHub API
|
|
28
|
+
|
|
29
|
+
%% Agent requests a typed execution
|
|
30
|
+
Agent->>ghx: executeTask("pr.view", { owner, name, prNumber })
|
|
31
|
+
|
|
32
|
+
%% ghx routing engine takes over
|
|
33
|
+
Note over ghx: 1. Validate input schema<br/>2. Select optimal route (GraphQL/CLI)<br/>3. Run preflight checks
|
|
34
|
+
ghx->>GH: typed GraphQL request
|
|
35
|
+
GH-->>ghx: response
|
|
36
|
+
Note over ghx: normalize errors & structure
|
|
37
|
+
|
|
38
|
+
%% Stable envelope returned
|
|
39
|
+
ghx-->>Agent: ResultEnvelope { ok: true, data: { ... } }
|
|
42
40
|
```
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
## Features
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
- **70+ Declarative Capabilities**: PRs, issues, labels, workflows, projects, releases — all defined by versioned YAML operation cards.
|
|
45
|
+
- **Deterministic Routing**: The agent doesn't choose CLI vs. GraphQL. ghx evaluates suitability rules and picks the optimal route automatically, with built-in fallbacks.
|
|
46
|
+
- **Stable Result Envelope**: No try/catch needed. Every execution returns `{ ok, data, error, meta }`. Errors are mapped to standard codes (`AUTH`, `RATE_LIMIT`, `NOT_FOUND`, etc.).
|
|
47
|
+
- **Chaining & Batching**: Execute multiple steps (`add label`, `add assignee`, `comment`) in one call. ghx resolves node IDs and batches them into a single network request.
|
|
48
|
+
- **Type Safety**: Full TypeScript schemas for inputs and outputs (via generated GraphQL types).
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
npm i -g @ghx-dev/core
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Quick Start (CLI)
|
|
57
|
-
|
|
58
|
-
Set `GITHUB_TOKEN` or `GH_TOKEN` in your environment, then:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npx @ghx-dev/core capabilities list
|
|
62
|
-
npx @ghx-dev/core capabilities explain repo.view
|
|
63
|
-
npx @ghx-dev/core run repo.view --input '{"owner":"aryeko","name":"ghx"}'
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
If installed globally, replace `npx @ghx-dev/core` with `ghx`.
|
|
67
|
-
|
|
68
|
-
Every capability returns a stable envelope:
|
|
50
|
+
## Documentation
|
|
69
51
|
|
|
70
|
-
|
|
71
|
-
{
|
|
72
|
-
"ok": true,
|
|
73
|
-
"data": {
|
|
74
|
-
"id": "R_kgDOOx...",
|
|
75
|
-
"name": "ghx",
|
|
76
|
-
"nameWithOwner": "aryeko/ghx"
|
|
77
|
-
},
|
|
78
|
-
"error": null,
|
|
79
|
-
"meta": {
|
|
80
|
-
"capability_id": "repo.view",
|
|
81
|
-
"route_used": "cli",
|
|
82
|
-
"reason": "CARD_PREFERRED"
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
```
|
|
52
|
+
Comprehensive documentation is available in the [`docs/`](./docs/) directory:
|
|
86
53
|
|
|
87
|
-
|
|
54
|
+
- **[Getting Started](./docs/getting-started/README.md)** — Installation, why ghx, and use case diagrams.
|
|
55
|
+
- [Library Quickstart](./docs/getting-started/library-quickstart.md)
|
|
56
|
+
- [CLI Quickstart](./docs/getting-started/cli-quickstart.md)
|
|
57
|
+
- [Agent Setup](./docs/getting-started/agent-setup.md)
|
|
58
|
+
- **[Concepts](./docs/concepts/README.md)** — How ghx works internally (Routing Engine, Operation Cards, Result Envelope, Chaining).
|
|
59
|
+
- **[Architecture](./docs/architecture/README.md)** — System design, execution pipeline, formatters, and GraphQL layer.
|
|
60
|
+
- **[Reference](./docs/reference/README.md)** — API exports, error codes, and a complete table of all 70+ capabilities.
|
|
88
61
|
|
|
89
|
-
|
|
62
|
+
## Quick Start (Library)
|
|
90
63
|
|
|
91
64
|
```bash
|
|
92
|
-
|
|
93
|
-
[
|
|
94
|
-
{"task":"issue.labels.remove","input":{"owner":"acme","name":"repo","issueNumber":42,"labels":["triage"]}},
|
|
95
|
-
{"task":"issue.labels.add","input":{"owner":"acme","name":"repo","issueNumber":42,"labels":["enhancement"]}},
|
|
96
|
-
{"task":"issue.comments.create","input":{"owner":"acme","name":"repo","issueNumber":42,"body":"Triaged."}}
|
|
97
|
-
]
|
|
98
|
-
EOF
|
|
65
|
+
npm install @ghx-dev/core
|
|
99
66
|
```
|
|
100
67
|
|
|
101
|
-
## Quick Start (Library API)
|
|
102
|
-
|
|
103
68
|
```ts
|
|
104
69
|
import { createGithubClientFromToken, executeTask } from "@ghx-dev/core"
|
|
105
70
|
|
|
106
71
|
const token = process.env.GITHUB_TOKEN!
|
|
107
72
|
const githubClient = createGithubClientFromToken(token)
|
|
108
73
|
|
|
74
|
+
// Execute a task: input is validated, optimal route is chosen
|
|
109
75
|
const result = await executeTask(
|
|
110
76
|
{ task: "repo.view", input: { owner: "aryeko", name: "ghx" } },
|
|
111
77
|
{ githubClient, githubToken: token },
|
|
112
78
|
)
|
|
113
79
|
|
|
114
80
|
if (result.ok) {
|
|
115
|
-
console.log(result.data)
|
|
81
|
+
console.log("Success:", result.data.nameWithOwner)
|
|
82
|
+
console.log("Route used:", result.meta.route_used) // e.g. "graphql"
|
|
116
83
|
} else {
|
|
117
|
-
console.error(result.error
|
|
84
|
+
console.error("Failed:", result.error.code) // e.g. "NOT_FOUND"
|
|
85
|
+
console.error("Retryable?", result.error.retryable)
|
|
118
86
|
}
|
|
119
87
|
```
|
|
120
88
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
## Agent Onboarding
|
|
89
|
+
## Quick Start (CLI)
|
|
124
90
|
|
|
125
|
-
|
|
126
|
-
<summary>Install ghx as a project skill for Claude Code</summary>
|
|
91
|
+
Use ghx directly from your terminal or add it as an agent skill.
|
|
127
92
|
|
|
128
93
|
```bash
|
|
129
|
-
|
|
130
|
-
npx @ghx-dev/core
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
The canonical setup skill content is stored in `skills/using-ghx/SKILL.md` (package root). During build/publish it is copied to `dist/skills/using-ghx/SKILL.md`. `ghx setup` writes this content to `.agents/skills/ghx/SKILL.md` in user or project scope.
|
|
134
|
-
|
|
135
|
-
</details>
|
|
136
|
-
|
|
137
|
-
## Agent Tools
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
import {
|
|
141
|
-
createExecuteTool,
|
|
142
|
-
createGithubClientFromToken,
|
|
143
|
-
executeTask,
|
|
144
|
-
explainCapability,
|
|
145
|
-
listCapabilities,
|
|
146
|
-
} from "@ghx-dev/core"
|
|
147
|
-
|
|
148
|
-
// Wire the execute tool to the real engine
|
|
149
|
-
const token = process.env.GITHUB_TOKEN!
|
|
150
|
-
const githubClient = createGithubClientFromToken(token)
|
|
151
|
-
|
|
152
|
-
const tool = createExecuteTool({
|
|
153
|
-
executeTask: (request) => executeTask(request, { githubClient, githubToken: token }),
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
// Discover and execute capabilities
|
|
157
|
-
console.log(listCapabilities())
|
|
158
|
-
console.log(explainCapability("repo.view"))
|
|
159
|
-
const result = await tool.execute("repo.view", { owner: "aryeko", name: "ghx" })
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## 70 Capabilities
|
|
163
|
-
|
|
164
|
-
| Domain | Count | Examples |
|
|
165
|
-
|---|---|---|
|
|
166
|
-
| Repository | 3 | `repo.view`, `repo.labels.list` |
|
|
167
|
-
| Issues | 23 | create/update/close, labels, assignees, milestones, relations |
|
|
168
|
-
| Pull Requests | 21 | diff, threads, reviews, checks, merge, branch update |
|
|
169
|
-
| Workflows and CI | 11 | runs, jobs, logs, dispatch, rerun, cancel, artifacts |
|
|
170
|
-
| Releases | 5 | view, list, create, update, publish |
|
|
171
|
-
| Projects v2 | 7 | items, fields, add/remove issues |
|
|
172
|
-
|
|
173
|
-
Full list: `ghx capabilities list` or [operation card registry](https://github.com/aryeko/ghx/tree/main/packages/core/src/core/registry/cards).
|
|
174
|
-
|
|
175
|
-
## Result Envelope
|
|
94
|
+
# List all 70+ capabilities
|
|
95
|
+
npx @ghx-dev/core capabilities list
|
|
176
96
|
|
|
177
|
-
|
|
97
|
+
# Run a capability
|
|
98
|
+
npx @ghx-dev/core run pr.view --input '{"owner":"aryeko","name":"ghx","number":42}'
|
|
178
99
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
message: string
|
|
186
|
-
retryable: boolean
|
|
187
|
-
details?: Record<string, unknown>
|
|
188
|
-
}
|
|
189
|
-
meta: {
|
|
190
|
-
capability_id: string
|
|
191
|
-
route_used?: "cli" | "graphql" | "rest"
|
|
192
|
-
reason?: string
|
|
193
|
-
attempts?: Array<{
|
|
194
|
-
route: "cli" | "graphql" | "rest"
|
|
195
|
-
status: "success" | "error" | "skipped"
|
|
196
|
-
error_code?: string
|
|
197
|
-
duration_ms?: number
|
|
198
|
-
}>
|
|
199
|
-
}
|
|
200
|
-
}
|
|
100
|
+
# Output is a standard ResultEnvelope:
|
|
101
|
+
# {
|
|
102
|
+
# "ok": true,
|
|
103
|
+
# "data": { ... },
|
|
104
|
+
# "meta": { "capability_id": "pr.view", "route_used": "graphql", ... }
|
|
105
|
+
# }
|
|
201
106
|
```
|
|
202
107
|
|
|
203
|
-
##
|
|
204
|
-
|
|
205
|
-
- `GITHUB_TOKEN` or `GH_TOKEN` (required)
|
|
206
|
-
- `GITHUB_GRAPHQL_URL` (optional; override GraphQL endpoint)
|
|
207
|
-
- `GH_HOST` (optional; derives enterprise GraphQL endpoint)
|
|
208
|
-
|
|
209
|
-
## Security and Permissions
|
|
210
|
-
|
|
211
|
-
- Start with least privilege and grant only what your capability set needs.
|
|
212
|
-
- For quick local testing, a classic PAT with `repo` scope is the simplest route.
|
|
213
|
-
- For production agents, prefer fine-grained tokens with read permissions first (`Metadata`, `Contents`, `Pull requests`, `Issues`, `Actions`, `Projects`) and add writes only where needed.
|
|
108
|
+
## Agent Integration
|
|
214
109
|
|
|
215
|
-
|
|
110
|
+
To install the `ghx` skill for Claude Code:
|
|
216
111
|
|
|
217
|
-
|
|
218
|
-
-
|
|
219
|
-
- Route adapters: CLI and GraphQL
|
|
220
|
-
|
|
221
|
-
<details>
|
|
222
|
-
<summary>Public Exports</summary>
|
|
223
|
-
|
|
224
|
-
Root (`@ghx-dev/core`):
|
|
225
|
-
|
|
226
|
-
- `executeTask` -- run a capability
|
|
227
|
-
- `createGithubClientFromToken` -- create a client from a token string
|
|
228
|
-
- `createGithubClient`, `createGraphqlClient` -- create clients from a custom transport
|
|
229
|
-
- `listOperationCards`, `getOperationCard` -- inspect capability registry
|
|
230
|
-
- `createSafeCliCommandRunner` -- custom CLI execution
|
|
231
|
-
- Types: `TaskRequest`, `ResultEnvelope`, `ResultError`, `ResultMeta`, `AttemptMeta`, `RouteSource`, `RouteReasonCode`, `TokenClientOptions`
|
|
232
|
-
|
|
233
|
-
Subpaths:
|
|
234
|
-
|
|
235
|
-
- `@ghx-dev/core/cli` -- CLI entrypoint
|
|
236
|
-
|
|
237
|
-
</details>
|
|
238
|
-
|
|
239
|
-
<details>
|
|
240
|
-
<a id="custom-graphql-transport"></a>
|
|
241
|
-
<summary>Custom GraphQL Transport</summary>
|
|
242
|
-
|
|
243
|
-
For full control over the GraphQL layer, pass your own transport to `createGithubClient`:
|
|
244
|
-
|
|
245
|
-
```ts
|
|
246
|
-
import { createGithubClient, executeTask } from "@ghx-dev/core"
|
|
247
|
-
|
|
248
|
-
const githubClient = createGithubClient({
|
|
249
|
-
async execute<TData>(query: string, variables?: Record<string, unknown>): Promise<TData> {
|
|
250
|
-
const response = await fetch("https://api.github.com/graphql", {
|
|
251
|
-
method: "POST",
|
|
252
|
-
headers: {
|
|
253
|
-
"content-type": "application/json",
|
|
254
|
-
authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
|
255
|
-
},
|
|
256
|
-
body: JSON.stringify({ query, variables: variables ?? {} }),
|
|
257
|
-
})
|
|
258
|
-
const payload = (await response.json()) as { data?: TData; errors?: Array<{ message?: string }> }
|
|
259
|
-
if (payload.errors?.length) throw new Error(payload.errors[0]?.message ?? "GraphQL error")
|
|
260
|
-
if (payload.data === undefined) throw new Error("GraphQL response missing data")
|
|
261
|
-
return payload.data
|
|
262
|
-
},
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
const result = await executeTask(
|
|
266
|
-
{ task: "repo.view", input: { owner: "aryeko", name: "ghx" } },
|
|
267
|
-
{ githubClient, githubToken: process.env.GITHUB_TOKEN },
|
|
268
|
-
)
|
|
112
|
+
```bash
|
|
113
|
+
npx @ghx-dev/core setup --scope project --yes
|
|
269
114
|
```
|
|
270
115
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
## Documentation
|
|
274
|
-
|
|
275
|
-
- [Documentation Hub](https://github.com/aryeko/ghx/blob/main/docs/README.md)
|
|
276
|
-
- [Architecture](https://github.com/aryeko/ghx/blob/main/docs/architecture/README.md)
|
|
277
|
-
- [Capabilities Reference](https://github.com/aryeko/ghx/blob/main/docs/capabilities/README.md)
|
|
278
|
-
- [Operation Cards](https://github.com/aryeko/ghx/blob/main/docs/architecture/operation-cards.md)
|
|
279
|
-
- [Publishing Guide](https://github.com/aryeko/ghx/blob/main/docs/contributing/publishing.md)
|
|
116
|
+
This installs `.agents/skills/ghx/SKILL.md` which teaches Claude how to use `npx @ghx-dev/core` for reliable GitHub interactions.
|
|
280
117
|
|
|
281
118
|
## License
|
|
282
119
|
|
|
283
|
-
MIT
|
|
120
|
+
MIT
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
import {
|
|
77
77
|
createGraphqlClient,
|
|
78
78
|
createTokenTransport
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-C2KRRSSX.js";
|
|
80
80
|
|
|
81
81
|
// src/core/execution/cli/safe-runner.ts
|
|
82
82
|
import { spawn } from "child_process";
|
|
@@ -180,9 +180,97 @@ function createSafeCliCommandRunner(options) {
|
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
// src/core/auth/resolve-token.ts
|
|
184
|
+
import { statSync } from "fs";
|
|
185
|
+
import { mkdir, readFile, rename, unlink, writeFile } from "fs/promises";
|
|
186
|
+
import { homedir } from "os";
|
|
187
|
+
import { join } from "path";
|
|
188
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
189
|
+
var GH_AUTH_TIMEOUT_MS = 5e3;
|
|
190
|
+
function resolveHostname() {
|
|
191
|
+
return process.env.GH_HOST || "github.com";
|
|
192
|
+
}
|
|
193
|
+
function resolveCacheDir() {
|
|
194
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
|
|
195
|
+
return join(base, "ghx", "tokens");
|
|
196
|
+
}
|
|
197
|
+
function resolveCachePath() {
|
|
198
|
+
return join(resolveCacheDir(), resolveHostname());
|
|
199
|
+
}
|
|
200
|
+
async function readCachedToken() {
|
|
201
|
+
const cachePath = resolveCachePath();
|
|
202
|
+
try {
|
|
203
|
+
const stat = statSync(cachePath);
|
|
204
|
+
if (Date.now() - stat.mtimeMs > CACHE_TTL_MS) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
} catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
const content = await readFile(cachePath, "utf8");
|
|
212
|
+
const trimmed = content.trim();
|
|
213
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
214
|
+
} catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async function writeCachedToken(token) {
|
|
219
|
+
const cacheDir = resolveCacheDir();
|
|
220
|
+
const cachePath = resolveCachePath();
|
|
221
|
+
const tmpPath = `${cachePath}.${process.pid}.tmp`;
|
|
222
|
+
await mkdir(cacheDir, { recursive: true, mode: 448 });
|
|
223
|
+
await writeFile(tmpPath, token, { mode: 384 });
|
|
224
|
+
await rename(tmpPath, cachePath);
|
|
225
|
+
}
|
|
226
|
+
async function resolveFromGhCli() {
|
|
227
|
+
const runner = createSafeCliCommandRunner();
|
|
228
|
+
const hostname = resolveHostname();
|
|
229
|
+
const args = hostname === "github.com" ? ["auth", "token"] : ["auth", "token", "--hostname", hostname];
|
|
230
|
+
try {
|
|
231
|
+
const result = await runner.run("gh", args, GH_AUTH_TIMEOUT_MS);
|
|
232
|
+
if (result.exitCode !== 0) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
const token = result.stdout.trim();
|
|
236
|
+
return token.length > 0 ? token : null;
|
|
237
|
+
} catch {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async function resolveGithubToken() {
|
|
242
|
+
const githubToken = process.env.GITHUB_TOKEN?.trim();
|
|
243
|
+
if (githubToken && githubToken.length > 0) {
|
|
244
|
+
return { token: githubToken, source: "env" };
|
|
245
|
+
}
|
|
246
|
+
const ghToken = process.env.GH_TOKEN?.trim();
|
|
247
|
+
if (ghToken && ghToken.length > 0) {
|
|
248
|
+
return { token: ghToken, source: "env" };
|
|
249
|
+
}
|
|
250
|
+
const cached = await readCachedToken();
|
|
251
|
+
if (cached !== null) {
|
|
252
|
+
return { token: cached, source: "cache" };
|
|
253
|
+
}
|
|
254
|
+
const ghCliToken = await resolveFromGhCli();
|
|
255
|
+
if (ghCliToken !== null) {
|
|
256
|
+
await writeCachedToken(ghCliToken).catch(() => {
|
|
257
|
+
});
|
|
258
|
+
return { token: ghCliToken, source: "gh-cli" };
|
|
259
|
+
}
|
|
260
|
+
throw new Error(
|
|
261
|
+
"GitHub token not found. Set GITHUB_TOKEN or GH_TOKEN environment variable, or authenticate with: gh auth login"
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
async function invalidateTokenCache() {
|
|
265
|
+
try {
|
|
266
|
+
await unlink(resolveCachePath());
|
|
267
|
+
} catch {
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
183
271
|
// src/core/registry/index.ts
|
|
184
272
|
import { readdirSync, readFileSync } from "fs";
|
|
185
|
-
import { dirname, extname, join } from "path";
|
|
273
|
+
import { dirname, extname, join as join2 } from "path";
|
|
186
274
|
import { fileURLToPath } from "url";
|
|
187
275
|
import { load as parseYaml } from "js-yaml";
|
|
188
276
|
|
|
@@ -381,7 +469,7 @@ var operationCardSchema = {
|
|
|
381
469
|
var validateCard = ajv.compile(operationCardSchema);
|
|
382
470
|
function cardDirectory() {
|
|
383
471
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
384
|
-
return
|
|
472
|
+
return join2(currentDir, "cards");
|
|
385
473
|
}
|
|
386
474
|
function loadCardsFromYaml() {
|
|
387
475
|
const directory = cardDirectory();
|
|
@@ -472,7 +560,7 @@ function loadCardsFromYaml() {
|
|
|
472
560
|
return a.localeCompare(b);
|
|
473
561
|
});
|
|
474
562
|
return entries.map((entry) => {
|
|
475
|
-
const filePath =
|
|
563
|
+
const filePath = join2(directory, entry);
|
|
476
564
|
const raw = readFileSync(filePath, "utf8");
|
|
477
565
|
const parsed = parseYaml(raw);
|
|
478
566
|
const validation = validateOperationCard(parsed);
|
|
@@ -745,7 +833,7 @@ function createLogger(config) {
|
|
|
745
833
|
}
|
|
746
834
|
function write(level, msg, ctx) {
|
|
747
835
|
if (levelIndex(level) < minIndex) return;
|
|
748
|
-
const version = true ? "0.
|
|
836
|
+
const version = true ? "0.3.0" : "unknown";
|
|
749
837
|
const entry = {
|
|
750
838
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
751
839
|
pid: config.pid,
|
|
@@ -856,7 +944,7 @@ function assembleChainResult(input) {
|
|
|
856
944
|
};
|
|
857
945
|
}
|
|
858
946
|
if (alias in mutationRawResult) {
|
|
859
|
-
return { task: req.task, ok: true
|
|
947
|
+
return { task: req.task, ok: true };
|
|
860
948
|
}
|
|
861
949
|
if (alias in queryRawResult) {
|
|
862
950
|
return { task: req.task, ok: true, data: queryRawResult[alias] };
|
|
@@ -6049,13 +6137,13 @@ function createGithubClient(transport) {
|
|
|
6049
6137
|
let prMutations;
|
|
6050
6138
|
let release;
|
|
6051
6139
|
let project;
|
|
6052
|
-
const loadRepo = async () => repo ??= await import("./repo-
|
|
6053
|
-
const loadIssueQueries = async () => issueQueries ??= await import("./issue-queries-
|
|
6054
|
-
const loadIssueMutations = async () => issueMutations ??= await import("./issue-mutations-
|
|
6055
|
-
const loadPrQueries = async () => prQueries ??= await import("./pr-queries-
|
|
6056
|
-
const loadPrMutations = async () => prMutations ??= await import("./pr-mutations-
|
|
6057
|
-
const loadRelease = async () => release ??= await import("./release-
|
|
6058
|
-
const loadProject = async () => project ??= await import("./project-
|
|
6140
|
+
const loadRepo = async () => repo ??= await import("./repo-JF47JAZG.js");
|
|
6141
|
+
const loadIssueQueries = async () => issueQueries ??= await import("./issue-queries-YQL65J7X.js");
|
|
6142
|
+
const loadIssueMutations = async () => issueMutations ??= await import("./issue-mutations-DIWPF3JH.js");
|
|
6143
|
+
const loadPrQueries = async () => prQueries ??= await import("./pr-queries-NUL2UZJB.js");
|
|
6144
|
+
const loadPrMutations = async () => prMutations ??= await import("./pr-mutations-BVHDCAPR.js");
|
|
6145
|
+
const loadRelease = async () => release ??= await import("./release-IQCWD655.js");
|
|
6146
|
+
const loadProject = async () => project ??= await import("./project-3ZSPVIOC.js");
|
|
6059
6147
|
return {
|
|
6060
6148
|
query: (query, variables) => graphqlClient.query(query, variables),
|
|
6061
6149
|
queryRaw: (query, variables) => graphqlClient.queryRaw(query, variables),
|
|
@@ -6116,6 +6204,8 @@ function createGithubClient(transport) {
|
|
|
6116
6204
|
|
|
6117
6205
|
export {
|
|
6118
6206
|
createSafeCliCommandRunner,
|
|
6207
|
+
resolveGithubToken,
|
|
6208
|
+
invalidateTokenCache,
|
|
6119
6209
|
listOperationCards,
|
|
6120
6210
|
getOperationCard,
|
|
6121
6211
|
extractArrayItemHints,
|
|
@@ -6129,4 +6219,4 @@ export {
|
|
|
6129
6219
|
createGithubClientFromToken,
|
|
6130
6220
|
createGithubClient
|
|
6131
6221
|
};
|
|
6132
|
-
//# sourceMappingURL=chunk-
|
|
6222
|
+
//# sourceMappingURL=chunk-7A73AXLY.js.map
|