@foundation0/api 1.0.1 → 1.1.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 +9 -9
- package/agents.ts +429 -4
- package/git.ts +6 -23
- package/mcp/cli.mjs +1 -1
- package/mcp/cli.ts +40 -40
- package/mcp/client.ts +9 -9
- package/mcp/index.ts +9 -9
- package/mcp/server.ts +6 -6
- package/package.json +4 -6
- package/projects.ts +11 -11
- package/dist/git.js +0 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# example-org MCP Server
|
|
2
2
|
|
|
3
|
-
Install and register the
|
|
3
|
+
Install and register the example-org MCP server with the MCP-enabled agent/tooling you use.
|
|
4
4
|
|
|
5
5
|
## 1) Install
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ The runnable entrypoint is `f0-mcp` (available from `bin` when installed globall
|
|
|
23
23
|
The server supports:
|
|
24
24
|
|
|
25
25
|
- `GITEA_HOST` (recommended, required by git-backed tools)
|
|
26
|
-
- `
|
|
26
|
+
- `FALLBACK_GITEA_HOST` (fallback host variable)
|
|
27
27
|
- `GITEA_TOKEN` (for authenticated actions)
|
|
28
28
|
- `MCP_TOOLS_PREFIX` (or `--tools-prefix`) to namespace tools in clients
|
|
29
29
|
|
|
@@ -37,7 +37,7 @@ Useful defaults:
|
|
|
37
37
|
### A) `.codex/config.toml`
|
|
38
38
|
|
|
39
39
|
```toml
|
|
40
|
-
[mcp_servers.
|
|
40
|
+
[mcp_servers.example]
|
|
41
41
|
command = "bun"
|
|
42
42
|
args = ["x", "@foundation0/api", "f0-mcp"]
|
|
43
43
|
enabled = true
|
|
@@ -45,7 +45,7 @@ startup_timeout_ms = 20_000
|
|
|
45
45
|
env = {
|
|
46
46
|
GITEA_HOST = "https://gitea.example.com",
|
|
47
47
|
GITEA_TOKEN = "your-token",
|
|
48
|
-
MCP_TOOLS_PREFIX = "
|
|
48
|
+
MCP_TOOLS_PREFIX = "example"
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
@@ -61,9 +61,9 @@ args = []
|
|
|
61
61
|
```json
|
|
62
62
|
{
|
|
63
63
|
"mcpServers": {
|
|
64
|
-
"
|
|
64
|
+
"example": {
|
|
65
65
|
"command": "bun",
|
|
66
|
-
"args": ["x", "@foundation0/api", "f0-mcp", "--tools-prefix", "
|
|
66
|
+
"args": ["x", "@foundation0/api", "f0-mcp", "--tools-prefix", "example"],
|
|
67
67
|
"env": {
|
|
68
68
|
"GITEA_HOST": "https://gitea.example.com",
|
|
69
69
|
"GITEA_TOKEN": "your-token"
|
|
@@ -82,7 +82,7 @@ Use the same command/args/env block in your MCP server configuration area:
|
|
|
82
82
|
```json
|
|
83
83
|
{
|
|
84
84
|
"command": "bun",
|
|
85
|
-
"args": ["x", "@foundation0/api", "f0-mcp", "--tools-prefix", "
|
|
85
|
+
"args": ["x", "@foundation0/api", "f0-mcp", "--tools-prefix", "example"],
|
|
86
86
|
"env": {
|
|
87
87
|
"GITEA_HOST": "https://gitea.example.com",
|
|
88
88
|
"GITEA_TOKEN": "your-token"
|
|
@@ -105,7 +105,7 @@ Add environment variables for host/token and optional `MCP_TOOLS_PREFIX`.
|
|
|
105
105
|
f0-mcp --help
|
|
106
106
|
|
|
107
107
|
# examples
|
|
108
|
-
f0-mcp --tools-prefix=
|
|
108
|
+
f0-mcp --tools-prefix=example --server-name=my-example
|
|
109
109
|
f0-mcp --tools-prefix api --server-version 1.2.3
|
|
110
110
|
```
|
|
111
111
|
|
package/agents.ts
CHANGED
|
@@ -23,12 +23,25 @@ export interface AgentLoadResult {
|
|
|
23
23
|
loaded: unknown
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface AgentRunResult {
|
|
27
|
+
agentName: string
|
|
28
|
+
exitCode: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface AgentCreateResult {
|
|
32
|
+
agentName: string
|
|
33
|
+
agentRoot: string
|
|
34
|
+
createdPaths: string[]
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
interface ActiveConfigInput {
|
|
27
38
|
path: string
|
|
28
39
|
required: boolean
|
|
29
40
|
}
|
|
30
41
|
|
|
31
|
-
const CLI_NAME = '
|
|
42
|
+
const CLI_NAME = 'example'
|
|
43
|
+
const AGENT_INITIAL_VERSION = 'v0.0.1'
|
|
44
|
+
const DEFAULT_SKILL_NAME = 'coding-standards'
|
|
32
45
|
const VERSION_RE = 'v?\\d+(?:\\.\\d+){2,}'
|
|
33
46
|
const VERSION_RE_CORE = `(?:${VERSION_RE})`
|
|
34
47
|
const VERSION_WITH_EXT_RE = new RegExp(`^(.+)\\.(${VERSION_RE})\\.([A-Za-z][A-Za-z0-9_-]*)$`)
|
|
@@ -36,13 +49,16 @@ const VERSION_ONLY_RE = new RegExp(`^(.+)\\.(${VERSION_RE})$`)
|
|
|
36
49
|
const PRIORITIZED_EXTS = ['.md', '.json', '.yaml', '.yml', '.ts', '.js', '.txt']
|
|
37
50
|
|
|
38
51
|
export function usage(): string {
|
|
39
|
-
return `Usage:\n ${CLI_NAME} agents <agent-name> <file-path> --set-active\n ${CLI_NAME} agents --list\n ${CLI_NAME} agents <agent-name> load\n\n` +
|
|
40
|
-
`Examples:\n ${CLI_NAME} agents coder /system/boot.v0.0.1 --set-active\n ${CLI_NAME} agents coder /system/boot --set-active --latest\n ${CLI_NAME} agents coder /skills/coding-standards.v0.0.1 --set-active\n ${CLI_NAME} agents --list\n` +
|
|
52
|
+
return `Usage:\n ${CLI_NAME} agents create <agent-name>\n ${CLI_NAME} agents <agent-name> <file-path> --set-active\n ${CLI_NAME} agents --list\n ${CLI_NAME} agents <agent-name> load\n ${CLI_NAME} agents <agent-name> run [codex-args...]\n\n` +
|
|
53
|
+
`Examples:\n ${CLI_NAME} agents create reviewer\n ${CLI_NAME} agents coder /system/boot.v0.0.1 --set-active\n ${CLI_NAME} agents coder /system/boot --set-active --latest\n ${CLI_NAME} agents coder /skills/coding-standards.v0.0.1 --set-active\n ${CLI_NAME} agents --list\n` +
|
|
41
54
|
` ${CLI_NAME} agents coder load\n` +
|
|
55
|
+
` ${CLI_NAME} agents coder run --model gpt-5\n` +
|
|
42
56
|
`\n` +
|
|
43
57
|
`file-path is relative to the agent root (leading slash required).\n` +
|
|
44
58
|
`Use --latest to resolve /file-name to the latest version.\n` +
|
|
45
|
-
`The active file created is [file].active.<ext>.\n`
|
|
59
|
+
`The active file created is [file].active.<ext>.\n` +
|
|
60
|
+
`Use "run" to start codex with developer_instructions from system/prompt.ts.\n` +
|
|
61
|
+
`Set EXAMPLE_CODEX_BIN to pin a specific codex binary.\n`
|
|
46
62
|
}
|
|
47
63
|
|
|
48
64
|
export function resolveAgentsRoot(processRoot: string = process.cwd()): string {
|
|
@@ -76,6 +92,200 @@ export function listAgents(processRoot: string = process.cwd()): string[] {
|
|
|
76
92
|
.sort((a, b) => a.localeCompare(b))
|
|
77
93
|
}
|
|
78
94
|
|
|
95
|
+
function normalizeAgentName(agentName: string): string {
|
|
96
|
+
if (!agentName || typeof agentName !== 'string') {
|
|
97
|
+
throw new Error('agent-name is required.')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const normalized = agentName.trim()
|
|
101
|
+
if (!normalized) {
|
|
102
|
+
throw new Error('agent-name is required.')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (normalized.startsWith('-')) {
|
|
106
|
+
throw new Error(`Invalid agent-name: ${agentName}`)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (normalized === '.' || normalized === '..' || normalized.includes('/') || normalized.includes('\\')) {
|
|
110
|
+
throw new Error(`Invalid agent-name: ${agentName}`)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(normalized)) {
|
|
114
|
+
throw new Error(`Invalid agent-name: ${agentName}`)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return normalized
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function titleCaseAgentName(agentName: string): string {
|
|
121
|
+
return agentName
|
|
122
|
+
.split(/[-_]+/)
|
|
123
|
+
.filter(Boolean)
|
|
124
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
125
|
+
.join(' ')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function buildBootDocument(agentName: string): string {
|
|
129
|
+
const title = titleCaseAgentName(agentName) || agentName
|
|
130
|
+
return `# ${title} Agent Boot (${AGENT_INITIAL_VERSION})
|
|
131
|
+
|
|
132
|
+
You are the \`${agentName}\` agent.
|
|
133
|
+
|
|
134
|
+
## Role
|
|
135
|
+
- Follow the active workflow and execute scoped tasks.
|
|
136
|
+
- Keep outputs concise, concrete, and implementation-focused.
|
|
137
|
+
- Avoid changing unrelated files or behavior.
|
|
138
|
+
|
|
139
|
+
## Startup Sequence
|
|
140
|
+
1. Read active boot/workflow docs and enabled skills.
|
|
141
|
+
2. Confirm scope and constraints before changes.
|
|
142
|
+
3. Apply the smallest safe change set.
|
|
143
|
+
4. Report changed files and outcomes.
|
|
144
|
+
`
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function buildWorkflowDocument(agentName: string): string {
|
|
148
|
+
return `# ${titleCaseAgentName(agentName) || agentName} Workflow (${AGENT_INITIAL_VERSION})
|
|
149
|
+
|
|
150
|
+
1. Parse request and constraints.
|
|
151
|
+
2. Identify exact files and minimal edits.
|
|
152
|
+
3. Implement and verify changes.
|
|
153
|
+
4. If blocked, stop and report the blocker.
|
|
154
|
+
5. Return result summary with next actions if needed.
|
|
155
|
+
`
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function buildToolsConfig(): string {
|
|
159
|
+
return `${JSON.stringify({
|
|
160
|
+
tools: [
|
|
161
|
+
{
|
|
162
|
+
name: 'shell_command',
|
|
163
|
+
enabled: true,
|
|
164
|
+
description: 'Execute shell commands for file and workspace operations.',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'apply_patch',
|
|
168
|
+
enabled: true,
|
|
169
|
+
description: 'Apply focused file edits safely.',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'read_file',
|
|
173
|
+
enabled: true,
|
|
174
|
+
description: 'Read files when needed for context.',
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
permissions: {
|
|
178
|
+
network: false,
|
|
179
|
+
write: true,
|
|
180
|
+
delete: true,
|
|
181
|
+
},
|
|
182
|
+
}, null, 2)}
|
|
183
|
+
`
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function buildModelConfig(): string {
|
|
187
|
+
return `${JSON.stringify({
|
|
188
|
+
provider: 'openai',
|
|
189
|
+
model: 'gpt-5',
|
|
190
|
+
temperature: 0.2,
|
|
191
|
+
max_tokens: 4096,
|
|
192
|
+
top_p: 0.95,
|
|
193
|
+
}, null, 2)}
|
|
194
|
+
`
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function buildDefaultSkillDocument(): string {
|
|
198
|
+
return `# Coding Standards (${AGENT_INITIAL_VERSION})
|
|
199
|
+
|
|
200
|
+
- Keep changes minimal and focused on the request.
|
|
201
|
+
- Preserve existing behavior unless explicitly changing it.
|
|
202
|
+
- Prefer readable, deterministic implementations.
|
|
203
|
+
`
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const SYSTEM_PROMPT_TS_TEMPLATE = `import * as fs from 'fs'
|
|
207
|
+
import * as path from 'path'
|
|
208
|
+
|
|
209
|
+
const base = path.join(__dirname)
|
|
210
|
+
const readActive = (p: string) => fs.readFileSync(path.join(base, p), 'utf8')
|
|
211
|
+
|
|
212
|
+
export const boot = readActive('boot.active.md')
|
|
213
|
+
export const workflow = readActive('workflow.active.md')
|
|
214
|
+
export const tools = JSON.parse(readActive('tools.active.json'))
|
|
215
|
+
export const model = JSON.parse(readActive('model.active.json'))
|
|
216
|
+
|
|
217
|
+
export const prompt = [boot, workflow].join('\\n\\n')
|
|
218
|
+
|
|
219
|
+
export const agentConfig = {
|
|
220
|
+
boot,
|
|
221
|
+
workflow,
|
|
222
|
+
tools,
|
|
223
|
+
model,
|
|
224
|
+
prompt,
|
|
225
|
+
}
|
|
226
|
+
`
|
|
227
|
+
|
|
228
|
+
const SKILLS_TS_TEMPLATE = `import * as fs from 'fs'
|
|
229
|
+
import * as path from 'path'
|
|
230
|
+
|
|
231
|
+
export interface SkillFile {
|
|
232
|
+
id: string
|
|
233
|
+
version: string
|
|
234
|
+
activeFile: string
|
|
235
|
+
resolvedFile: string
|
|
236
|
+
content: string
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const skillsDir = path.join(__dirname)
|
|
240
|
+
const enabledListPath = path.join(skillsDir, 'enabled-skills.md')
|
|
241
|
+
|
|
242
|
+
const resolveVersionAndId = (activeFile: string) => {
|
|
243
|
+
const baseName = path.basename(activeFile, '.active.md')
|
|
244
|
+
const resolved = \`\${baseName}.${AGENT_INITIAL_VERSION}.md\`
|
|
245
|
+
return {
|
|
246
|
+
id: baseName,
|
|
247
|
+
version: '${AGENT_INITIAL_VERSION}',
|
|
248
|
+
resolvedFile: resolved,
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const enabledLines = fs
|
|
253
|
+
.readFileSync(enabledListPath, 'utf8')
|
|
254
|
+
.split(/\\r?\\n/)
|
|
255
|
+
.map((line) => line.trim())
|
|
256
|
+
.filter(Boolean)
|
|
257
|
+
|
|
258
|
+
export const skills: SkillFile[] = enabledLines.map((activeFile) => {
|
|
259
|
+
const resolved = resolveVersionAndId(activeFile)
|
|
260
|
+
return {
|
|
261
|
+
...resolved,
|
|
262
|
+
activeFile,
|
|
263
|
+
content: fs.readFileSync(path.join(skillsDir, resolved.resolvedFile), 'utf8'),
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
`
|
|
267
|
+
|
|
268
|
+
const LOAD_TS_TEMPLATE = `import { readFileSync } from 'fs'
|
|
269
|
+
import * as path from 'path'
|
|
270
|
+
|
|
271
|
+
import { agentConfig } from './system/prompt'
|
|
272
|
+
import { skills } from './skills/skills'
|
|
273
|
+
|
|
274
|
+
const activeDoc = path.join(__dirname, 'system')
|
|
275
|
+
|
|
276
|
+
const loadActive = (name: string) =>
|
|
277
|
+
readFileSync(path.join(activeDoc, name), 'utf8').trim()
|
|
278
|
+
|
|
279
|
+
export const load = () => ({
|
|
280
|
+
...agentConfig,
|
|
281
|
+
bootDoc: loadActive('boot.active.md'),
|
|
282
|
+
workflowDoc: loadActive('workflow.active.md'),
|
|
283
|
+
skills,
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
export type AgentBundle = ReturnType<typeof load>
|
|
287
|
+
`
|
|
288
|
+
|
|
79
289
|
export function parseTargetSpec(spec: string): VersionedFileSpec {
|
|
80
290
|
if (!spec || typeof spec !== 'string') {
|
|
81
291
|
throw new Error('file-path is required.')
|
|
@@ -285,6 +495,68 @@ function createWindowsSymlink(activeFile: string, sourceFile: string): boolean {
|
|
|
285
495
|
return result.status === 0
|
|
286
496
|
}
|
|
287
497
|
|
|
498
|
+
export function createAgent(agentName: string, processRoot: string = process.cwd()): AgentCreateResult {
|
|
499
|
+
const normalizedAgentName = normalizeAgentName(agentName)
|
|
500
|
+
const agentsRoot = resolveAgentsRootFrom(processRoot)
|
|
501
|
+
const agentRoot = path.join(agentsRoot, normalizedAgentName)
|
|
502
|
+
|
|
503
|
+
if (fs.existsSync(agentRoot)) {
|
|
504
|
+
throw new Error(`Agent folder already exists: ${agentRoot}`)
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const systemDir = path.join(agentRoot, 'system')
|
|
508
|
+
const skillsDir = path.join(agentRoot, 'skills')
|
|
509
|
+
|
|
510
|
+
fs.mkdirSync(systemDir, { recursive: true })
|
|
511
|
+
fs.mkdirSync(skillsDir, { recursive: true })
|
|
512
|
+
|
|
513
|
+
const createdPaths: string[] = []
|
|
514
|
+
const writeFile = (relativePath: string, content: string) => {
|
|
515
|
+
const absolutePath = path.join(agentRoot, relativePath)
|
|
516
|
+
fs.mkdirSync(path.dirname(absolutePath), { recursive: true })
|
|
517
|
+
fs.writeFileSync(absolutePath, content, 'utf8')
|
|
518
|
+
createdPaths.push(absolutePath)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const bootFileName = `boot.${AGENT_INITIAL_VERSION}.md`
|
|
522
|
+
const workflowFileName = `workflow.${AGENT_INITIAL_VERSION}.md`
|
|
523
|
+
const toolsFileName = `tools.${AGENT_INITIAL_VERSION}.json`
|
|
524
|
+
const modelFileName = `model.${AGENT_INITIAL_VERSION}.json`
|
|
525
|
+
const skillFileName = `${DEFAULT_SKILL_NAME}.${AGENT_INITIAL_VERSION}.md`
|
|
526
|
+
const activeSkillFileName = `${DEFAULT_SKILL_NAME}.active.md`
|
|
527
|
+
|
|
528
|
+
writeFile(path.join('system', bootFileName), buildBootDocument(normalizedAgentName))
|
|
529
|
+
writeFile(path.join('system', workflowFileName), buildWorkflowDocument(normalizedAgentName))
|
|
530
|
+
writeFile(path.join('system', toolsFileName), buildToolsConfig())
|
|
531
|
+
writeFile(path.join('system', modelFileName), buildModelConfig())
|
|
532
|
+
writeFile(path.join('system', 'prompt.ts'), SYSTEM_PROMPT_TS_TEMPLATE)
|
|
533
|
+
|
|
534
|
+
writeFile(path.join('skills', skillFileName), buildDefaultSkillDocument())
|
|
535
|
+
writeFile(path.join('skills', 'enabled-skills.md'), `${activeSkillFileName}\n`)
|
|
536
|
+
writeFile(path.join('skills', 'skills.ts'), SKILLS_TS_TEMPLATE)
|
|
537
|
+
|
|
538
|
+
writeFile('load.ts', LOAD_TS_TEMPLATE)
|
|
539
|
+
|
|
540
|
+
const createActiveLink = (versionedFile: string, activeFile: string) => {
|
|
541
|
+
const source = path.join(agentRoot, versionedFile)
|
|
542
|
+
const target = path.join(agentRoot, activeFile)
|
|
543
|
+
setActiveLink(source, target)
|
|
544
|
+
createdPaths.push(target)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
createActiveLink(path.join('system', bootFileName), path.join('system', 'boot.active.md'))
|
|
548
|
+
createActiveLink(path.join('system', workflowFileName), path.join('system', 'workflow.active.md'))
|
|
549
|
+
createActiveLink(path.join('system', toolsFileName), path.join('system', 'tools.active.json'))
|
|
550
|
+
createActiveLink(path.join('system', modelFileName), path.join('system', 'model.active.json'))
|
|
551
|
+
createActiveLink(path.join('skills', skillFileName), path.join('skills', activeSkillFileName))
|
|
552
|
+
|
|
553
|
+
return {
|
|
554
|
+
agentName: normalizedAgentName,
|
|
555
|
+
agentRoot,
|
|
556
|
+
createdPaths: createdPaths.sort((a, b) => a.localeCompare(b)),
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
288
560
|
export function setActive(
|
|
289
561
|
agentName: string,
|
|
290
562
|
target: string,
|
|
@@ -362,6 +634,135 @@ export async function loadAgent(agentName: string, processRoot: string = process
|
|
|
362
634
|
}
|
|
363
635
|
}
|
|
364
636
|
|
|
637
|
+
type SpawnCodexResult = {
|
|
638
|
+
status: number | null
|
|
639
|
+
signal: NodeJS.Signals | null
|
|
640
|
+
error?: Error
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
type SpawnCodexFn = (args: string[]) => SpawnCodexResult
|
|
644
|
+
|
|
645
|
+
function getCodexCommand(): string {
|
|
646
|
+
const override = process.env.EXAMPLE_CODEX_BIN?.trim()
|
|
647
|
+
if (override) {
|
|
648
|
+
return override
|
|
649
|
+
}
|
|
650
|
+
if (process.platform === 'win32') {
|
|
651
|
+
// Prefer npm/pnpm cmd shim over stale codex.exe binaries.
|
|
652
|
+
return 'codex.cmd'
|
|
653
|
+
}
|
|
654
|
+
return 'codex'
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const defaultSpawnCodex: SpawnCodexFn = (args) => {
|
|
658
|
+
const spawnOptions = {
|
|
659
|
+
stdio: 'inherit' as const,
|
|
660
|
+
env: process.env,
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const primaryCommand = getCodexCommand()
|
|
664
|
+
const primary = spawnSync(primaryCommand, args, spawnOptions)
|
|
665
|
+
if (primary.error) {
|
|
666
|
+
const err = primary.error as NodeJS.ErrnoException
|
|
667
|
+
if (
|
|
668
|
+
process.platform === 'win32'
|
|
669
|
+
&& !process.env.EXAMPLE_CODEX_BIN
|
|
670
|
+
&& primaryCommand === 'codex.cmd'
|
|
671
|
+
&& err.code === 'ENOENT'
|
|
672
|
+
) {
|
|
673
|
+
return spawnSync('codex', args, spawnOptions)
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
return primary
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function toExitCode(signal: NodeJS.Signals | null): number {
|
|
681
|
+
if (!signal) {
|
|
682
|
+
return 1
|
|
683
|
+
}
|
|
684
|
+
if (signal === 'SIGINT') {
|
|
685
|
+
return 130
|
|
686
|
+
}
|
|
687
|
+
if (signal === 'SIGTERM') {
|
|
688
|
+
return 143
|
|
689
|
+
}
|
|
690
|
+
return 1
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
694
|
+
return typeof value === 'object' && value !== null
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
async function resolvePromptValue(value: unknown): Promise<unknown> {
|
|
698
|
+
if (typeof value === 'function') {
|
|
699
|
+
return await value()
|
|
700
|
+
}
|
|
701
|
+
return value
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function extractPromptString(value: unknown): string | null {
|
|
705
|
+
if (typeof value === 'string') {
|
|
706
|
+
return value
|
|
707
|
+
}
|
|
708
|
+
if (isRecord(value) && typeof value.prompt === 'string') {
|
|
709
|
+
return value.prompt
|
|
710
|
+
}
|
|
711
|
+
return null
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
export async function loadAgentPrompt(agentName: string, processRoot: string = process.cwd()): Promise<string> {
|
|
715
|
+
const agentsRoot = resolveAgentsRoot(processRoot)
|
|
716
|
+
const agentDir = path.join(agentsRoot, agentName)
|
|
717
|
+
|
|
718
|
+
if (!existsDir(agentDir)) {
|
|
719
|
+
throw new Error(`Agent folder not found: ${agentDir}`)
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const promptFile = path.join(agentDir, 'system', 'prompt.ts')
|
|
723
|
+
if (!existsFile(promptFile)) {
|
|
724
|
+
throw new Error(`Prompt file not found for agent '${agentName}': ${promptFile}`)
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const promptModuleUrl = pathToFileURL(promptFile).href
|
|
728
|
+
const promptModule = await import(promptModuleUrl)
|
|
729
|
+
const candidates = [
|
|
730
|
+
await resolvePromptValue(promptModule.prompt),
|
|
731
|
+
await resolvePromptValue(promptModule.agentConfig),
|
|
732
|
+
await resolvePromptValue(promptModule.default),
|
|
733
|
+
]
|
|
734
|
+
|
|
735
|
+
for (const candidate of candidates) {
|
|
736
|
+
const promptText = extractPromptString(candidate)
|
|
737
|
+
if (promptText !== null) {
|
|
738
|
+
return promptText
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
throw new Error(`Prompt module for agent '${agentName}' must export a prompt string.`)
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
export async function runAgent(
|
|
746
|
+
agentName: string,
|
|
747
|
+
codexArgs: string[] = [],
|
|
748
|
+
processRoot: string = process.cwd(),
|
|
749
|
+
options: { spawnCodex?: SpawnCodexFn } = {}
|
|
750
|
+
): Promise<AgentRunResult> {
|
|
751
|
+
const prompt = await loadAgentPrompt(agentName, processRoot)
|
|
752
|
+
const spawnCodex = options.spawnCodex ?? defaultSpawnCodex
|
|
753
|
+
const args = ['--config', `developer_instructions=${prompt}`, ...codexArgs]
|
|
754
|
+
const result = spawnCodex(args)
|
|
755
|
+
|
|
756
|
+
if (result.error) {
|
|
757
|
+
throw new Error(`Failed to start codex: ${result.error.message}`)
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return {
|
|
761
|
+
agentName,
|
|
762
|
+
exitCode: typeof result.status === 'number' ? result.status : toExitCode(result.signal),
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
365
766
|
function validateActiveConfigInputs(agentDir: string): void {
|
|
366
767
|
const issues: string[] = []
|
|
367
768
|
|
|
@@ -432,6 +833,7 @@ export async function main(argv: string[], processRoot: string = process.cwd()):
|
|
|
432
833
|
|
|
433
834
|
const [scope, maybeAgentOrFlag, maybeTarget, ...rest] = argv
|
|
434
835
|
const listMode = scope === 'agents' && maybeAgentOrFlag === '--list'
|
|
836
|
+
const createMode = scope === 'agents' && maybeAgentOrFlag === 'create'
|
|
435
837
|
|
|
436
838
|
if (scope !== 'agents') {
|
|
437
839
|
throw new Error('Expected command `agents` as first positional argument.')
|
|
@@ -445,6 +847,21 @@ export async function main(argv: string[], processRoot: string = process.cwd()):
|
|
|
445
847
|
return listAgents(processRoot).join('\n')
|
|
446
848
|
}
|
|
447
849
|
|
|
850
|
+
if (createMode) {
|
|
851
|
+
if (!maybeTarget) {
|
|
852
|
+
throw new Error('Missing required argument: <agent-name>.')
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const unknownFlags = rest.filter(Boolean)
|
|
856
|
+
if (unknownFlags.length > 0) {
|
|
857
|
+
throw new Error(`Unknown flags for create mode: ${unknownFlags.join(', ')}`)
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
const result = createAgent(maybeTarget, processRoot)
|
|
861
|
+
const displayPath = path.relative(processRoot, result.agentRoot) || result.agentRoot
|
|
862
|
+
return `[${CLI_NAME}] created agent: ${result.agentName} (${displayPath})`
|
|
863
|
+
}
|
|
864
|
+
|
|
448
865
|
const agentName = maybeAgentOrFlag
|
|
449
866
|
const target = maybeTarget
|
|
450
867
|
const setActive = rest.includes('--set-active')
|
|
@@ -458,6 +875,14 @@ export async function main(argv: string[], processRoot: string = process.cwd()):
|
|
|
458
875
|
return JSON.stringify(result.loaded, null, 2)
|
|
459
876
|
}
|
|
460
877
|
|
|
878
|
+
if (target === 'run') {
|
|
879
|
+
const result = await runAgent(agentName, rest, processRoot)
|
|
880
|
+
if (result.exitCode !== 0) {
|
|
881
|
+
process.exitCode = result.exitCode
|
|
882
|
+
}
|
|
883
|
+
return ''
|
|
884
|
+
}
|
|
885
|
+
|
|
461
886
|
if (!agentName || !target) {
|
|
462
887
|
throw new Error('Missing required arguments: <agent-name> and <file-path>.')
|
|
463
888
|
}
|
package/git.ts
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
export type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
headers: Record<string, string>
|
|
7
|
-
query: string[]
|
|
8
|
-
body?: unknown
|
|
9
|
-
}
|
|
10
|
-
response: {
|
|
11
|
-
headers: Record<string, string>
|
|
12
|
-
}
|
|
13
|
-
status: number
|
|
14
|
-
ok: boolean
|
|
15
|
-
body: T
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type GitServiceApiMethod = (...args: unknown[]) => Promise<GitServiceApiExecutionResult>
|
|
19
|
-
|
|
20
|
-
export type GitServiceApi = {
|
|
21
|
-
[key: string]: GitServiceApi | GitServiceApiMethod
|
|
22
|
-
}
|
|
1
|
+
export type {
|
|
2
|
+
GitServiceApi,
|
|
3
|
+
GitServiceApiExecutionResult,
|
|
4
|
+
GitServiceApiMethod,
|
|
5
|
+
} from '@foundation0/git'
|
|
23
6
|
|
|
24
7
|
export {
|
|
25
8
|
buildGitApiMockResponse,
|
|
@@ -28,4 +11,4 @@ export {
|
|
|
28
11
|
extractDependencyIssueNumbers,
|
|
29
12
|
resolveProjectRepoIdentity,
|
|
30
13
|
syncIssueDependencies,
|
|
31
|
-
} from '
|
|
14
|
+
} from '@foundation0/git'
|
package/mcp/cli.mjs
CHANGED
package/mcp/cli.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const getArgValue = (name: string, fallback?: string): string | undefined => {
|
|
4
|
-
const exactArg = process.argv.find((arg) => arg.startsWith(`${name}=`))
|
|
5
|
-
if (exactArg) {
|
|
6
|
-
const [, value] = exactArg.split('=', 2)
|
|
7
|
-
return value
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const index = process.argv.indexOf(name)
|
|
11
|
-
if (index >= 0 && index + 1 < process.argv.length) {
|
|
12
|
-
const next = process.argv[index + 1]
|
|
13
|
-
if (!next.startsWith('--')) {
|
|
14
|
-
return next
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return fallback
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const hasFlag = (name: string): boolean => process.argv.includes(name)
|
|
22
|
-
|
|
1
|
+
import { runExampleMcpServer } from './server'
|
|
2
|
+
|
|
3
|
+
const getArgValue = (name: string, fallback?: string): string | undefined => {
|
|
4
|
+
const exactArg = process.argv.find((arg) => arg.startsWith(`${name}=`))
|
|
5
|
+
if (exactArg) {
|
|
6
|
+
const [, value] = exactArg.split('=', 2)
|
|
7
|
+
return value
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const index = process.argv.indexOf(name)
|
|
11
|
+
if (index >= 0 && index + 1 < process.argv.length) {
|
|
12
|
+
const next = process.argv[index + 1]
|
|
13
|
+
if (!next.startsWith('--')) {
|
|
14
|
+
return next
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return fallback
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const hasFlag = (name: string): boolean => process.argv.includes(name)
|
|
22
|
+
|
|
23
23
|
const serverName = getArgValue('--server-name', 'f0-mcp')
|
|
24
|
-
const serverVersion = getArgValue('--server-version', '1.0.0')
|
|
25
|
-
const toolsPrefix = getArgValue('--tools-prefix') ?? process.env.MCP_TOOLS_PREFIX
|
|
26
|
-
|
|
24
|
+
const serverVersion = getArgValue('--server-version', '1.0.0')
|
|
25
|
+
const toolsPrefix = getArgValue('--tools-prefix') ?? process.env.MCP_TOOLS_PREFIX
|
|
26
|
+
|
|
27
27
|
if (hasFlag('--help') || hasFlag('-h')) {
|
|
28
28
|
console.log('Usage: f0-mcp [--tools-prefix=api]')
|
|
29
|
-
console.log('Optional flags:')
|
|
30
|
-
console.log(' --server-name <name>')
|
|
31
|
-
console.log(' --server-version <version>')
|
|
32
|
-
console.log(' --tools-prefix <prefix>')
|
|
33
|
-
process.exit(0)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
void
|
|
37
|
-
serverName: serverName ?? undefined,
|
|
38
|
-
serverVersion: serverVersion ?? undefined,
|
|
39
|
-
toolsPrefix,
|
|
40
|
-
}).catch((error) => {
|
|
41
|
-
console.error('Failed to start
|
|
42
|
-
process.exit(1)
|
|
43
|
-
})
|
|
29
|
+
console.log('Optional flags:')
|
|
30
|
+
console.log(' --server-name <name>')
|
|
31
|
+
console.log(' --server-version <version>')
|
|
32
|
+
console.log(' --tools-prefix <prefix>')
|
|
33
|
+
process.exit(0)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void runExampleMcpServer({
|
|
37
|
+
serverName: serverName ?? undefined,
|
|
38
|
+
serverVersion: serverVersion ?? undefined,
|
|
39
|
+
toolsPrefix,
|
|
40
|
+
}).catch((error) => {
|
|
41
|
+
console.error('Failed to start example-org MCP server', error)
|
|
42
|
+
process.exit(1)
|
|
43
|
+
})
|
package/mcp/client.ts
CHANGED
|
@@ -40,30 +40,30 @@ const tryParseResult = (text: string): { parsed?: unknown; text: string } => {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export interface
|
|
43
|
+
export interface ExampleMcpClientOptions {
|
|
44
44
|
name?: string
|
|
45
45
|
version?: string
|
|
46
46
|
requestTimeoutMs?: number
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export interface
|
|
49
|
+
export interface ExampleMcpCallArgs {
|
|
50
50
|
args?: unknown[]
|
|
51
51
|
options?: Record<string, unknown>
|
|
52
52
|
[key: string]: unknown
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export type
|
|
55
|
+
export type ExampleMcpCallResponse = {
|
|
56
56
|
isError: boolean
|
|
57
57
|
text: string
|
|
58
58
|
data: unknown
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export class
|
|
61
|
+
export class ExampleMcpClient {
|
|
62
62
|
private readonly client: Client
|
|
63
63
|
private readonly requestTimeoutMs: number
|
|
64
64
|
private transport: StdioClientTransport | null = null
|
|
65
65
|
|
|
66
|
-
public constructor(options:
|
|
66
|
+
public constructor(options: ExampleMcpClientOptions = {}) {
|
|
67
67
|
this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
|
|
68
68
|
this.client = new Client(
|
|
69
69
|
{
|
|
@@ -110,7 +110,7 @@ export class F0McpClient {
|
|
|
110
110
|
return response.tools.map((tool) => tool.name)
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
public async call(toolName: string, args:
|
|
113
|
+
public async call(toolName: string, args: ExampleMcpCallArgs = {}): Promise<ExampleMcpCallResponse> {
|
|
114
114
|
const response = await this.client.request(
|
|
115
115
|
{
|
|
116
116
|
method: 'tools/call',
|
|
@@ -138,12 +138,12 @@ export class F0McpClient {
|
|
|
138
138
|
path: string,
|
|
139
139
|
methodArgs: unknown[] = [],
|
|
140
140
|
methodOptions: Record<string, unknown> = {},
|
|
141
|
-
): Promise<
|
|
141
|
+
): Promise<ExampleMcpCallResponse> {
|
|
142
142
|
const args = { args: methodArgs.map((value) => String(value)), options: methodOptions }
|
|
143
143
|
return this.call(path, args)
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
export const
|
|
148
|
-
return new
|
|
147
|
+
export const createExampleMcpClient = (options: ExampleMcpClientOptions = {}): ExampleMcpClient => {
|
|
148
|
+
return new ExampleMcpClient(options)
|
|
149
149
|
}
|
package/mcp/index.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
createExampleMcpServer,
|
|
3
|
+
runExampleMcpServer,
|
|
4
4
|
normalizeToolCallNameForServer,
|
|
5
|
-
type
|
|
6
|
-
type
|
|
5
|
+
type ExampleMcpServerOptions,
|
|
6
|
+
type ExampleMcpServerInstance,
|
|
7
7
|
} from './server'
|
|
8
8
|
|
|
9
9
|
export {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
type
|
|
13
|
-
type
|
|
14
|
-
type
|
|
10
|
+
ExampleMcpClient,
|
|
11
|
+
createExampleMcpClient,
|
|
12
|
+
type ExampleMcpCallArgs,
|
|
13
|
+
type ExampleMcpCallResponse,
|
|
14
|
+
type ExampleMcpClientOptions,
|
|
15
15
|
} from './client'
|
package/mcp/server.ts
CHANGED
|
@@ -308,20 +308,20 @@ const invokeTool = async (tool: ToolDefinition, payload: unknown): Promise<unkno
|
|
|
308
308
|
return Promise.resolve(tool.method(...invocationArgs))
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
export interface
|
|
311
|
+
export interface ExampleMcpServerOptions {
|
|
312
312
|
serverName?: string
|
|
313
313
|
serverVersion?: string
|
|
314
314
|
toolsPrefix?: string
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
-
export type
|
|
317
|
+
export type ExampleMcpServerInstance = {
|
|
318
318
|
api: ApiEndpoint
|
|
319
319
|
tools: ToolDefinition[]
|
|
320
320
|
server: Server
|
|
321
321
|
run: () => Promise<Server>
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
-
export const
|
|
324
|
+
export const createExampleMcpServer = (options: ExampleMcpServerOptions = {}): ExampleMcpServerInstance => {
|
|
325
325
|
const api: ApiEndpoint = {
|
|
326
326
|
agents: agentsApi,
|
|
327
327
|
projects: projectsApi,
|
|
@@ -336,7 +336,7 @@ export const createF0McpServer = (options: F0McpServerOptions = {}): F0McpServer
|
|
|
336
336
|
|
|
337
337
|
const server = new Server(
|
|
338
338
|
{
|
|
339
|
-
name: options.serverName ?? '
|
|
339
|
+
name: options.serverName ?? 'example-api',
|
|
340
340
|
version: options.serverVersion ?? '1.0.0',
|
|
341
341
|
},
|
|
342
342
|
{
|
|
@@ -452,8 +452,8 @@ export const createF0McpServer = (options: F0McpServerOptions = {}): F0McpServer
|
|
|
452
452
|
return { api, tools, server, run }
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
-
export const
|
|
456
|
-
const instance =
|
|
455
|
+
export const runExampleMcpServer = async (options: ExampleMcpServerOptions = {}): Promise<Server> => {
|
|
456
|
+
const instance = createExampleMcpServer(options)
|
|
457
457
|
return instance.run()
|
|
458
458
|
}
|
|
459
459
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foundation0/api",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Foundation 0 API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,15 +11,13 @@
|
|
|
11
11
|
"main": "agents.ts",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"foundation0",
|
|
14
|
-
"f0",
|
|
15
14
|
"api"
|
|
16
15
|
],
|
|
17
|
-
"author": "",
|
|
16
|
+
"author": "Foundation 0",
|
|
18
17
|
"license": "ISC",
|
|
19
18
|
"files": [
|
|
20
19
|
"agents.ts",
|
|
21
20
|
"git.ts",
|
|
22
|
-
"dist/git.js",
|
|
23
21
|
"taskgraph-parser.ts",
|
|
24
22
|
"projects.ts",
|
|
25
23
|
"mcp"
|
|
@@ -29,13 +27,13 @@
|
|
|
29
27
|
"registry": "https://registry.npmjs.org/"
|
|
30
28
|
},
|
|
31
29
|
"dependencies": {
|
|
30
|
+
"@foundation0/git": "^1.0.0",
|
|
32
31
|
"@modelcontextprotocol/sdk": "^1.13.0"
|
|
33
32
|
},
|
|
34
33
|
"scripts": {
|
|
35
|
-
"build:git": "bun build ../git/packages/git/src/index.ts --target bun --format esm --minify --outfile ./dist/git.js",
|
|
36
34
|
"mcp": "bun run mcp/cli.ts",
|
|
37
35
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
38
|
-
"deploy": "pnpm
|
|
36
|
+
"deploy": "pnpm publish --access public",
|
|
39
37
|
"version:patch": "pnpm version patch",
|
|
40
38
|
"version:minor": "pnpm version minor",
|
|
41
39
|
"version:major": "pnpm version major"
|
package/projects.ts
CHANGED
|
@@ -160,7 +160,7 @@ export type ProjectWriteGitTaskResult = {
|
|
|
160
160
|
issue: ProjectGitTaskRecord
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
const CLI_NAME = '
|
|
163
|
+
const CLI_NAME = 'example'
|
|
164
164
|
const VERSION_RE = 'v?\\d+(?:\\.\\d+){2,}'
|
|
165
165
|
const VERSION_RE_CORE = `(?:${VERSION_RE})`
|
|
166
166
|
const ACTIVE_EXT_PRIORITY = ['.md', '.json', '.yaml', '.yml', '.ts', '.js', '.txt']
|
|
@@ -171,9 +171,9 @@ const VERSIONED_DOC_RE = new RegExp(`^(.+)\\.(${VERSION_RE_CORE})\\.([^.]+)$`)
|
|
|
171
171
|
const TASK_HASH_LENGTH = 8
|
|
172
172
|
const ISSUE_LIST_PAGE_SIZE = 100
|
|
173
173
|
const resolveGiteaHost = (): string => {
|
|
174
|
-
const host = process.env.GITEA_HOST ?? process.env.
|
|
174
|
+
const host = process.env.GITEA_HOST ?? process.env.EXAMPLE_GITEA_HOST
|
|
175
175
|
if (!host) {
|
|
176
|
-
throw new Error('No Gitea host configured. Set GITEA_HOST or
|
|
176
|
+
throw new Error('No Gitea host configured. Set GITEA_HOST or EXAMPLE_GITEA_HOST.')
|
|
177
177
|
}
|
|
178
178
|
return host
|
|
179
179
|
}
|
|
@@ -1856,13 +1856,13 @@ export async function syncTasks(
|
|
|
1856
1856
|
}
|
|
1857
1857
|
const log = syncOptions.verbose
|
|
1858
1858
|
? (message: string) => {
|
|
1859
|
-
process.stderr.write(`[
|
|
1859
|
+
process.stderr.write(`[example projects ${projectName}] ${message}\n`)
|
|
1860
1860
|
}
|
|
1861
1861
|
: null
|
|
1862
1862
|
|
|
1863
|
-
const previousTimeoutEnv = process.env.
|
|
1863
|
+
const previousTimeoutEnv = process.env.EXAMPLE_GIT_REQUEST_TIMEOUT_MS
|
|
1864
1864
|
if (syncOptions.requestTimeoutMs) {
|
|
1865
|
-
process.env.
|
|
1865
|
+
process.env.EXAMPLE_GIT_REQUEST_TIMEOUT_MS = String(syncOptions.requestTimeoutMs)
|
|
1866
1866
|
}
|
|
1867
1867
|
|
|
1868
1868
|
log?.(`Resolved project root: ${projectRoot}`)
|
|
@@ -2020,9 +2020,9 @@ export async function syncTasks(
|
|
|
2020
2020
|
|
|
2021
2021
|
if (syncOptions.skipDependencies) {
|
|
2022
2022
|
if (previousTimeoutEnv === undefined) {
|
|
2023
|
-
delete process.env.
|
|
2023
|
+
delete process.env.EXAMPLE_GIT_REQUEST_TIMEOUT_MS
|
|
2024
2024
|
} else {
|
|
2025
|
-
process.env.
|
|
2025
|
+
process.env.EXAMPLE_GIT_REQUEST_TIMEOUT_MS = previousTimeoutEnv
|
|
2026
2026
|
}
|
|
2027
2027
|
|
|
2028
2028
|
return {
|
|
@@ -2081,9 +2081,9 @@ export async function syncTasks(
|
|
|
2081
2081
|
}
|
|
2082
2082
|
|
|
2083
2083
|
if (previousTimeoutEnv === undefined) {
|
|
2084
|
-
delete process.env.
|
|
2084
|
+
delete process.env.EXAMPLE_GIT_REQUEST_TIMEOUT_MS
|
|
2085
2085
|
} else {
|
|
2086
|
-
process.env.
|
|
2086
|
+
process.env.EXAMPLE_GIT_REQUEST_TIMEOUT_MS = previousTimeoutEnv
|
|
2087
2087
|
}
|
|
2088
2088
|
|
|
2089
2089
|
return {
|
|
@@ -2127,7 +2127,7 @@ export async function clearIssues(
|
|
|
2127
2127
|
|
|
2128
2128
|
const log = clearOptions.verbose
|
|
2129
2129
|
? (message: string) => {
|
|
2130
|
-
process.stderr.write(`[
|
|
2130
|
+
process.stderr.write(`[example projects ${projectName}] ${message}\n`)
|
|
2131
2131
|
}
|
|
2132
2132
|
: null
|
|
2133
2133
|
|
package/dist/git.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
var q="2022-11-28";function x(e){let a=e.method??"GET",t=e.path,r=e.query??[],s=e.headers??[],l=e.apiBase??"https://api.github.com",o=e.apiVersion??"2022-11-28",u=[a,...t,...r,...s];return{endpoint:t.length>0?`${l}/${t.join("/")}`:l,method:a,path:[...t],query:[...r],headers:[...s],requestParts:u,apiVersion:o}}class L{apiBase;apiVersion;defaultMethod;constructor(e={}){this.apiBase=e.apiBase??"https://api.github.com",this.apiVersion=e.apiVersion??q,this.defaultMethod=e.defaultMethod??"GET"}buildInvocation(e){return{path:e.path,method:e.method??this.defaultMethod,query:e.query,headers:e.headers,apiBase:this.apiBase,apiVersion:this.apiVersion}}request(e){return x(this.buildInvocation(e))}requestAsync(e){return Promise.resolve(this.request(e))}get metadata(){return{apiBase:this.apiBase,apiVersion:this.apiVersion,defaultMethod:this.defaultMethod}}}function ne(e={}){return new L(e)}import{existsSync as le,readFileSync as ue}from"fs";import{dirname as oe,join as M}from"path";var ie="https://gitea.machian.com",me="GITEA",pe="/swagger.v1.json",ke=(e)=>{let a=e.trim();if(!a||a.startsWith("#"))return null;let t=a.indexOf("=");if(t<0)return null;let r=a.slice(0,t).trim(),s=a.slice(t+1).trim();if(!r)return null;if(s.length>=2&&s.startsWith('"')&&s.endsWith('"'))return[r,s.slice(1,-1)];if(s.length>=2&&s.startsWith("'")&&s.endsWith("'"))return[r,s.slice(1,-1)];return[r,s]},ce=(e)=>{if(!le(e))return{};let a={},t=ue(e,"utf8");for(let r of t.split(/\r?\n/)){let s=ke(r);if(!s)continue;let[l,o]=s;a[l]=o}return a},fe=()=>{let e=[M(process.cwd(),".env"),M(oe(process.cwd()),".env")];for(let a of e){let t=ce(a);if(Object.keys(t).length>0)return t}return{}},Ve=(e)=>{let a=(e??"").toUpperCase();if(a==="GITEA")return"GITEA";if(a==="GITHUB")return"GITHUB";return me},F=(e={})=>{let a=fe(),t=Ve(e.platform??process.env.PLATFORM??process.env.GIT_PLATFORM??a.PLATFORM??a.GIT_PLATFORM),r=e.giteaHost??process.env.GITEA_HOST??a.GITEA_HOST??ie,s=e.giteaToken??process.env.GITEA_TOKEN??a.GITEA_TOKEN,l=e.giteaApiVersion??process.env.GITEA_API_VERSION??a.GITEA_API_VERSION,o=e.giteaSwaggerPath??process.env.GITEA_SWAGGER_PATH??a.GITEA_SWAGGER_PATH??pe;return{platform:t,giteaHost:r,giteaToken:s,giteaApiVersion:l,giteaSwaggerPath:o}};var n=(e,a,t,r)=>({featurePath:e,method:a,swaggerPath:t,notes:r}),ge=[n(["issue","close"],"PATCH","/repos/{owner}/{repo}/issues/{number}"),n(["issue","comment"],"POST","/repos/{owner}/{repo}/issues/{number}/comments"),n(["issue","create"],"POST","/repos/{owner}/{repo}/issues"),n(["issue","delete"],"DELETE","/repos/{owner}/{repo}/issues/{number}"),n(["issue","edit"],"PATCH","/repos/{owner}/{repo}/issues/{number}"),n(["issue","list"],"GET","/repos/{owner}/{repo}/issues"),n(["issue","lock"],"PUT","/repos/{owner}/{repo}/issues/{number}/lock"),n(["issue","pin"],"POST","/repos/{owner}/{repo}/issues/{number}/pin"),n(["issue","reopen"],"PATCH","/repos/{owner}/{repo}/issues/{number}"),n(["issue","view"],"GET","/repos/{owner}/{repo}/issues/{number}"),n(["pr","comment"],"POST","/repos/{owner}/{repo}/issues/{number}/comments"),n(["pr","create"],"POST","/repos/{owner}/{repo}/pulls"),n(["pr","diff"],"GET","/repos/{owner}/{repo}/pulls/{number}.{diffType}"),n(["pr","edit"],"PATCH","/repos/{owner}/{repo}/pulls/{number}"),n(["pr","list"],"GET","/repos/{owner}/{repo}/pulls"),n(["pr","close"],"PATCH","/repos/{owner}/{repo}/pulls/{number}"),n(["pr","lock"],"PUT","/repos/{owner}/{repo}/issues/{number}/lock"),n(["pr","merge"],"POST","/repos/{owner}/{repo}/pulls/{number}/merge"),n(["pr","reopen"],"PATCH","/repos/{owner}/{repo}/pulls/{number}"),n(["pr","view"],"GET","/repos/{owner}/{repo}/pulls/{number}"),n(["repo","archive"],"GET","/repos/{owner}/{repo}/archive/{archive}"),n(["repo","create"],"POST","/user/repos"),n(["repo","delete"],"DELETE","/repos/{owner}/{repo}"),n(["repo","deploy-key"],"GET","/repos/{owner}/{repo}/keys"),n(["repo","edit"],"PATCH","/repos/{owner}/{repo}"),n(["repo","fork"],"POST","/repos/{owner}/{repo}/forks"),n(["repo","list"],"GET","/user/repos"),n(["repo","sync"],"POST","/repos/{owner}/{repo}/mirror-sync"),n(["repo","view"],"GET","/repos/{owner}/{repo}"),n(["release","create"],"POST","/repos/{owner}/{repo}/releases"),n(["release","delete"],"DELETE","/repos/{owner}/{repo}/releases/{id}"),n(["release","delete-asset"],"DELETE","/repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"),n(["release","download"],"GET","/repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"),n(["release","edit"],"PATCH","/repos/{owner}/{repo}/releases/{id}"),n(["release","list"],"GET","/repos/{owner}/{repo}/releases"),n(["release","upload"],"POST","/repos/{owner}/{repo}/releases/{id}/assets"),n(["release","verify"],"GET","/repos/{owner}/{repo}/releases/{id}"),n(["release","verify-asset"],"GET","/repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"),n(["release","view"],"GET","/repos/{owner}/{repo}/releases/{id}"),n(["contents","create"],"POST","/repos/{owner}/{repo}/contents/{filepath}"),n(["contents","delete"],"DELETE","/repos/{owner}/{repo}/contents/{filepath}"),n(["contents","list"],"GET","/repos/{owner}/{repo}/contents/{filepath}"),n(["contents","update"],"PUT","/repos/{owner}/{repo}/contents/{filepath}"),n(["contents","view"],"GET","/repos/{owner}/{repo}/contents/{filepath}"),n(["search","code"],"GET","/repos/search"),n(["search","commits"],"GET","/repos/search"),n(["search","issues"],"GET","/repos/issues/search"),n(["search","prs"],"GET","/repos/issues/search"),n(["search","repos"],"GET","/repos/search"),n(["workflow","disable"],"PUT","/repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable"),n(["workflow","enable"],"PUT","/repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable"),n(["workflow","list"],"GET","/repos/{owner}/{repo}/actions/workflows"),n(["workflow","run"],"POST","/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches"),n(["workflow","view"],"GET","/repos/{owner}/{repo}/actions/workflows/{workflow_id}"),n(["secret","delete"],"DELETE","/repos/{owner}/{repo}/actions/secrets/{secretname}"),n(["secret","list"],"GET","/repos/{owner}/{repo}/actions/secrets"),n(["secret","set"],"PUT","/repos/{owner}/{repo}/actions/secrets/{secretname}"),n(["variable","delete"],"DELETE","/repos/{owner}/{repo}/actions/variables/{variablename}"),n(["variable","get"],"GET","/repos/{owner}/{repo}/actions/variables/{variablename}"),n(["variable","list"],"GET","/repos/{owner}/{repo}/actions/variables"),n(["variable","set"],"POST","/repos/{owner}/{repo}/actions/variables/{variablename}"),n(["gpg-key","add"],"POST","/user/gpg_keys"),n(["gpg-key","delete"],"DELETE","/user/gpg_keys/{id}"),n(["gpg-key","list"],"GET","/user/gpg_keys"),n(["ssh-key","add"],"POST","/user/keys"),n(["ssh-key","delete"],"DELETE","/user/keys/{id}"),n(["ssh-key","list"],"GET","/user/keys"),n(["label","clone"],"POST","/repos/{owner}/{repo}/labels"),n(["label","create"],"POST","/repos/{owner}/{repo}/labels"),n(["label","delete"],"DELETE","/repos/{owner}/{repo}/labels/{id}"),n(["label","edit"],"PATCH","/repos/{owner}/{repo}/labels/{id}"),n(["label","list"],"GET","/repos/{owner}/{repo}/labels")],he=new Map([["issue",n(["issue"],"GET","/repos/{owner}/{repo}/issues","fallback to issue list")],["pr",n(["pr"],"GET","/repos/{owner}/{repo}/pulls","fallback to pull request list")],["repo",n(["repo"],"GET","/repos/{owner}/{repo}","fallback to repository read")],["release",n(["release"],"GET","/repos/{owner}/{repo}/releases","fallback to release list")],["run",n(["run"],"GET","/repos/{owner}/{repo}/actions/tasks","fallback to workflow task list")],["workflow",n(["workflow"],"GET","/repos/{owner}/{repo}/actions/workflows","fallback to workflow list")],["search",n(["search"],"GET","/repos/search","fallback to global repo search")],["secret",n(["secret"],"GET","/repos/{owner}/{repo}/actions/secrets","fallback to repository secret list")],["variable",n(["variable"],"GET","/repos/{owner}/{repo}/actions/variables","fallback to repository variable list")],["label",n(["label"],"GET","/repos/{owner}/{repo}/labels","fallback to repository label list")],["org",n(["org"],"GET","/orgs","fallback to list organizations")]]),U=(e)=>ge.find((a)=>a.featurePath.length===e.length&&a.featurePath.every((t,r)=>t===e[r])),W=(e)=>he.get(e[0]);var de=new Set(["GET","POST","PUT","PATCH","DELETE"]),we=new Set(["view","get","list","status","exists","search","stats","verify","check"]),be=new Set(["delete","remove","unarchive","unstar","unwatch","unpin","unlink","unsubscribe","unfollow","deprovision","expire"]),ye=new Set(["edit","update","close","open","pin","reopen","rename","set","transfer","enable","disable","lock","unlock","set-default","follow","watch","subscribe","archive","merge","approve"]),Ge=new Set(["create","add","run","dispatch","comment","fork","sync","set-upstream","upload","install","request","approve","create-team","apply","start","stop","rerun","reset"]),Q=(e)=>{if(!e||typeof e!=="string")return;let a=e.trim().toUpperCase();return de.has(a)?a:void 0},ve=(e)=>{if(e.length===0)return"GET";let a=e[e.length-1].toLowerCase();if(we.has(a))return"GET";if(be.has(a))return"DELETE";if(ye.has(a))return"PATCH";if(Ge.has(a))return"POST";if(e.length===1)return"GET";return"POST"};class O{apiBase;apiVersion;token;swaggerUrl;swaggerSpec;constructor(e){this.apiBase=this.buildApiBase(e.giteaHost),this.apiVersion=e.apiVersion,this.token=e.giteaToken,this.swaggerUrl=this.buildSwaggerUrl(e.giteaHost,e.giteaSwaggerPath),this.swaggerSpec=e.swaggerSpec}get platform(){return"GITEA"}async mapFeature(e){let a=e.args??[],t=e.flagValues??{},r=U(e.feature.path)??W(e.feature.path);if(!r)return this.mapFallback(e.feature.path,a,this.mapFlags(t,e.feature.path),e.method);return this.mapRule(r,a,t,e.method)}async mapFeatureResponse(e){let a=await this.mapFeature(e);return x({path:a.mappedPath,method:a.method,query:a.query,headers:a.headers,apiBase:a.apiBase,apiVersion:a.apiVersion})}async validateFeature(e){let a=await this.mapFeature(e),t=await this.fetchSwaggerSpec(),r=`/${a.mappedPath.join("/")}`,s=t.paths?.[r];if(!s)return{...a,mapped:!1,reason:`Swagger endpoint not found: ${r}`};let l=Object.prototype.hasOwnProperty.call(s,a.method.toLowerCase()),o=l?void 0:`Swagger method mismatch for ${r}: ${a.method}`;return{...a,mapped:l,reason:o}}async fetchSwaggerSpec(){if(this.swaggerSpec)return this.swaggerSpec;let e=await fetch(this.swaggerUrl,{headers:this.token?{Authorization:`token ${this.token}`}:void 0});if(!e.ok)throw Error(`Could not fetch swagger spec from ${this.swaggerUrl}: ${e.status}`);return await e.json()}mapRule(e,a=[],t={},r){let s=this.mapSwaggerPath(e.swaggerPath,a,this.shouldUseContentsRoot(e,a)),l=this.mapFeatureQuery(e,t),o=this.mapHeaders(),u=Q(r)??e.method;return{platform:this.platform,featurePath:e.featurePath,mappedPath:s,method:u,query:l,headers:o,apiBase:this.apiBase,swaggerPath:e.swaggerPath,mapped:!0,apiVersion:this.apiVersion,reason:e.notes}}mapFallback(e,a,t,r){let{owner:s,repo:l,tail:o}=this.extractOwnerRepoArgs(a),u=this.sanitizePath(["repos",s,l,...e,...o]),i=this.mapHeaders(),m=Q(r)??ve(e);return{platform:this.platform,featurePath:e,mappedPath:u,method:m,query:t,headers:i,apiBase:this.apiBase,swaggerPath:`/${u.join("/")}`,mapped:!1,apiVersion:this.apiVersion,reason:`No direct mapping for feature: ${e.join(" ")}`}}mapFeatureQuery(e,a){let t=[...e.staticQuery??[]];return t.push(...this.mapFlags(a,e.featurePath)),t}mapFlags(e,a){let t=[];if(a[0]==="search"){if(a[1]==="prs")t.push("type=pr");if(a[1]==="issues")t.push("type=issue")}for(let[r,s]of Object.entries(e)){if(s===void 0)continue;let l=this.normalizeFlagKey(r);if(typeof s==="boolean"){t.push(`${l}=${s}`);continue}t.push(`${l}=${s}`)}return t}mapHeaders(){let e=["Accept: application/json"];if(this.token)e.push(`Authorization: token ${this.token}`);return e}shouldUseContentsRoot(e,a){if(e.swaggerPath!=="/repos/{owner}/{repo}/contents/{filepath}")return!1;if(e.featurePath[0]!=="contents"||e.featurePath[1]!=="list")return!1;let[,,t]=a;if(t===void 0||t==="")return!0;return String(t).trim()===""}mapSwaggerPath(e,a=[],t=!1){let r=this.normalizeSwaggerPathArgs(e,a),s=this.sanitizePath(e.split("/")),l=0,o=s.flatMap((u)=>{if(!u.startsWith("{")||!u.endsWith("}"))return[u];let i=r[l];l+=1;let m=/^\\{v\\d+\\}$/.test(i);if(t&&u==="{filepath}"&&(!i||i.trim()===""||m))return[];return[i?i:u]});return this.sanitizePath(o)}normalizeSwaggerPathArgs(e,a){let t=[...a],s=e.split("/").filter((l)=>l.startsWith("{")&&l.endsWith("}")).length;if(s<=1)return t;if(!t[0])return t;if(t[0].includes("/")&&s>=2){let l=t[0].split("/");if(l.length>=2&&l[0]&&l[1])t[0]=l[0],t.splice(1,0,l[1])}if(s>=2&&t.length>=2)return t;while(t.length<s)t.push(`{v${t.length}}`);return t}extractOwnerRepoArgs(e){if(!e.length)return{owner:"{owner}",repo:"{repo}",tail:[]};if(e.length>=2)return{owner:e[0],repo:e[1],tail:e.slice(2)};let t=e[0].split("/");if(t.length===2&&t[0]&&t[1])return{owner:t[0],repo:t[1],tail:[]};return{owner:"{owner}",repo:"{repo}",tail:e}}buildApiBase(e){let a=e.replace(/\/$/,"");if(a.endsWith("/api/v1"))return a;return`${a}/api/v1`}buildSwaggerUrl(e,a="/swagger.v1.json"){let t=this.buildApiBase(e).replace(/\/api\/v1$/,""),r=a.startsWith("/")?a:`/${a}`;return`${t}${r}`}sanitizePath(e){return e.filter((a)=>a.length>0)}normalizeFlagKey(e){return e.replace(/^--/,"").trim()}}var $=(e={})=>{let a=F(e.config);if(a.platform==="GITEA")return new O({giteaHost:a.giteaHost,giteaToken:a.giteaToken,giteaSwaggerPath:a.giteaSwaggerPath,apiVersion:a.giteaApiVersion,...e.swaggerSpec?{swaggerSpec:e.swaggerSpec}:{}});throw Error(`Unsupported platform: ${a.platform}`)},Ae=async(e,a={})=>{let t=$(a),r=await t.mapFeature(e),s=await t.mapFeatureResponse(e);return{mapping:r,response:s}};var z={features:[{path:["agent-task","create"],args:["<task description>"],flags:[{name:"--base",takesValue:!0},{name:"--custom-agent",takesValue:!0},{name:"--follow",takesValue:!1},{name:"--from-file",takesValue:!0}]},{path:["agent-task","list"],args:[],flags:[{name:"--limit",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["agent-task","view"],args:["<session-id> | <pr-number> | <pr-url> | <pr-branch>"],flags:[{name:"--follow",takesValue:!1},{name:"--log",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["alias","delete"],args:[],flags:[{name:"--all",takesValue:!1}]},{path:["alias","import"],args:["<filename> | -"],flags:[{name:"--clobber",takesValue:!1}]},{path:["alias","list"],args:[],flags:[]},{path:["alias","set"],args:["<alias>","<expansion>"],flags:[{name:"--clobber",takesValue:!1},{name:"--shell",takesValue:!1},{name:"--cache",takesValue:!0},{name:"--field",takesValue:!0},{name:"--header",takesValue:!0},{name:"--hostname",takesValue:!0},{name:"--include",takesValue:!1},{name:"--input",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--method",takesValue:!0},{name:"--paginate",takesValue:!1},{name:"--preview",takesValue:!0},{name:"--raw-field",takesValue:!0},{name:"--silent",takesValue:!1},{name:"--slurp",takesValue:!1},{name:"--template",takesValue:!0},{name:"--verbose",takesValue:!1}]},{path:["attestation","download"],args:["<file-path> | oci://<image-uri>"],flags:[{name:"--digest-alg",takesValue:!0},{name:"--hostname",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--predicate-type",takesValue:!0},{name:"--repo",takesValue:!0}]},{path:["attestation","trusted-root"],args:[],flags:[{name:"--hostname",takesValue:!0},{name:"--tuf-root",takesValue:!0},{name:"--tuf-url",takesValue:!0},{name:"--verify-only",takesValue:!1}]},{path:["attestation","verify"],args:["<file-path> | oci://<image-uri>"],flags:[{name:"--bundle",takesValue:!0},{name:"--bundle-from-oci",takesValue:!1},{name:"--cert-identity",takesValue:!0},{name:"--cert-identity-regex",takesValue:!0},{name:"--cert-oidc-issuer",takesValue:!0},{name:"--custom-trusted-root",takesValue:!0},{name:"--deny-self-hosted-runners",takesValue:!1},{name:"--digest-alg",takesValue:!0},{name:"--format",takesValue:!0},{name:"--hostname",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--no-public-good",takesValue:!1},{name:"--owner",takesValue:!0},{name:"--predicate-type",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--signer-digest",takesValue:!0},{name:"--signer-repo",takesValue:!0},{name:"--signer-workflow",takesValue:!0},{name:"--source-digest",takesValue:!0},{name:"--source-ref",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["auth","login"],args:[],flags:[{name:"--clipboard",takesValue:!1},{name:"--git-protocol",takesValue:!0},{name:"--hostname",takesValue:!0},{name:"--insecure-storage",takesValue:!1},{name:"--scopes",takesValue:!0},{name:"--skip-ssh-key",takesValue:!1},{name:"--web",takesValue:!1},{name:"--with-token",takesValue:!1}]},{path:["auth","logout"],args:[],flags:[{name:"--hostname",takesValue:!0},{name:"--user",takesValue:!0}]},{path:["auth","refresh"],args:[],flags:[{name:"--clipboard",takesValue:!1},{name:"--hostname",takesValue:!0},{name:"--insecure-storage",takesValue:!1},{name:"--remove-scopes",takesValue:!0},{name:"--reset-scopes",takesValue:!1},{name:"--scopes",takesValue:!0}]},{path:["auth","setup-git"],args:[],flags:[{name:"--force",takesValue:!1},{name:"--hostname",takesValue:!0}]},{path:["auth","status"],args:[],flags:[{name:"--active",takesValue:!1},{name:"--hostname",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--show-token",takesValue:!1},{name:"--template",takesValue:!0}]},{path:["auth","switch"],args:[],flags:[{name:"--hostname",takesValue:!0},{name:"--user",takesValue:!0}]},{path:["auth","token"],args:[],flags:[{name:"--hostname",takesValue:!0},{name:"--user",takesValue:!0},{name:"--branch",takesValue:!0},{name:"--commit",takesValue:!1},{name:"--no-browser",takesValue:!1},{name:"--projects",takesValue:!1},{name:"--releases",takesValue:!1},{name:"--settings",takesValue:!1},{name:"--wiki",takesValue:!1}]},{path:["cache","delete"],args:["<cache-id> | <cache-key> | --all"],flags:[{name:"--all",takesValue:!1},{name:"--ref",takesValue:!0},{name:"--succeed-on-no-caches",takesValue:!1}]},{path:["cache","list"],args:[],flags:[{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--key",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--order",takesValue:!0},{name:"--ref",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["codespace","code"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--insiders",takesValue:!1},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["codespace","cp"],args:["-e","-r","]","<sources>...","<dest>"],flags:[{name:"--codespace",takesValue:!0},{name:"--expand",takesValue:!1},{name:"--profile",takesValue:!0},{name:"--recursive",takesValue:!1},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0}]},{path:["codespace","create"],args:[],flags:[{name:"--branch",takesValue:!0},{name:"--default-permissions",takesValue:!1},{name:"--devcontainer-path",takesValue:!0},{name:"--display-name",takesValue:!0},{name:"--idle-timeout",takesValue:!0},{name:"--location",takesValue:!0},{name:"--machine",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--retention-period",takesValue:!0},{name:"--status",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["codespace","delete"],args:[],flags:[{name:"--all",takesValue:!1},{name:"--codespace",takesValue:!0},{name:"--days",takesValue:!1},{name:"--force",takesValue:!1},{name:"--org",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0},{name:"--user",takesValue:!0}]},{path:["codespace","edit"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--display-name",takesValue:!0},{name:"--machine",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0}]},{path:["codespace","jupyter"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0}]},{path:["codespace","list"],args:[],flags:[{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--org",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--template",takesValue:!0},{name:"--user",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["codespace","logs"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--follow",takesValue:!1},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0}]},{path:["codespace","ports"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["codespace","rebuild"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--full",takesValue:!1},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0}]},{path:["codespace","ssh"],args:["<flags>...","<command>"],flags:[{name:"--codespace",takesValue:!0},{name:"--config",takesValue:!1},{name:"--debug",takesValue:!1},{name:"--debug-file",takesValue:!0},{name:"--profile",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0},{name:"--server-port",takesValue:!0}]},{path:["codespace","stop"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--org",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0},{name:"--user",takesValue:!0}]},{path:["codespace","view"],args:[],flags:[{name:"--codespace",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--repo-owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--shell",takesValue:!0}]},{path:["config","clear-cache"],args:[],flags:[]},{path:["config","get"],args:["<key>"],flags:[{name:"--host",takesValue:!0}]},{path:["config","list"],args:[],flags:[{name:"--host",takesValue:!0}]},{path:["config","set"],args:["<key>","<value>"],flags:[{name:"--host",takesValue:!0}]},{path:["extension","browse"],args:[],flags:[{name:"--debug",takesValue:!1},{name:"--single-column",takesValue:!1}]},{path:["extension","create"],args:["<name>"],flags:[{name:"--precompiled",takesValue:!0}]},{path:["extension","exec"],args:["<name>","args"],flags:[]},{path:["extension","install"],args:["<repository>"],flags:[{name:"--force",takesValue:!1},{name:"--pin",takesValue:!0}]},{path:["extension","list"],args:[],flags:[]},{path:["extension","remove"],args:["<name>"],flags:[]},{path:["extension","search"],args:["<query>"],flags:[{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--license",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--order",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["extension","upgrade"],args:[],flags:[{name:"--all",takesValue:!1},{name:"--dry-run",takesValue:!1},{name:"--force",takesValue:!1}]},{path:["gist","clone"],args:["<gist>","<directory>"],flags:[]},{path:["gist","create"],args:["<filename>... | <pattern>... | -"],flags:[{name:"--desc",takesValue:!0},{name:"--filename",takesValue:!0},{name:"--public",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["gist","delete"],args:["<id> | <url>"],flags:[{name:"--yes",takesValue:!1}]},{path:["gist","edit"],args:["<id> | <url>","<filename>"],flags:[{name:"--add",takesValue:!0},{name:"--desc",takesValue:!0},{name:"--filename",takesValue:!0},{name:"--remove",takesValue:!0}]},{path:["gist","list"],args:[],flags:[{name:"--filter",takesValue:!0},{name:"--include-content",takesValue:!1},{name:"--limit",takesValue:!0},{name:"--public",takesValue:!1},{name:"--secret",takesValue:!1}]},{path:["gist","rename"],args:["<id> | <url>","<old-filename>","<new-filename>"],flags:[]},{path:["gist","view"],args:["<id> | <url>"],flags:[{name:"--filename",takesValue:!0},{name:"--files",takesValue:!1},{name:"--raw",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["gpg-key","add"],args:["<key-file>"],flags:[{name:"--title",takesValue:!0}]},{path:["gpg-key","delete"],args:["<key-id>"],flags:[{name:"--yes",takesValue:!1}]},{path:["gpg-key","list"],args:[],flags:[]},{path:["issue","close"],args:["<number> | <url>"],flags:[{name:"--comment",takesValue:!0},{name:"--reason",takesValue:!0}]},{path:["issue","comment"],args:["<number> | <url>"],flags:[{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--create-if-none",takesValue:!1},{name:"--delete-last",takesValue:!1},{name:"--edit-last",takesValue:!1},{name:"--editor",takesValue:!1},{name:"--web",takesValue:!1},{name:"--yes",takesValue:!1}]},{path:["issue","create"],args:[],flags:[{name:"--assignee",takesValue:!0},{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--editor",takesValue:!1},{name:"--label",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--project",takesValue:!0},{name:"--recover",takesValue:!0},{name:"--template",takesValue:!0},{name:"--title",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["issue","delete"],args:["<number> | <url>"],flags:[{name:"--yes",takesValue:!1}]},{path:["issue","develop"],args:["<number> | <url>"],flags:[{name:"--base",takesValue:!0},{name:"--branch-repo",takesValue:!0},{name:"--checkout",takesValue:!1},{name:"--list",takesValue:!1},{name:"--name",takesValue:!0}]},{path:["issue","edit"],args:["<numbers> | <urls>"],flags:[{name:"--add-assignee",takesValue:!0},{name:"--add-label",takesValue:!0},{name:"--add-project",takesValue:!0},{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--remove-assignee",takesValue:!0},{name:"--remove-label",takesValue:!0},{name:"--remove-milestone",takesValue:!1},{name:"--remove-project",takesValue:!0},{name:"--title",takesValue:!0}]},{path:["issue","list"],args:[],flags:[{name:"--app",takesValue:!0},{name:"--assignee",takesValue:!0},{name:"--author",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--label",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--mention",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--search",takesValue:!0},{name:"--state",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["issue","lock"],args:["<number> | <url>"],flags:[{name:"--reason",takesValue:!0}]},{path:["issue","pin"],args:["<number> | <url>"],flags:[]},{path:["issue","reopen"],args:["<number> | <url>"],flags:[{name:"--comment",takesValue:!0}]},{path:["issue","status"],args:[],flags:[{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["issue","transfer"],args:["<number> | <url>","<destination-repo>"],flags:[]},{path:["issue","unlock"],args:["<number> | <url>"],flags:[]},{path:["issue","unpin"],args:["<number> | <url>"],flags:[]},{path:["issue","view"],args:["<number> | <url>"],flags:[{name:"--comments",takesValue:!1},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["label","clone"],args:["<source-repository>"],flags:[{name:"--force",takesValue:!1}]},{path:["label","create"],args:["<name>"],flags:[{name:"--color",takesValue:!0},{name:"--description",takesValue:!0},{name:"--force",takesValue:!1}]},{path:["label","delete"],args:["<name>"],flags:[{name:"--yes",takesValue:!1}]},{path:["label","edit"],args:["<name>"],flags:[{name:"--color",takesValue:!0},{name:"--description",takesValue:!0},{name:"--name",takesValue:!0}]},{path:["label","list"],args:[],flags:[{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--order",takesValue:!0},{name:"--search",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["org","list"],args:[],flags:[{name:"--limit",takesValue:!0},{name:"--help",takesValue:!1},{name:"--repo",takesValue:!1}]},{path:["pr","checkout"],args:["<number> | <url> | <branch>"],flags:[{name:"--branch",takesValue:!0},{name:"--detach",takesValue:!1},{name:"--force",takesValue:!1},{name:"--recurse-submodules",takesValue:!1}]},{path:["pr","checks"],args:["<number> | <url> | <branch>"],flags:[{name:"--fail-fast",takesValue:!1},{name:"--interval",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--required",takesValue:!1},{name:"--template",takesValue:!0},{name:"--watch",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["pr","close"],args:["<number> | <url> | <branch>"],flags:[{name:"--comment",takesValue:!0},{name:"--delete-branch",takesValue:!1}]},{path:["pr","comment"],args:["<number> | <url> | <branch>"],flags:[{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--create-if-none",takesValue:!1},{name:"--delete-last",takesValue:!1},{name:"--edit-last",takesValue:!1},{name:"--editor",takesValue:!1},{name:"--web",takesValue:!1},{name:"--yes",takesValue:!1}]},{path:["pr","create"],args:[],flags:[{name:"--assignee",takesValue:!0},{name:"--base",takesValue:!0},{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--draft",takesValue:!1},{name:"--dry-run",takesValue:!1},{name:"--editor",takesValue:!1},{name:"--fill",takesValue:!1},{name:"--fill-first",takesValue:!1},{name:"--fill-verbose",takesValue:!1},{name:"--head",takesValue:!0},{name:"--label",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--no-maintainer-edit",takesValue:!1},{name:"--project",takesValue:!0},{name:"--recover",takesValue:!0},{name:"--reviewer",takesValue:!0},{name:"--template",takesValue:!0},{name:"--title",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["pr","diff"],args:["<number> | <url> | <branch>"],flags:[{name:"--color",takesValue:!0},{name:"--name-only",takesValue:!1},{name:"--patch",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["pr","edit"],args:["<number> | <url> | <branch>"],flags:[{name:"--add-assignee",takesValue:!0},{name:"--add-label",takesValue:!0},{name:"--add-project",takesValue:!0},{name:"--add-reviewer",takesValue:!0},{name:"--base",takesValue:!0},{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--remove-assignee",takesValue:!0},{name:"--remove-label",takesValue:!0},{name:"--remove-milestone",takesValue:!1},{name:"--remove-project",takesValue:!0},{name:"--remove-reviewer",takesValue:!0},{name:"--title",takesValue:!0}]},{path:["pr","list"],args:[],flags:[{name:"--app",takesValue:!0},{name:"--assignee",takesValue:!0},{name:"--author",takesValue:!0},{name:"--base",takesValue:!0},{name:"--draft",takesValue:!1},{name:"--head",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--label",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--search",takesValue:!0},{name:"--state",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["pr","lock"],args:["<number> | <url>"],flags:[{name:"--reason",takesValue:!0}]},{path:["pr","merge"],args:["<number> | <url> | <branch>"],flags:[{name:"--admin",takesValue:!1},{name:"--author-email",takesValue:!0},{name:"--auto",takesValue:!1},{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--delete-branch",takesValue:!1},{name:"--disable-auto",takesValue:!1},{name:"--match-head-commit",takesValue:!1},{name:"--merge",takesValue:!1},{name:"--rebase",takesValue:!1},{name:"--squash",takesValue:!1},{name:"--subject",takesValue:!0}]},{path:["pr","ready"],args:["<number> | <url> | <branch>"],flags:[{name:"--undo",takesValue:!1}]},{path:["pr","reopen"],args:["<number> | <url> | <branch>"],flags:[{name:"--comment",takesValue:!0}]},{path:["pr","revert"],args:["<number> | <url> | <branch>"],flags:[{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--draft",takesValue:!1},{name:"--title",takesValue:!0}]},{path:["pr","review"],args:["<number> | <url> | <branch>"],flags:[{name:"--approve",takesValue:!1},{name:"--body",takesValue:!0},{name:"--body-file",takesValue:!0},{name:"--comment",takesValue:!1},{name:"--request-changes",takesValue:!1}]},{path:["pr","status"],args:[],flags:[{name:"--conflict-status",takesValue:!1},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["pr","unlock"],args:["<number> | <url>"],flags:[]},{path:["pr","update-branch"],args:["<number> | <url> | <branch>"],flags:[{name:"--rebase",takesValue:!1}]},{path:["pr","view"],args:["<number> | <url> | <branch>"],flags:[{name:"--comments",takesValue:!1},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["preview","prompter"],args:["prompt type"],flags:[]},{path:["project","close"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--undo",takesValue:!1}]},{path:["project","copy"],args:["<number>"],flags:[{name:"--drafts",takesValue:!1},{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--source-owner",takesValue:!0},{name:"--target-owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--title",takesValue:!0}]},{path:["project","create"],args:[],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--title",takesValue:!0}]},{path:["project","delete"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["project","edit"],args:["<number>"],flags:[{name:"--description",takesValue:!0},{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--readme",takesValue:!0},{name:"--template",takesValue:!0},{name:"--title",takesValue:!0},{name:"--visibility",takesValue:!0}]},{path:["project","field-create"],args:["<number>"],flags:[{name:"--data-type",takesValue:!0},{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--name",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--single-select-options",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["project","field-delete"],args:[],flags:[{name:"--format",takesValue:!0},{name:"--id",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["project","field-list"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["project","item-add"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--url",takesValue:!0}]},{path:["project","item-archive"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--id",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--undo",takesValue:!1}]},{path:["project","item-create"],args:["<number>"],flags:[{name:"--body",takesValue:!0},{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--title",takesValue:!0}]},{path:["project","item-delete"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--id",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["project","item-edit"],args:[],flags:[{name:"--body",takesValue:!0},{name:"--clear",takesValue:!1},{name:"--date",takesValue:!0},{name:"--field-id",takesValue:!0},{name:"--format",takesValue:!0},{name:"--id",takesValue:!0},{name:"--iteration-id",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--number",takesValue:!0},{name:"--project-id",takesValue:!0},{name:"--single-select-option-id",takesValue:!0},{name:"--template",takesValue:!0},{name:"--text",takesValue:!0},{name:"--title",takesValue:!0}]},{path:["project","item-list"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["project","link"],args:["<number>"],flags:[{name:"--owner",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--team",takesValue:!0}]},{path:["project","list"],args:[],flags:[{name:"--closed",takesValue:!1},{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["project","mark-template"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--undo",takesValue:!1}]},{path:["project","unlink"],args:["<number>"],flags:[{name:"--owner",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--team",takesValue:!0}]},{path:["project","view"],args:["<number>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["release","create"],args:["<tag>","<filename>... | <pattern>..."],flags:[{name:"--discussion-category",takesValue:!0},{name:"--draft",takesValue:!1},{name:"--fail-on-no-commits",takesValue:!1},{name:"--generate-notes",takesValue:!1},{name:"--latest",takesValue:!1},{name:"--notes",takesValue:!0},{name:"--notes-file",takesValue:!0},{name:"--notes-from-tag",takesValue:!1},{name:"--notes-start-tag",takesValue:!0},{name:"--prerelease",takesValue:!1},{name:"--target",takesValue:!0},{name:"--title",takesValue:!0},{name:"--verify-tag",takesValue:!1}]},{path:["release","delete"],args:["<tag>"],flags:[{name:"--cleanup-tag",takesValue:!1},{name:"--yes",takesValue:!1}]},{path:["release","delete-asset"],args:["<tag>","<asset-name>"],flags:[{name:"--yes",takesValue:!1}]},{path:["release","download"],args:["<tag>"],flags:[{name:"--archive",takesValue:!0},{name:"--clobber",takesValue:!1},{name:"--dir",takesValue:!0},{name:"--output",takesValue:!0},{name:"--pattern",takesValue:!0},{name:"--skip-existing",takesValue:!1}]},{path:["release","edit"],args:["<tag>"],flags:[{name:"--discussion-category",takesValue:!0},{name:"--draft",takesValue:!1},{name:"--latest",takesValue:!1},{name:"--notes",takesValue:!0},{name:"--notes-file",takesValue:!0},{name:"--prerelease",takesValue:!1},{name:"--tag",takesValue:!0},{name:"--target",takesValue:!0},{name:"--title",takesValue:!0},{name:"--verify-tag",takesValue:!1}]},{path:["release","list"],args:[],flags:[{name:"--exclude-drafts",takesValue:!1},{name:"--exclude-pre-releases",takesValue:!1},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--order",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["release","upload"],args:["<tag>","<files>..."],flags:[{name:"--clobber",takesValue:!1}]},{path:["release","verify"],args:["<tag>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["release","verify-asset"],args:["<tag>","<file-path>"],flags:[{name:"--format",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["release","view"],args:["<tag>"],flags:[{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["repo","archive"],args:["<repository>"],flags:[{name:"--yes",takesValue:!1}]},{path:["repo","autolink"],args:["<command>"],flags:[]},{path:["repo","clone"],args:["<repository>","<directory>"],flags:[{name:"--upstream-remote-name",takesValue:!0}]},{path:["repo","create"],args:["<name>"],flags:[{name:"--add-readme",takesValue:!1},{name:"--clone",takesValue:!1},{name:"--description",takesValue:!0},{name:"--disable-issues",takesValue:!1},{name:"--disable-wiki",takesValue:!1},{name:"--gitignore",takesValue:!0},{name:"--homepage",takesValue:!1},{name:"--include-all-branches",takesValue:!1},{name:"--internal",takesValue:!1},{name:"--license",takesValue:!0},{name:"--private",takesValue:!1},{name:"--public",takesValue:!1},{name:"--push",takesValue:!1},{name:"--remote",takesValue:!0},{name:"--source",takesValue:!0},{name:"--team",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["repo","delete"],args:["<repository>"],flags:[{name:"--yes",takesValue:!1}]},{path:["repo","deploy-key"],args:["<command>"],flags:[]},{path:["repo","edit"],args:["<repository>"],flags:[{name:"--accept-visibility-change-consequences",takesValue:!1},{name:"--add-topic",takesValue:!0},{name:"--allow-forking",takesValue:!1},{name:"--allow-update-branch",takesValue:!1},{name:"--default-branch",takesValue:!0},{name:"--delete-branch-on-merge",takesValue:!1},{name:"--description",takesValue:!0},{name:"--enable-advanced-security",takesValue:!1},{name:"--enable-auto-merge",takesValue:!1},{name:"--enable-discussions",takesValue:!1},{name:"--enable-issues",takesValue:!1},{name:"--enable-merge-commit",takesValue:!1},{name:"--enable-projects",takesValue:!1},{name:"--enable-rebase-merge",takesValue:!1},{name:"--enable-secret-scanning",takesValue:!1},{name:"--enable-secret-scanning-push-protection",takesValue:!1},{name:"--enable-squash-merge",takesValue:!1},{name:"--enable-wiki",takesValue:!1},{name:"--homepage",takesValue:!1},{name:"--remove-topic",takesValue:!0},{name:"--template",takesValue:!1},{name:"--visibility",takesValue:!0}]},{path:["repo","fork"],args:["<repository>"],flags:[{name:"--clone",takesValue:!1},{name:"--default-branch-only",takesValue:!1},{name:"--fork-name",takesValue:!0},{name:"--org",takesValue:!0},{name:"--remote",takesValue:!1},{name:"--remote-name",takesValue:!0}]},{path:["repo","gitignore"],args:["<command>"],flags:[]},{path:["repo","license"],args:["<command>"],flags:[]},{path:["repo","list"],args:["<owner>"],flags:[{name:"--archived",takesValue:!1},{name:"--fork",takesValue:!1},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--language",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--no-archived",takesValue:!1},{name:"--source",takesValue:!1},{name:"--template",takesValue:!0},{name:"--topic",takesValue:!0},{name:"--visibility",takesValue:!0}]},{path:["repo","rename"],args:["<new-name>"],flags:[{name:"--yes",takesValue:!1}]},{path:["repo","set-default"],args:["<repository>"],flags:[{name:"--unset",takesValue:!1},{name:"--view",takesValue:!1}]},{path:["repo","sync"],args:["<destination-repository>"],flags:[{name:"--branch",takesValue:!0},{name:"--force",takesValue:!1},{name:"--source",takesValue:!0}]},{path:["repo","unarchive"],args:["<repository>"],flags:[{name:"--yes",takesValue:!1}]},{path:["repo","view"],args:["<repository>"],flags:[{name:"--branch",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["ruleset","check"],args:["<branch>"],flags:[{name:"--default",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["ruleset","list"],args:[],flags:[{name:"--limit",takesValue:!0},{name:"--org",takesValue:!0},{name:"--parents",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["ruleset","view"],args:["<ruleset-id>"],flags:[{name:"--org",takesValue:!0},{name:"--parents",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["run","cancel"],args:["<run-id>"],flags:[{name:"--force",takesValue:!1}]},{path:["run","delete"],args:["<run-id>"],flags:[]},{path:["run","download"],args:["<run-id>"],flags:[{name:"--dir",takesValue:!0},{name:"--name",takesValue:!0},{name:"--pattern",takesValue:!0}]},{path:["run","list"],args:[],flags:[{name:"--all",takesValue:!1},{name:"--branch",takesValue:!0},{name:"--commit",takesValue:!1},{name:"--created",takesValue:!0},{name:"--event",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--status",takesValue:!0},{name:"--template",takesValue:!0},{name:"--user",takesValue:!0},{name:"--workflow",takesValue:!0}]},{path:["run","rerun"],args:["<run-id>"],flags:[{name:"--debug",takesValue:!1},{name:"--failed",takesValue:!1},{name:"--job",takesValue:!0}]},{path:["run","view"],args:["<run-id>"],flags:[{name:"--attempt",takesValue:!0},{name:"--exit-status",takesValue:!1},{name:"--job",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--log",takesValue:!1},{name:"--log-failed",takesValue:!1},{name:"--template",takesValue:!0},{name:"--verbose",takesValue:!1},{name:"--web",takesValue:!1}]},{path:["run","watch"],args:["<run-id>"],flags:[{name:"--compact",takesValue:!1},{name:"--exit-status",takesValue:!1},{name:"--interval",takesValue:!0}]},{path:["search","code"],args:["<query>"],flags:[{name:"--extension",takesValue:!0},{name:"--filename",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--language",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--match",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--size",takesValue:!0},{name:"--template",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["search","commits"],args:["<query>"],flags:[{name:"--author",takesValue:!0},{name:"--author-date",takesValue:!0},{name:"--author-email",takesValue:!0},{name:"--author-name",takesValue:!0},{name:"--committer",takesValue:!0},{name:"--committer-date",takesValue:!0},{name:"--committer-email",takesValue:!0},{name:"--committer-name",takesValue:!0},{name:"--hash",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--merge",takesValue:!1},{name:"--order",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--parent",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--template",takesValue:!0},{name:"--tree",takesValue:!0},{name:"--visibility",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["search","issues"],args:["<query>"],flags:[{name:"--app",takesValue:!0},{name:"--archived",takesValue:!1},{name:"--assignee",takesValue:!0},{name:"--author",takesValue:!0},{name:"--closed",takesValue:!0},{name:"--commenter",takesValue:!0},{name:"--comments",takesValue:!0},{name:"--created",takesValue:!0},{name:"--include-prs",takesValue:!1},{name:"--interactions",takesValue:!0},{name:"--involves",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--label",takesValue:!0},{name:"--language",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--locked",takesValue:!1},{name:"--match",takesValue:!0},{name:"--mentions",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--no-assignee",takesValue:!1},{name:"--no-label",takesValue:!1},{name:"--no-milestone",takesValue:!1},{name:"--no-project",takesValue:!1},{name:"--order",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--project",takesValue:!0},{name:"--reactions",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--state",takesValue:!0},{name:"--team-mentions",takesValue:!0},{name:"--template",takesValue:!0},{name:"--updated",takesValue:!0},{name:"--visibility",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["search","prs"],args:["<query>"],flags:[{name:"--app",takesValue:!0},{name:"--archived",takesValue:!1},{name:"--assignee",takesValue:!0},{name:"--author",takesValue:!0},{name:"--base",takesValue:!0},{name:"--checks",takesValue:!0},{name:"--closed",takesValue:!0},{name:"--commenter",takesValue:!0},{name:"--comments",takesValue:!0},{name:"--created",takesValue:!0},{name:"--draft",takesValue:!1},{name:"--head",takesValue:!0},{name:"--interactions",takesValue:!0},{name:"--involves",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--label",takesValue:!0},{name:"--language",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--locked",takesValue:!1},{name:"--match",takesValue:!0},{name:"--mentions",takesValue:!0},{name:"--merged",takesValue:!1},{name:"--merged-at",takesValue:!0},{name:"--milestone",takesValue:!0},{name:"--no-assignee",takesValue:!1},{name:"--no-label",takesValue:!1},{name:"--no-milestone",takesValue:!1},{name:"--no-project",takesValue:!1},{name:"--order",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--project",takesValue:!0},{name:"--reactions",takesValue:!0},{name:"--repo",takesValue:!0},{name:"--review",takesValue:!0},{name:"--review-requested",takesValue:!0},{name:"--reviewed-by",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--state",takesValue:!0},{name:"--team-mentions",takesValue:!0},{name:"--template",takesValue:!0},{name:"--updated",takesValue:!0},{name:"--visibility",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["search","repos"],args:["<query>"],flags:[{name:"--archived",takesValue:!1},{name:"--created",takesValue:!0},{name:"--followers",takesValue:!0},{name:"--forks",takesValue:!0},{name:"--good-first-issues",takesValue:!0},{name:"--help-wanted-issues",takesValue:!0},{name:"--include-forks",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--language",takesValue:!0},{name:"--license",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--match",takesValue:!0},{name:"--number-topics",takesValue:!0},{name:"--order",takesValue:!0},{name:"--owner",takesValue:!0},{name:"--size",takesValue:!0},{name:"--sort",takesValue:!0},{name:"--stars",takesValue:!0},{name:"--template",takesValue:!0},{name:"--topic",takesValue:!0},{name:"--updated",takesValue:!0},{name:"--visibility",takesValue:!0},{name:"--web",takesValue:!1}]},{path:["secret","delete"],args:["<secret-name>"],flags:[{name:"--app",takesValue:!0},{name:"--env",takesValue:!0},{name:"--org",takesValue:!0},{name:"--user",takesValue:!1}]},{path:["secret","list"],args:[],flags:[{name:"--app",takesValue:!0},{name:"--env",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--org",takesValue:!0},{name:"--template",takesValue:!0},{name:"--user",takesValue:!1}]},{path:["secret","set"],args:["<secret-name>"],flags:[{name:"--app",takesValue:!0},{name:"--body",takesValue:!0},{name:"--env",takesValue:!0},{name:"--env-file",takesValue:!0},{name:"--no-repos-selected",takesValue:!1},{name:"--no-store",takesValue:!1},{name:"--org",takesValue:!0},{name:"--repos",takesValue:!0},{name:"--user",takesValue:!1},{name:"--visibility",takesValue:!0}]},{path:["ssh-key","add"],args:["<key-file>"],flags:[{name:"--title",takesValue:!0},{name:"--type",takesValue:!0}]},{path:["ssh-key","delete"],args:["<id>"],flags:[{name:"--yes",takesValue:!1}]},{path:["ssh-key","list"],args:[],flags:[{name:"--exclude",takesValue:!0},{name:"--org",takesValue:!0}]},{path:["variable","delete"],args:["<variable-name>"],flags:[{name:"--env",takesValue:!0},{name:"--org",takesValue:!0}]},{path:["variable","get"],args:["<variable-name>"],flags:[{name:"--env",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--org",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["variable","list"],args:[],flags:[{name:"--env",takesValue:!0},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--org",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["variable","set"],args:["<variable-name>"],flags:[{name:"--body",takesValue:!0},{name:"--env",takesValue:!0},{name:"--env-file",takesValue:!0},{name:"--org",takesValue:!0},{name:"--repos",takesValue:!0},{name:"--visibility",takesValue:!0}]},{path:["workflow","disable"],args:["<workflow-id> | <workflow-name>"],flags:[]},{path:["workflow","enable"],args:["<workflow-id> | <workflow-name>"],flags:[]},{path:["workflow","list"],args:[],flags:[{name:"--all",takesValue:!1},{name:"--jq",takesValue:!0},{name:"--json",takesValue:!0},{name:"--limit",takesValue:!0},{name:"--template",takesValue:!0}]},{path:["workflow","run"],args:["<workflow-id> | <workflow-name>"],flags:[{name:"--field",takesValue:!0},{name:"--json",takesValue:!1},{name:"--raw-field",takesValue:!0},{name:"--ref",takesValue:!0}]},{path:["workflow","view"],args:["<workflow-id> | <workflow-name> | <filename>"],flags:[{name:"--ref",takesValue:!0},{name:"--web",takesValue:!1},{name:"--yaml",takesValue:!1}]},{path:["contents","create"],args:["<file-path>"],flags:[]},{path:["contents","view"],args:["<file-path>"],flags:[]},{path:["contents","list"],args:["<dir-path>"],flags:[]},{path:["contents","update"],args:["<file-path>"],flags:[]},{path:["contents","delete"],args:["<file-path>"],flags:[]}]};import{spawn as Ee}from"child_process";import Te from"crypto";var Pe=60000,je=(e)=>typeof e==="object"&&e!==null&&!Array.isArray(e),C=(e)=>{if(typeof e==="number"&&Number.isFinite(e)&&e>0)return Math.floor(e);if(typeof e!=="string")return null;let a=e.trim();if(!a)return null;let t=Number(a);if(!Number.isFinite(t)||t<=0)return null;return Math.floor(t)},Se=()=>{return C(process.env.F0_GIT_REQUEST_TIMEOUT_MS)??C(process.env.F0_HTTP_REQUEST_TIMEOUT_MS)??C(process.env.F0_HTTP_TIMEOUT_MS)??Pe},Re=(e)=>Object.fromEntries(e.map((a)=>{let t=a.indexOf(":");if(t<0)return null;let r=a.slice(0,t).trim(),s=a.slice(t+1).trim();return[r,s]}).filter((a)=>Boolean(a))),Ie=(e)=>{if(e.length===0||!je(e[e.length-1]))return{args:e.map((t)=>String(t)),options:{}};let a=e[e.length-1];return{args:e.slice(0,-1).map((t)=>String(t)),options:a}},J=(e)=>e.replace(/^--/,"").trim().toLowerCase(),xe=(e,a)=>{let t={},r={},s=new Map;for(let o of e.flags){let u=J(o.name);s.set(u,o.name)}let l=new Set(["body","json","data","payload","headers","query","method"]);for(let[o,u]of Object.entries(a)){let i=J(o);if(u===void 0)continue;if(l.has(i))continue;if(s.has(i)){let m=s.get(i);if(m)t[m]=typeof u==="boolean"?u:String(u);continue}r[o]=u}return{flags:t,unhandled:r}},Fe=(e,a,t)=>{if(!["POST","PUT","PATCH","DELETE"].includes(e.toUpperCase()))return;if(a.body!==void 0)return a.body;if(a.json!==void 0)return a.json;if(a.data!==void 0)return a.data;if(a.payload!==void 0)return a.payload;if(Object.keys(t).length>0)return t;return},_e=(e,a,t,r={})=>{let s=`${e}/${a.join("/")}`,l=new URL(s);for(let o of t){let[u,i=""]=o.split("=",2);if(!u)continue;l.searchParams.set(u,i)}for(let[o,u]of Object.entries(r))l.searchParams.set(o,String(u));return l.toString()},Oe=()=>typeof AbortSignal<"u"&&typeof AbortSignal.timeout==="function",$e=()=>Boolean(process.env.VITEST)||!1,Ce=(e)=>{let a=(e??"").trim().toLowerCase();if(a==="fetch"||a==="curl")return a;let t=Boolean(process.versions?.bun);if(!$e()&&t&&process.platform==="win32")return"curl";return"fetch"},K=async(e)=>{if(!e)return Buffer.from([]);let a=[];for await(let t of e)if(typeof t==="string")a.push(Buffer.from(t));else a.push(Buffer.from(t));return Buffer.concat(a)},De=async(e,a,t)=>{let r=process.platform==="win32"?"curl.exe":"curl",l=`
|
|
3
|
-
__F0_CURL_STATUS_${Te.randomBytes(8).toString("hex")}__`,o=`${l}%{http_code}${l}`,u=["--silent","--show-error","--location","--request",a.method,"--write-out",o],i=t>0?Math.max(1,Math.ceil(t/1000)):null;if(i!==null)u.push("--max-time",String(i));for(let[d,f]of Object.entries(a.headers))u.push("--header",`${d}: ${f}`);if(a.body!==void 0)u.push("--data-binary","@-");u.push(e);let m=Ee(r,u,{stdio:["pipe","pipe","pipe"],windowsHide:!0});if(a.body!==void 0)m.stdin.write(a.body);m.stdin.end();let[V,G]=await Promise.all([K(m.stdout),K(m.stderr)]),h=await new Promise((d)=>{m.on("close",(f)=>d(f??0)),m.on("error",()=>d(1))}),g=V.toString("utf8"),k=G.toString("utf8").trim();if(h!==0){let d=k||`curl failed with exit code ${h}`;if(h===28&&t>0)throw Error(`Request timed out after ${t}ms: ${a.method} ${e}`);throw Error(d)}let c=g.lastIndexOf(l),w=c>-1?g.lastIndexOf(l,c-1):-1;if(w<0||c<0)throw Error("Failed to parse curl response status code.");let b=g.slice(w+l.length,c).trim(),p=Number(b),E=g.slice(0,w);if(!Number.isFinite(p)||p<=0)throw Error(`Invalid curl status code: ${b}`);return{status:p,ok:p>=200&&p<300,bodyText:E,responseHeaders:{}}},He=(e,a,t,r,s,l)=>{return async(...o)=>{let{args:u,options:i}=Ie(o),{flags:m,unhandled:V}=xe(e,i),{query:G,method:h,...g}=i,k=await a.mapFeature({feature:e,args:u,flagValues:m,method:h}),c=k.mappedPath.map((f)=>{if(f==="{owner}"&&t.defaultOwner)return t.defaultOwner;if(f==="{repo}"&&t.defaultRepo)return t.defaultRepo;return f}),w=Fe(k.method,g,V),b={...Re(k.headers),...i.headers??{}};if(w!==void 0&&!b["Content-Type"])b["Content-Type"]="application/json";let p=_e(k.apiBase,c,k.query,G??{}),E={method:k.method,headers:b,body:w!==void 0?JSON.stringify(w):void 0},d=Date.now();l?.(`http:request ${k.method} ${p}`);try{let f={},y=0,v=!1,j="";if(s==="curl"){let T=await De(p,{method:k.method,headers:b,...E.body!==void 0?{body:String(E.body)}:{}},r);y=T.status,v=T.ok;let P=T.bodyText;j=P;try{j=JSON.parse(P)}catch{j=P}}else{let T=r>0&&Oe()?AbortSignal.timeout(r):null,P=!T&&r>0?new AbortController:null,B=P?setTimeout(()=>P.abort(),r):null;try{let S=await fetch(p,{...E,...T?{signal:T}:{},...P?{signal:P.signal}:{}});y=S.status,v=S.ok;let H=await S.text();j=H;try{j=JSON.parse(H)}catch{j=H}try{S.headers.forEach((se,re)=>{f[re.toLowerCase()]=se})}catch{}}catch(S){if(T&&T.aborted||P?.signal.aborted)throw Error(`Request timed out after ${r}ms: ${k.method} ${p}`);throw S}finally{if(B)clearTimeout(B)}}return l?.(`http:response ${k.method} ${p} -> ${y} (${Date.now()-d}ms)`),{mapping:{...k,mappedPath:c},request:{url:p,method:k.method,headers:b,query:[...k.query],body:w},response:{headers:f},status:y,ok:v,body:j}}catch(f){let y=f instanceof Error?f.message:String(f);throw l?.(`http:error ${k.method} ${p} (${y})`),f}}},X=(e,a,t,r,s,l,o,u)=>{let i=e;for(let m=0;m<a.length;m+=1){let V=a[m];if(m===a.length-1){i[V]=He(t,r,s,l,o,u);continue}if(!i[V])i[V]={};let h=i[V];if(typeof h!=="object"||h===null)i[V]={};i=i[V]}},Y=(e={})=>{let a=F(e.config),t=$({config:a,...e.swaggerSpec?{swaggerSpec:e.swaggerSpec}:{}}),r=C(e.requestTimeoutMs)??Se(),s=Ce(e.httpTransport??process.env.F0_GIT_HTTP_TRANSPORT),l=e.log,o={defaultOwner:e.defaultOwner??process.env.GITEA_TEST_OWNER??"F0",defaultRepo:e.defaultRepo??process.env.GITEA_TEST_REPO??"_test"},u={};for(let i of z.features){if(i.path.length===0)continue;if(X(u,i.path,i,t,o,r,s,l),i.path[0]!=="repo")X(u,["repo",...i.path],i,t,o,r,s,l)}return u},qe=Y();import{spawn as Le}from"child_process";import Ne from"crypto";var Be="https://gitea.machian.com",Me=60000,N=(e)=>{if(typeof e==="number"&&Number.isFinite(e)&&e>0)return Math.floor(e);if(typeof e!=="string")return null;let a=e.trim();if(!a)return null;let t=Number(a);if(!Number.isFinite(t)||t<=0)return null;return Math.floor(t)},ae=()=>{return N(process.env.F0_GIT_REQUEST_TIMEOUT_MS)??N(process.env.F0_HTTP_REQUEST_TIMEOUT_MS)??N(process.env.F0_HTTP_TIMEOUT_MS)??Me},Ue=()=>typeof AbortSignal<"u"&&typeof AbortSignal.timeout==="function",We=()=>Boolean(process.env.VITEST)||!1,Qe=(e)=>{let a=(e??"").trim().toLowerCase();if(a==="fetch"||a==="curl")return a;let t=Boolean(process.versions?.bun);if(!We()&&t&&process.platform==="win32")return"curl";return"fetch"},ze=async(e,a)=>{let t=ae();if(!Number.isFinite(t)||t<=0)return fetch(e,a);let r=t>0&&Ue()?AbortSignal.timeout(t):null,s=!r?new AbortController:null,l=s?setTimeout(()=>s.abort(),t):null;try{return await fetch(e,{...a,...r?{signal:r}:{},...s?{signal:s.signal}:{}})}catch(o){if(r&&r.aborted||s?.signal.aborted)throw Error(`Request timed out after ${t}ms: ${a.method??"GET"} ${e}`);throw o}finally{if(l)clearTimeout(l)}},Z=async(e)=>{if(!e)return Buffer.from([]);let a=[];for await(let t of e)if(typeof t==="string")a.push(Buffer.from(t));else a.push(Buffer.from(t));return Buffer.concat(a)},Je=async(e,a,t)=>{let r=process.platform==="win32"?"curl.exe":"curl",l=`
|
|
4
|
-
__F0_CURL_STATUS_${Ne.randomBytes(8).toString("hex")}__`,o=`${l}%{http_code}${l}`,u=["--silent","--show-error","--location","--request",a.method,"--write-out",o],i=t>0?Math.max(1,Math.ceil(t/1000)):null;if(i!==null)u.push("--max-time",String(i));for(let[d,f]of Object.entries(a.headers))u.push("--header",`${d}: ${f}`);if(a.body!==void 0)u.push("--data-binary","@-");u.push(e);let m=Le(r,u,{stdio:["pipe","pipe","pipe"],windowsHide:!0});if(a.body!==void 0)m.stdin.write(a.body);m.stdin.end();let[V,G]=await Promise.all([Z(m.stdout),Z(m.stderr)]),h=await new Promise((d)=>{m.on("close",(f)=>d(f??0)),m.on("error",()=>d(1))}),g=V.toString("utf8"),k=G.toString("utf8").trim();if(h!==0){let d=k||`curl failed with exit code ${h}`;if(h===28&&t>0)throw Error(`Request timed out after ${t}ms: ${a.method} ${e}`);throw Error(d)}let c=g.lastIndexOf(l),w=c>-1?g.lastIndexOf(l,c-1):-1;if(w<0||c<0)throw Error("Failed to parse curl response status code.");let b=g.slice(w+l.length,c).trim(),p=Number(b),E=g.slice(0,w);if(!Number.isFinite(p)||p<=0)throw Error(`Invalid curl status code: ${b}`);return{status:p,ok:p>=200&&p<300,bodyText:E}},R=(e)=>{let a=Number(e);if(!Number.isFinite(a)||a<=0||Math.floor(a)!==a)return null;return a},ee=(e)=>{let a=[];if(!e)return a;let t=R(e.number);if(t!==null)a.push(t);let r=R(e.index);if(r!==null)a.push(r);let s=e.issue;if(s&&typeof s==="object"&&!Array.isArray(s)){let l=s,o=R(l.number);if(o!==null)a.push(o);let u=R(l.index);if(u!==null)a.push(u)}return a};function I(e){let a=[];if(Array.isArray(e)){for(let t of e){if(!t||typeof t!=="object"||Array.isArray(t))continue;let r=t,s=R(r.number);if(s!==null)a.push(s);let l=R(r.index);if(l!==null)a.push(l);a.push(...ee(r))}return[...new Set(a)]}if(e&&typeof e==="object"&&!Array.isArray(e)){let t=e;if(Array.isArray(t.dependencies))return I(t.dependencies);if(Array.isArray(t.blocks))return I(t.blocks);if(Array.isArray(t.issues))return I(t.issues);return ee(t)}return[]}var te=(e)=>{let a=e.trim().replace(/\/$/,"");return a.endsWith("/api/v1")?a:`${a}/api/v1`},Ke=(e,a,t,r)=>{return`${te(e)}/repos/${encodeURIComponent(a)}/${encodeURIComponent(t)}/issues/${r}/dependencies`};async function _(e,a,t,r,s=Be,l,o){let u=Ke(s,a,t,r),i={Accept:"application/json",...l?{Authorization:`token ${l}`}:{},...o?{"Content-Type":"application/json"}:{}},m=ae(),V=Qe(process.env.F0_GIT_HTTP_TRANSPORT),G=!1,h=0,g="",k="";if(V==="curl"){let c=await Je(u,{method:e,headers:i,...o?{body:JSON.stringify(o)}:{}},m);G=c.ok,h=c.status,k=c.bodyText}else{let c=await ze(u,{method:e,headers:i,body:o?JSON.stringify(o):void 0});G=c.ok,h=c.status,k=await c.text()}g=k;try{g=JSON.parse(k)}catch{}return{ok:G,status:h,body:g,mapping:{featurePath:["issue","dependencies"],mappedPath:["issue","dependencies"],method:e,query:[],headers:[],apiBase:te(s),swaggerPath:"/repos/{owner}/{repo}/issues/{index}/dependencies",mapped:!0},request:{url:u,method:e,headers:{Accept:"application/json",...o?{"Content-Type":"application/json"}:{}},query:[],body:o},response:{headers:{}}}}async function Xe(e,a,t,r,s,l,o,u){let i=await _("GET",e,a,t,s,l);if(!i.ok)throw Error(`Failed to load issue dependencies for #${t}: status=${i.status} url=${i.request.url}`);let m=I(i.body),V=[...new Set(r.filter((p)=>p>0))],G=new Set(m),h=new Set(V),g=V.filter((p)=>!G.has(p)),k=m.filter((p)=>!h.has(p)),c=V.filter((p)=>G.has(p)).length;if(u)if(g.length>0||k.length>0)u(`Issue #${t}: dependency sync [add=${g.join(",")||"none"}, remove=${k.join(",")||"none"}]`);else u(`Issue #${t}: dependency sync already correct`);let w=0,b=0;if(!o){for(let y of k){let v=await _("DELETE",e,a,t,s,l,{index:y,owner:e,repo:a});if(!v.ok)throw Error(`Failed to remove dependency ${y} from issue #${t}: status=${v.status} url=${v.request.url}`);b+=1}for(let y of g){let v=await _("POST",e,a,t,s,l,{index:y,owner:e,repo:a});if(!v.ok)throw Error(`Failed to add dependency ${y} to issue #${t}: status=${v.status} url=${v.request.url}`);w+=1}let p=await _("GET",e,a,t,s,l);if(!p.ok)throw Error(`Failed to verify dependencies for issue #${t}: status=${p.status} url=${p.request.url}`);let E=I(p.body),d=new Set(E),f=V.filter((y)=>!d.has(y));if(f.length>0)throw Error(`Dependency sync mismatch for issue #${t}. Missing dependencies: ${f.join(", ")}`)}return{added:w,removed:b,unchanged:c}}import D from"fs";import A from"path";function Ye(e){try{if(e.startsWith("http://")||e.startsWith("https://")||e.startsWith("ssh://")){let t=new URL(e).pathname.split("/").filter(Boolean);if(t.length>=2){let r=t[t.length-2],l=t[t.length-1].replace(/\.git$/,"");return{owner:r,repo:l}}}if(e.startsWith("git@")){let a=e.split(":",2);if(a.length===2){let t=a[1].split("/").filter(Boolean);if(t.length>=2){let r=t[t.length-2],s=t[t.length-1].replace(/\.git$/,"");return{owner:r,repo:s}}}}}catch{return null}return null}function Ze(e){let a="";try{a=D.readFileSync(e,"utf8")}catch{return null}for(let t of a.split(/\r?\n/)){let r=t.trim();if(!r.startsWith("url"))continue;let s=r.match(/^url\s*=\s*(.+?)\s*$/);if(!s)continue;let l=Ye(s[1].trim());if(l)return l}return null}function ea(e){let a="";try{a=D.readFileSync(e,"utf8")}catch{return null}let r=a.trim().match(/^gitdir:\s*(.+)$/i);if(!r)return null;let s=r[1].trim();if(!s)return null;if(A.isAbsolute(s))return s;let l=A.dirname(e);while(!0){let o=A.resolve(l,s);try{if(D.statSync(o).isDirectory())return o}catch{}let u=A.dirname(l);if(u===l)break;l=u}return A.resolve(A.dirname(e),s)}function aa(e){let a;try{a=D.statSync(e)}catch{return null}if(a.isDirectory())return A.join(e,"config");if(a.isFile()){let t=ea(e);if(!t)return null;return A.join(t,"config")}return null}function ta(e){let a=[A.join(e,"code",".git"),A.join(e,".git")];for(let t of a){let r=aa(t);if(!r)continue;let s=Ze(r);if(s)return s}return null}export{Xe as syncIssueDependencies,ta as resolveProjectRepoIdentity,Ae as mapGitServiceFeature,qe as gitServiceApi,F as getGitPlatformConfig,I as extractDependencyIssueNumbers,ne as createRemoteGitApiClient,Y as createGitServiceApi,$ as createGitPlatformAdapter,_ as callIssueDependenciesApi,x as buildGitApiMockResponse,L as RemoteGitApiClient,O as GiteaPlatformAdapter,q as GIT_API_VERSION};
|