fullcourtdefense-cli 1.7.17 → 1.7.19
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/dist/commands/agentCi.d.ts +13 -0
- package/dist/commands/agentCi.js +311 -0
- package/dist/index.js +24 -0
- package/dist/version.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BotGuardConfig } from '../config';
|
|
2
|
+
export interface AgentCiArgs {
|
|
3
|
+
failOn?: string;
|
|
4
|
+
format?: string;
|
|
5
|
+
upload?: string;
|
|
6
|
+
requireUpload?: string;
|
|
7
|
+
requireGateway?: string;
|
|
8
|
+
requireApprovalFor?: string;
|
|
9
|
+
extraPath?: string;
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
apiUrl?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function agentCiCommand(args: AgentCiArgs, config: BotGuardConfig): Promise<void>;
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.agentCiCommand = agentCiCommand;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const config_1 = require("../config");
|
|
41
|
+
const discoverPaths_1 = require("./discoverPaths");
|
|
42
|
+
const discoverAgentFiles_1 = require("./discoverAgentFiles");
|
|
43
|
+
const discoverSecrets_1 = require("./discoverSecrets");
|
|
44
|
+
const discover_1 = require("./discover");
|
|
45
|
+
const SEVERITY_RANK = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
46
|
+
function stableId(parts) {
|
|
47
|
+
return crypto.createHash('sha256').update(parts.join('|')).digest('hex').slice(0, 16);
|
|
48
|
+
}
|
|
49
|
+
function parseJsonFile(filePath) {
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function parseTomlMcpServers(content) {
|
|
58
|
+
const servers = {};
|
|
59
|
+
const lines = content.split(/\r?\n/);
|
|
60
|
+
let current = null;
|
|
61
|
+
for (const raw of lines) {
|
|
62
|
+
const line = raw.trim();
|
|
63
|
+
const section = line.match(/^\[mcp_servers\.([^\]]+)\]$/);
|
|
64
|
+
if (section) {
|
|
65
|
+
current = section[1].replace(/^["']|["']$/g, '');
|
|
66
|
+
servers[current] = {};
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (!current || !line || line.startsWith('#'))
|
|
70
|
+
continue;
|
|
71
|
+
const match = line.match(/^([A-Za-z0-9_-]+)\s*=\s*(.+)$/);
|
|
72
|
+
if (!match)
|
|
73
|
+
continue;
|
|
74
|
+
const key = match[1];
|
|
75
|
+
const rawValue = match[2].trim().replace(/,$/, '');
|
|
76
|
+
if (rawValue.startsWith('[')) {
|
|
77
|
+
servers[current][key] = rawValue
|
|
78
|
+
.replace(/^\[|\]$/g, '')
|
|
79
|
+
.split(',')
|
|
80
|
+
.map(part => part.trim().replace(/^["']|["']$/g, ''))
|
|
81
|
+
.filter(Boolean);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
servers[current][key] = rawValue.replace(/^["']|["']$/g, '');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return servers;
|
|
88
|
+
}
|
|
89
|
+
function extractServerMap(parsed) {
|
|
90
|
+
if (!parsed || typeof parsed !== 'object')
|
|
91
|
+
return {};
|
|
92
|
+
if (parsed.mcpServers && typeof parsed.mcpServers === 'object')
|
|
93
|
+
return parsed.mcpServers;
|
|
94
|
+
if (parsed.servers && typeof parsed.servers === 'object')
|
|
95
|
+
return parsed.servers;
|
|
96
|
+
if (parsed.mcp?.servers && typeof parsed.mcp.servers === 'object')
|
|
97
|
+
return parsed.mcp.servers;
|
|
98
|
+
if (parsed['mcp.servers'] && typeof parsed['mcp.servers'] === 'object')
|
|
99
|
+
return parsed['mcp.servers'];
|
|
100
|
+
return {};
|
|
101
|
+
}
|
|
102
|
+
function riskSignalsForServer(name, server) {
|
|
103
|
+
const text = [
|
|
104
|
+
name,
|
|
105
|
+
server?.command,
|
|
106
|
+
...(Array.isArray(server?.args) ? server.args : []),
|
|
107
|
+
server?.url,
|
|
108
|
+
].filter(Boolean).join(' ').toLowerCase();
|
|
109
|
+
const signals = [
|
|
110
|
+
[/\b(shell|exec|command|terminal|powershell|bash|cmd\.exe)\b/, 'shell'],
|
|
111
|
+
[/\b(file|filesystem|readfile|writefile|directory|path)\b/, 'filesystem'],
|
|
112
|
+
[/\b(database|postgres|mysql|mongo|sql|db)\b/, 'database'],
|
|
113
|
+
[/\b(secret|token|key|password|credential|env)\b/, 'secrets'],
|
|
114
|
+
[/\b(payment|wire|transfer|bank|iban|invoice|billing)\b/, 'payment'],
|
|
115
|
+
[/\b(customer|user|pii|ssn|email|phone|record)\b/, 'pii'],
|
|
116
|
+
[/\b(browser|web|http|fetch|request|webhook)\b/, 'network'],
|
|
117
|
+
[/\b(delete|remove|destroy|drop|wipe|purge|write|update|create)\b/, 'write'],
|
|
118
|
+
];
|
|
119
|
+
return signals.filter(([re]) => re.test(text)).map(([, signal]) => signal);
|
|
120
|
+
}
|
|
121
|
+
function discoverMcpServers(cwd, extraPath) {
|
|
122
|
+
const out = [];
|
|
123
|
+
for (const candidate of (0, discoverPaths_1.discoverScanTargets)(cwd, extraPath)) {
|
|
124
|
+
if (!fs.existsSync(candidate.path))
|
|
125
|
+
continue;
|
|
126
|
+
const isToml = candidate.path.endsWith('.toml');
|
|
127
|
+
const parsed = isToml
|
|
128
|
+
? parseTomlMcpServers(fs.readFileSync(candidate.path, 'utf8'))
|
|
129
|
+
: parseJsonFile(candidate.path);
|
|
130
|
+
const map = extractServerMap(parsed);
|
|
131
|
+
for (const [name, server] of Object.entries(map)) {
|
|
132
|
+
const cfg = server;
|
|
133
|
+
const command = typeof cfg.command === 'string' ? cfg.command : undefined;
|
|
134
|
+
const args = Array.isArray(cfg.args) ? cfg.args.map(String) : [];
|
|
135
|
+
const url = typeof cfg.url === 'string' ? cfg.url : typeof cfg.endpoint === 'string' ? cfg.endpoint : undefined;
|
|
136
|
+
const targetText = [command, ...args, url].filter(Boolean).join(' ');
|
|
137
|
+
const protectedGateway = /fullcourtdefense|agentguard|mcp-gateway|5066|fcd/i.test(targetText);
|
|
138
|
+
out.push({
|
|
139
|
+
name,
|
|
140
|
+
source: candidate.source,
|
|
141
|
+
filePath: candidate.path,
|
|
142
|
+
command,
|
|
143
|
+
args,
|
|
144
|
+
url,
|
|
145
|
+
direct: !protectedGateway,
|
|
146
|
+
protectedGateway,
|
|
147
|
+
riskSignals: riskSignalsForServer(name, cfg),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
function parseRequiredControls(value) {
|
|
154
|
+
return (value || 'payment,delete,shell,secrets')
|
|
155
|
+
.split(',')
|
|
156
|
+
.map(part => part.trim().toLowerCase())
|
|
157
|
+
.filter(Boolean);
|
|
158
|
+
}
|
|
159
|
+
function finding(input) {
|
|
160
|
+
return { ...input, id: stableId([input.category, input.title, input.filePath || '', input.detail]) };
|
|
161
|
+
}
|
|
162
|
+
function evaluateAgentGate(args) {
|
|
163
|
+
const cwd = process.cwd();
|
|
164
|
+
const mcpServers = discoverMcpServers(cwd, args.extraPath);
|
|
165
|
+
const agentFiles = (0, discoverAgentFiles_1.scanAgentFiles)({ cwd });
|
|
166
|
+
const secrets = (0, discoverSecrets_1.scanSecrets)({ cwd, maxEnvDepth: 3 });
|
|
167
|
+
const requireGateway = args.requireGateway !== 'false';
|
|
168
|
+
const requiredControls = parseRequiredControls(args.requireApprovalFor);
|
|
169
|
+
const findings = [];
|
|
170
|
+
for (const server of mcpServers) {
|
|
171
|
+
if (requireGateway && server.direct && server.riskSignals.length > 0) {
|
|
172
|
+
findings.push(finding({
|
|
173
|
+
severity: server.riskSignals.includes('payment') || server.riskSignals.includes('shell') || server.riskSignals.includes('secrets') ? 'critical' : 'high',
|
|
174
|
+
category: 'mcp',
|
|
175
|
+
title: `Unprotected MCP server: ${server.name}`,
|
|
176
|
+
detail: `${server.source} exposes ${server.riskSignals.join(', ')} without Full Court Defense gateway wrapping.`,
|
|
177
|
+
filePath: server.filePath,
|
|
178
|
+
remediation: 'Wrap this MCP server with fullcourtdefense protect-all or install-mcp-gateway before merging.',
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
const missingControls = server.riskSignals.filter(signal => requiredControls.includes(signal));
|
|
182
|
+
if (missingControls.length > 0 && server.direct) {
|
|
183
|
+
findings.push(finding({
|
|
184
|
+
severity: 'high',
|
|
185
|
+
category: 'policy',
|
|
186
|
+
title: `Missing approval policy evidence for ${server.name}`,
|
|
187
|
+
detail: `Risky tool signals need approval/block policy before merge: ${missingControls.join(', ')}.`,
|
|
188
|
+
filePath: server.filePath,
|
|
189
|
+
remediation: 'Add an AgentGuard action policy requiring approval/block for this tool class, then route through the gateway.',
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
for (const file of agentFiles.filter(item => item.riskTags.length > 0)) {
|
|
194
|
+
findings.push(finding({
|
|
195
|
+
severity: file.riskTags.includes('allows_shell') || file.riskTags.includes('broad_filesystem') ? 'high' : 'medium',
|
|
196
|
+
category: 'agent-file',
|
|
197
|
+
title: `Risky agent instruction: ${file.title}`,
|
|
198
|
+
detail: `${file.filePath} contains agent risk tags: ${file.riskTags.join(', ')}.`,
|
|
199
|
+
filePath: file.filePath,
|
|
200
|
+
remediation: 'Review the instruction/rule and add explicit least-privilege boundaries.',
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
for (const secret of secrets.findings.filter(item => item.severity === 'critical' || item.severity === 'high')) {
|
|
204
|
+
findings.push(finding({
|
|
205
|
+
severity: secret.severity === 'critical' ? 'critical' : 'high',
|
|
206
|
+
category: 'secret',
|
|
207
|
+
title: secret.title,
|
|
208
|
+
detail: secret.detail,
|
|
209
|
+
filePath: secret.filePath,
|
|
210
|
+
remediation: secret.remediation,
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
let score = 100;
|
|
214
|
+
for (const item of findings) {
|
|
215
|
+
score -= item.severity === 'critical' ? 25 : item.severity === 'high' ? 12 : item.severity === 'medium' ? 5 : 2;
|
|
216
|
+
}
|
|
217
|
+
return { findings: findings.sort((a, b) => SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity]), score: Math.max(0, score), mcpServers };
|
|
218
|
+
}
|
|
219
|
+
function shouldFail(findings, failOn) {
|
|
220
|
+
return findings.some(item => SEVERITY_RANK[item.severity] >= SEVERITY_RANK[failOn]);
|
|
221
|
+
}
|
|
222
|
+
function toSarif(findings) {
|
|
223
|
+
return {
|
|
224
|
+
version: '2.1.0',
|
|
225
|
+
$schema: 'https://json.schemastore.org/sarif-2.1.0.json',
|
|
226
|
+
runs: [{
|
|
227
|
+
tool: {
|
|
228
|
+
driver: {
|
|
229
|
+
name: 'Full Court Defense Agent CI Gate',
|
|
230
|
+
informationUri: 'https://fullcourtdefense.ai',
|
|
231
|
+
rules: findings.map(item => ({
|
|
232
|
+
id: item.id,
|
|
233
|
+
name: item.title,
|
|
234
|
+
shortDescription: { text: item.title },
|
|
235
|
+
fullDescription: { text: item.detail },
|
|
236
|
+
help: { text: item.remediation },
|
|
237
|
+
defaultConfiguration: {
|
|
238
|
+
level: item.severity === 'critical' || item.severity === 'high' ? 'error' : item.severity === 'medium' ? 'warning' : 'note',
|
|
239
|
+
},
|
|
240
|
+
})),
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
results: findings.map(item => ({
|
|
244
|
+
ruleId: item.id,
|
|
245
|
+
level: item.severity === 'critical' || item.severity === 'high' ? 'error' : item.severity === 'medium' ? 'warning' : 'note',
|
|
246
|
+
message: { text: `${item.title}: ${item.detail}` },
|
|
247
|
+
locations: item.filePath ? [{
|
|
248
|
+
physicalLocation: {
|
|
249
|
+
artifactLocation: { uri: path.relative(process.cwd(), item.filePath).replace(/\\/g, '/') },
|
|
250
|
+
region: { startLine: 1 },
|
|
251
|
+
},
|
|
252
|
+
}] : [],
|
|
253
|
+
})),
|
|
254
|
+
}],
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function printSummary(report, failed, failOn) {
|
|
258
|
+
console.log(`Agent CI Gate: ${failed ? 'FAIL' : 'PASS'}`);
|
|
259
|
+
console.log(`Score: ${report.score}/100`);
|
|
260
|
+
console.log(`MCP servers: ${report.mcpServers.length}`);
|
|
261
|
+
console.log(`Findings: ${report.findings.length} (fail-on: ${failOn})`);
|
|
262
|
+
for (const item of report.findings.slice(0, 20)) {
|
|
263
|
+
console.log(`- [${item.severity.toUpperCase()}] ${item.title}`);
|
|
264
|
+
console.log(` ${item.detail}`);
|
|
265
|
+
if (item.filePath)
|
|
266
|
+
console.log(` ${path.relative(process.cwd(), item.filePath)}`);
|
|
267
|
+
}
|
|
268
|
+
if (report.findings.length > 20)
|
|
269
|
+
console.log(`... and ${report.findings.length - 20} more findings`);
|
|
270
|
+
}
|
|
271
|
+
async function agentCiCommand(args, config) {
|
|
272
|
+
const failOn = (['critical', 'high', 'medium', 'low'].includes(String(args.failOn || '').toLowerCase())
|
|
273
|
+
? String(args.failOn).toLowerCase()
|
|
274
|
+
: 'high');
|
|
275
|
+
const format = (['summary', 'json', 'sarif'].includes(String(args.format || '').toLowerCase())
|
|
276
|
+
? String(args.format).toLowerCase()
|
|
277
|
+
: 'summary');
|
|
278
|
+
const report = evaluateAgentGate(args);
|
|
279
|
+
const failed = shouldFail(report.findings, failOn);
|
|
280
|
+
if (format === 'json') {
|
|
281
|
+
console.log(JSON.stringify({ ...report, failed, failOn }, null, 2));
|
|
282
|
+
}
|
|
283
|
+
else if (format === 'sarif') {
|
|
284
|
+
console.log(JSON.stringify(toSarif(report.findings), null, 2));
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
printSummary(report, failed, failOn);
|
|
288
|
+
}
|
|
289
|
+
const uploadRequested = args.upload === 'true' || args.requireUpload === 'true';
|
|
290
|
+
if (uploadRequested) {
|
|
291
|
+
const creds = (0, config_1.resolveCliCredentials)(config, { apiKey: args.apiKey, apiUrl: args.apiUrl });
|
|
292
|
+
if (creds.apiKey || (creds.shieldId && creds.shieldKey)) {
|
|
293
|
+
try {
|
|
294
|
+
await (0, discover_1.runDiscoverUpload)({ apiKey: args.apiKey, apiUrl: args.apiUrl, silent: true }, config);
|
|
295
|
+
console.error('AgentGuard evidence upload: uploaded to AI Fleet / discovery posture inventory.');
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
console.error(`AgentGuard evidence upload: failed (${error instanceof Error ? error.message : String(error)})`);
|
|
299
|
+
if (args.requireUpload === 'true')
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
console.error('AgentGuard evidence upload: missing credentials. Run fullcourtdefense login or pass FULLCOURTDEFENSE_API_KEY.');
|
|
305
|
+
if (args.requireUpload === 'true')
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (failed)
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ const configure_1 = require("./commands/configure");
|
|
|
43
43
|
const login_1 = require("./commands/login");
|
|
44
44
|
const flushSpool_1 = require("./commands/flushSpool");
|
|
45
45
|
const discover_1 = require("./commands/discover");
|
|
46
|
+
const agentCi_1 = require("./commands/agentCi");
|
|
46
47
|
const hook_1 = require("./commands/hook");
|
|
47
48
|
const installCursorHook_1 = require("./commands/installCursorHook");
|
|
48
49
|
const mcpGateway_1 = require("./commands/mcpGateway");
|
|
@@ -125,6 +126,8 @@ function printHelp() {
|
|
|
125
126
|
discover Finds MCP servers, local secrets, agent rules/skills, and machine
|
|
126
127
|
blast radius on this laptop. Use --surface all --upload for AI Fleet.
|
|
127
128
|
Use --schedule logon to upload inventory/posture at machine login.
|
|
129
|
+
agent-ci CI/CD gate for agents and tools only. Fails builds on risky MCP,
|
|
130
|
+
agent instruction, gateway, policy, or secret drift. Not a bot scan.
|
|
128
131
|
install-cursor-hook
|
|
129
132
|
Installs a Cursor hook so EVERY agent action on this machine is
|
|
130
133
|
checked against your org's Action Policies — in any repo/folder.
|
|
@@ -218,6 +221,8 @@ function printHelp() {
|
|
|
218
221
|
\x1b[1mRecommended Commands:\x1b[0m
|
|
219
222
|
fullcourtdefense doctor
|
|
220
223
|
fullcourtdefense configure
|
|
224
|
+
fullcourtdefense agent-ci --fail-on high --require-gateway --format summary
|
|
225
|
+
fullcourtdefense agent-ci --fail-on high --format sarif --upload
|
|
221
226
|
fullcourtdefense scan --local
|
|
222
227
|
fullcourtdefense scan --local --type mcp --mcp-command node --mcp-args ./server.js --mcp-tool all --mode full --format report
|
|
223
228
|
fullcourtdefense scan --local --type mcp --mcp-url https://internal.company.com/mcp --mcp-auth-type bearer --mcp-token TOKEN --mcp-tool all --mode full --format report
|
|
@@ -256,6 +261,10 @@ function printHelp() {
|
|
|
256
261
|
--rag-url <url> Live RAG HTTP endpoint to scan
|
|
257
262
|
--shield-id <id> Shield ID for local outbound Shield verdicts
|
|
258
263
|
--shield-key <key> Optional Shield key for locked Shields
|
|
264
|
+
--fail-on <severity> agent-ci fail threshold: critical, high, medium, low
|
|
265
|
+
--require-gateway agent-ci requires risky MCP servers to use FCD gateway
|
|
266
|
+
--require-approval-for agent-ci risky controls list, e.g. payment,delete,shell,secrets
|
|
267
|
+
--require-upload agent-ci fails if evidence cannot upload to AgentGuard UI
|
|
259
268
|
--method <GET|POST> Local endpoint method
|
|
260
269
|
--request-format <fmt> Local endpoint request format: custom or openai
|
|
261
270
|
--auth-type <type> none, bearer, basic, api-key
|
|
@@ -489,6 +498,21 @@ async function main() {
|
|
|
489
498
|
await (0, discover_1.discoverCommand)(args, config);
|
|
490
499
|
break;
|
|
491
500
|
}
|
|
501
|
+
case 'agent-ci': {
|
|
502
|
+
const args = {
|
|
503
|
+
failOn: flags['fail-on'],
|
|
504
|
+
format: flags.format,
|
|
505
|
+
upload: flags.upload,
|
|
506
|
+
requireUpload: flags['require-upload'],
|
|
507
|
+
requireGateway: flags['require-gateway'],
|
|
508
|
+
requireApprovalFor: flags['require-approval-for'],
|
|
509
|
+
extraPath: flags.path,
|
|
510
|
+
apiKey: flags['api-key'],
|
|
511
|
+
apiUrl: flags['api-url'],
|
|
512
|
+
};
|
|
513
|
+
await (0, agentCi_1.agentCiCommand)(args, config);
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
492
516
|
case 'install-cursor-hook': {
|
|
493
517
|
const args = {
|
|
494
518
|
project: flags.project,
|
package/dist/version.json
CHANGED