@agentteams/cli 0.1.97 → 0.1.99
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/.eslintcache +1 -1
- package/README.md +27 -11
- package/dist/api/sentry.d.ts +7 -0
- package/dist/api/sentry.d.ts.map +1 -0
- package/dist/api/sentry.js +18 -0
- package/dist/api/sentry.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +15 -4
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/coaction.d.ts.map +1 -1
- package/dist/commands/coaction.js +6 -21
- package/dist/commands/coaction.js.map +1 -1
- package/dist/commands/codeReview.d.ts.map +1 -1
- package/dist/commands/codeReview.js +4 -5
- package/dist/commands/codeReview.js.map +1 -1
- package/dist/commands/document.d.ts +0 -1
- package/dist/commands/document.d.ts.map +1 -1
- package/dist/commands/document.js +1 -1
- package/dist/commands/document.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +6 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +42 -75
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/postmortem.d.ts.map +1 -1
- package/dist/commands/postmortem.js +1 -5
- package/dist/commands/postmortem.js.map +1 -1
- package/dist/commands/report.d.ts.map +1 -1
- package/dist/commands/report.js +7 -9
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/sentry.d.ts +2 -0
- package/dist/commands/sentry.d.ts.map +1 -0
- package/dist/commands/sentry.js +26 -0
- package/dist/commands/sentry.js.map +1 -0
- package/dist/commands/task.js +2 -2
- package/dist/commands/task.js.map +1 -1
- package/dist/index.js +3 -1350
- package/dist/index.js.map +1 -1
- package/dist/mcp/context.js +1 -1
- package/dist/mcp/context.js.map +1 -1
- package/dist/mcp-registration/clients.d.ts.map +1 -1
- package/dist/mcp-registration/clients.js +92 -0
- package/dist/mcp-registration/clients.js.map +1 -1
- package/dist/mcp-registration/detect.d.ts +1 -0
- package/dist/mcp-registration/detect.d.ts.map +1 -1
- package/dist/mcp-registration/detect.js +25 -2
- package/dist/mcp-registration/detect.js.map +1 -1
- package/dist/mcp-registration/index.d.ts +2 -2
- package/dist/mcp-registration/index.d.ts.map +1 -1
- package/dist/mcp-registration/index.js +4 -0
- package/dist/mcp-registration/index.js.map +1 -1
- package/dist/mcp-registration/install.d.ts +2 -0
- package/dist/mcp-registration/install.d.ts.map +1 -1
- package/dist/mcp-registration/install.js +22 -2
- package/dist/mcp-registration/install.js.map +1 -1
- package/dist/mcp-registration/types.d.ts +8 -1
- package/dist/mcp-registration/types.d.ts.map +1 -1
- package/dist/mcp-registration/types.js +1 -0
- package/dist/mcp-registration/types.js.map +1 -1
- package/dist/program/agentConfig.d.ts +3 -0
- package/dist/program/agentConfig.d.ts.map +1 -0
- package/dist/program/agentConfig.js +14 -0
- package/dist/program/agentConfig.js.map +1 -0
- package/dist/program/attachment.d.ts +3 -0
- package/dist/program/attachment.d.ts.map +1 -0
- package/dist/program/attachment.js +17 -0
- package/dist/program/attachment.js.map +1 -0
- package/dist/program/auth.d.ts +3 -0
- package/dist/program/auth.d.ts.map +1 -0
- package/dist/program/auth.js +39 -0
- package/dist/program/auth.js.map +1 -0
- package/dist/program/changeSet.d.ts +4 -0
- package/dist/program/changeSet.d.ts.map +1 -0
- package/dist/program/changeSet.js +53 -0
- package/dist/program/changeSet.js.map +1 -0
- package/dist/program/coaction.d.ts +7 -0
- package/dist/program/coaction.d.ts.map +1 -0
- package/dist/program/coaction.js +81 -0
- package/dist/program/coaction.js.map +1 -0
- package/dist/program/codeReview.d.ts +4 -0
- package/dist/program/codeReview.d.ts.map +1 -0
- package/dist/program/codeReview.js +101 -0
- package/dist/program/codeReview.js.map +1 -0
- package/dist/program/comment.d.ts +4 -0
- package/dist/program/comment.d.ts.map +1 -0
- package/dist/program/comment.js +50 -0
- package/dist/program/comment.js.map +1 -0
- package/dist/program/config.d.ts +3 -0
- package/dist/program/config.d.ts.map +1 -0
- package/dist/program/config.js +9 -0
- package/dist/program/config.js.map +1 -0
- package/dist/program/convention.d.ts +4 -0
- package/dist/program/convention.d.ts.map +1 -0
- package/dist/program/convention.js +37 -0
- package/dist/program/convention.js.map +1 -0
- package/dist/program/dependency.d.ts +3 -0
- package/dist/program/dependency.d.ts.map +1 -0
- package/dist/program/dependency.js +15 -0
- package/dist/program/dependency.js.map +1 -0
- package/dist/program/doctor.d.ts +6 -0
- package/dist/program/doctor.d.ts.map +1 -0
- package/dist/program/doctor.js +31 -0
- package/dist/program/doctor.js.map +1 -0
- package/dist/program/document.d.ts +7 -0
- package/dist/program/document.d.ts.map +1 -0
- package/dist/program/document.js +87 -0
- package/dist/program/document.js.map +1 -0
- package/dist/program/feedback.d.ts +3 -0
- package/dist/program/feedback.d.ts.map +1 -0
- package/dist/program/feedback.js +10 -0
- package/dist/program/feedback.js.map +1 -0
- package/dist/program/index.d.ts +3 -0
- package/dist/program/index.d.ts.map +1 -0
- package/dist/program/index.js +68 -0
- package/dist/program/index.js.map +1 -0
- package/dist/program/init.d.ts +6 -0
- package/dist/program/init.d.ts.map +1 -0
- package/dist/program/init.js +50 -0
- package/dist/program/init.js.map +1 -0
- package/dist/program/linear.d.ts +3 -0
- package/dist/program/linear.d.ts.map +1 -0
- package/dist/program/linear.js +25 -0
- package/dist/program/linear.js.map +1 -0
- package/dist/program/mcp.d.ts +6 -0
- package/dist/program/mcp.d.ts.map +1 -0
- package/dist/program/mcp.js +95 -0
- package/dist/program/mcp.js.map +1 -0
- package/dist/program/options/completionReport.d.ts +5 -0
- package/dist/program/options/completionReport.d.ts.map +1 -0
- package/dist/program/options/completionReport.js +19 -0
- package/dist/program/options/completionReport.js.map +1 -0
- package/dist/program/options/connection.d.ts +3 -0
- package/dist/program/options/connection.d.ts.map +1 -0
- package/dist/program/options/connection.js +8 -0
- package/dist/program/options/connection.js.map +1 -0
- package/dist/program/options/output.d.ts +3 -0
- package/dist/program/options/output.d.ts.map +1 -0
- package/dist/program/options/output.js +6 -0
- package/dist/program/options/output.js.map +1 -0
- package/dist/program/options/pagination.d.ts +3 -0
- package/dist/program/options/pagination.d.ts.map +1 -0
- package/dist/program/options/pagination.js +6 -0
- package/dist/program/options/pagination.js.map +1 -0
- package/dist/program/options/resource.d.ts +6 -0
- package/dist/program/options/resource.d.ts.map +1 -0
- package/dist/program/options/resource.js +29 -0
- package/dist/program/options/resource.js.map +1 -0
- package/dist/program/plan.d.ts +7 -0
- package/dist/program/plan.d.ts.map +1 -0
- package/dist/program/plan.js +138 -0
- package/dist/program/plan.js.map +1 -0
- package/dist/program/postmortem.d.ts +4 -0
- package/dist/program/postmortem.d.ts.map +1 -0
- package/dist/program/postmortem.js +27 -0
- package/dist/program/postmortem.js.map +1 -0
- package/dist/program/report.d.ts +4 -0
- package/dist/program/report.d.ts.map +1 -0
- package/dist/program/report.js +39 -0
- package/dist/program/report.js.map +1 -0
- package/dist/program/resolve.d.ts +6 -0
- package/dist/program/resolve.d.ts.map +1 -0
- package/dist/program/resolve.js +30 -0
- package/dist/program/resolve.js.map +1 -0
- package/dist/program/search.d.ts +6 -0
- package/dist/program/search.d.ts.map +1 -0
- package/dist/program/search.js +43 -0
- package/dist/program/search.js.map +1 -0
- package/dist/program/sentry.d.ts +3 -0
- package/dist/program/sentry.d.ts.map +1 -0
- package/dist/program/sentry.js +19 -0
- package/dist/program/sentry.js.map +1 -0
- package/dist/program/shared.d.ts +32 -0
- package/dist/program/shared.d.ts.map +1 -0
- package/dist/program/shared.js +96 -0
- package/dist/program/shared.js.map +1 -0
- package/dist/program/sync.d.ts +6 -0
- package/dist/program/sync.d.ts.map +1 -0
- package/dist/program/sync.js +35 -0
- package/dist/program/sync.js.map +1 -0
- package/dist/program/task.d.ts +3 -0
- package/dist/program/task.d.ts.map +1 -0
- package/dist/program/task.js +13 -0
- package/dist/program/task.js.map +1 -0
- package/dist/program/worktree.d.ts +3 -0
- package/dist/program/worktree.d.ts.map +1 -0
- package/dist/program/worktree.js +30 -0
- package/dist/program/worktree.js.map +1 -0
- package/dist/utils/agentIdentity.d.ts +43 -0
- package/dist/utils/agentIdentity.d.ts.map +1 -1
- package/dist/utils/agentIdentity.js +45 -0
- package/dist/utils/agentIdentity.js.map +1 -1
- package/dist/utils/apiContext.d.ts.map +1 -1
- package/dist/utils/apiContext.js +6 -1
- package/dist/utils/apiContext.js.map +1 -1
- package/dist/utils/apiKeyInput.d.ts +1 -3
- package/dist/utils/apiKeyInput.d.ts.map +1 -1
- package/dist/utils/apiKeyInput.js +1 -9
- package/dist/utils/apiKeyInput.js.map +1 -1
- package/dist/utils/apiOrigin.d.ts +43 -0
- package/dist/utils/apiOrigin.d.ts.map +1 -0
- package/dist/utils/apiOrigin.js +78 -0
- package/dist/utils/apiOrigin.js.map +1 -0
- package/dist/utils/config.d.ts +9 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -4
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/httpClient.d.ts.map +1 -1
- package/dist/utils/httpClient.js +50 -0
- package/dist/utils/httpClient.js.map +1 -1
- package/dist/utils/outputPolicy.d.ts +6 -7
- package/dist/utils/outputPolicy.d.ts.map +1 -1
- package/dist/utils/outputPolicy.js +0 -5
- package/dist/utils/outputPolicy.js.map +1 -1
- package/dist/utils/projectRootHash.d.ts +30 -0
- package/dist/utils/projectRootHash.d.ts.map +1 -0
- package/dist/utils/projectRootHash.js +43 -0
- package/dist/utils/projectRootHash.js.map +1 -0
- package/dist/utils/runnerTypes.d.ts +29 -0
- package/dist/utils/runnerTypes.d.ts.map +1 -0
- package/dist/utils/runnerTypes.js +40 -0
- package/dist/utils/runnerTypes.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,1357 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Command, Option } from 'commander';
|
|
6
|
-
import { executeCommand } from './commands/index.js';
|
|
7
|
-
import { formatOutput } from './utils/formatter.js';
|
|
8
|
-
import { formatAuthResultText } from './utils/authFormat.js';
|
|
9
|
-
import { handleError } from './utils/errors.js';
|
|
10
|
-
import { createSummaryLines, shouldPrintSummary } from './utils/outputPolicy.js';
|
|
11
|
-
import { printInitResult } from './utils/initOutput.js';
|
|
12
|
-
import { printDoctorResult, resolveDoctorExitCode } from './utils/doctorOutput.js';
|
|
13
|
-
import { executeValidatedInteractiveCommand, normalizeInteractiveFormat } from './utils/interactiveCommand.js';
|
|
14
|
-
import { startUpdateCheck, readCache, compareVersions, formatUpdateMessage } from './utils/updateCheck.js';
|
|
15
|
-
import { MCP_CLIENT_IDS } from './mcp-registration/types.js';
|
|
16
|
-
import { resolveApiKeyInput } from './utils/apiKeyInput.js';
|
|
3
|
+
import { createProgram } from './program/index.js';
|
|
4
|
+
import { compareVersions, formatUpdateMessage, readCache, startUpdateCheck } from './utils/updateCheck.js';
|
|
17
5
|
const require = createRequire(import.meta.url);
|
|
18
6
|
const pkg = require('../package.json');
|
|
19
|
-
const program =
|
|
20
|
-
function createApiKeyOption() {
|
|
21
|
-
return new Option('--api-key <key>', 'Deprecated: pass an API key in argv. Prefer AGENTTEAMS_API_KEY or --api-key-file.');
|
|
22
|
-
}
|
|
23
|
-
function createApiKeyFileOption() {
|
|
24
|
-
return new Option('--api-key-file <path>', 'Read the API key from a file, or use "-" to read stdin.');
|
|
25
|
-
}
|
|
26
|
-
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
27
|
-
try {
|
|
28
|
-
const commands = [];
|
|
29
|
-
for (let command = actionCommand; command; command = command.parent) {
|
|
30
|
-
commands.push(command);
|
|
31
|
-
}
|
|
32
|
-
const apiKeyCommand = commands.find((command) => command.opts().apiKey !== undefined);
|
|
33
|
-
const apiKeyFileCommand = commands.find((command) => command.opts().apiKeyFile !== undefined);
|
|
34
|
-
if (!apiKeyCommand && !apiKeyFileCommand)
|
|
35
|
-
return;
|
|
36
|
-
const apiKey = apiKeyCommand?.opts().apiKey;
|
|
37
|
-
const apiKeyFile = apiKeyFileCommand?.opts().apiKeyFile;
|
|
38
|
-
const resolved = resolveApiKeyInput({ apiKey, apiKeyFile });
|
|
39
|
-
(apiKeyFileCommand ?? apiKeyCommand ?? actionCommand).setOptionValue('apiKey', resolved);
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
console.error(handleError(error));
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
function normalizeFormat(format) {
|
|
47
|
-
if (format === undefined || format === null || format === '')
|
|
48
|
-
return 'json';
|
|
49
|
-
if (format === 'json')
|
|
50
|
-
return 'json';
|
|
51
|
-
throw new Error(`Unsupported output format: ${String(format)}. Only json is supported.`);
|
|
52
|
-
}
|
|
53
|
-
function writeOutputFile(outputFile, content) {
|
|
54
|
-
const resolvedPath = resolve(outputFile);
|
|
55
|
-
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
56
|
-
writeFileSync(resolvedPath, content, 'utf-8');
|
|
57
|
-
const bytes = Buffer.byteLength(content, 'utf-8');
|
|
58
|
-
return { resolvedPath, bytes };
|
|
59
|
-
}
|
|
60
|
-
function printCommandResult(params) {
|
|
61
|
-
const outputText = typeof params.result === 'string' ? params.result : formatOutput(params.result);
|
|
62
|
-
const summaryLines = createSummaryLines(params.result, {
|
|
63
|
-
resource: params.resource,
|
|
64
|
-
action: params.action,
|
|
65
|
-
});
|
|
66
|
-
if (typeof params.outputFile === 'string' && params.outputFile.trim().length > 0) {
|
|
67
|
-
const { resolvedPath, bytes } = writeOutputFile(params.outputFile, outputText);
|
|
68
|
-
console.log(`Saved output to ${resolvedPath} (${bytes} bytes).`);
|
|
69
|
-
for (const line of summaryLines) {
|
|
70
|
-
console.log(line);
|
|
71
|
-
}
|
|
72
|
-
if (params.verbose) {
|
|
73
|
-
console.log(outputText);
|
|
74
|
-
}
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (shouldPrintSummary({
|
|
78
|
-
resource: params.resource,
|
|
79
|
-
action: params.action,
|
|
80
|
-
format: params.format,
|
|
81
|
-
formatExplicit: params.formatExplicit,
|
|
82
|
-
outputFile: params.outputFile,
|
|
83
|
-
verbose: params.verbose,
|
|
84
|
-
})) {
|
|
85
|
-
for (const line of summaryLines) {
|
|
86
|
-
console.log(line);
|
|
87
|
-
}
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
console.log(outputText);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* One constant for both `init` and `auth login`.
|
|
94
|
-
*
|
|
95
|
-
* The flag has to read identically in both `--help` outputs: a user who learns it
|
|
96
|
-
* from one command types it at the other. Sharing the string makes that structural
|
|
97
|
-
* rather than something a reviewer has to notice drifting.
|
|
98
|
-
*/
|
|
99
|
-
const DEVICE_AUTH_OPTION_DESCRIPTION = 'authorize with a short code on another device instead of a local browser callback (for SSH, containers, and other headless shells)';
|
|
100
|
-
const DEVICE_AUTH_SET_DEFAULT_DESCRIPTION = "with --device-auth: remember device-code login as this machine's default in ~/.agentteams/config.json";
|
|
101
|
-
const CONVENTION_HINT = `\nFor workflow rules and reporting guidelines, see: .agentteams/convention.md`;
|
|
102
|
-
program.name('agentteams').description('CLI tool for AgentTeams API').version(pkg.version);
|
|
103
|
-
program
|
|
104
|
-
.command('init')
|
|
105
|
-
.description('Initialize AgentTeams CLI via OAuth')
|
|
106
|
-
// No commander `.default()` on purpose: init has to tell "the user asked for
|
|
107
|
-
// this credential" apart from "nothing was typed". A default would fill
|
|
108
|
-
// `options.auth` on every run, and `detectInitExecutionContext` reads a
|
|
109
|
-
// present value as an explicit relink request — which would make the
|
|
110
|
-
// configured-project fast path unreachable from the real CLI. The absent case
|
|
111
|
-
// is defaulted in `executeInitCommandWithContext`.
|
|
112
|
-
.addOption(new Option('--auth <mode>', 'Credential to configure. `personal-token` (default) stores a rotating personal login outside the repository — in the OS credential store, or in a permission-protected file when that store is unavailable — and refreshes itself; `api-key` writes a legacy agent key into .agentteams/config.json, which expires 30 days after issue and must be reissued by hand.').choices(['api-key', 'personal-token']))
|
|
113
|
-
// Entry point files are no longer written for every AI client on every run.
|
|
114
|
-
// Without a TTY the selection now comes from what is actually configured in
|
|
115
|
-
// the folder (.claude/, .cursor/, …), and this option is how an automated
|
|
116
|
-
// caller states the set explicitly instead.
|
|
117
|
-
.option('--agent-files <list>', "Comma-separated agent entry point files to create (CLAUDE.md, AGENTS.md, GEMINI.md, .cursor/rules/agentteams.mdc), or 'none'. Defaults to the AI clients detected in this folder.")
|
|
118
|
-
.option('--agent-files-example', 'When a selected entry point file already exists, write a <name>-example file next to it instead of leaving it alone.', false)
|
|
119
|
-
.option('--install-worktree-hook', "Install the managed git post-checkout hook even if this repository has no linked worktrees yet. By default the hook is installed only when linked worktrees exist; 'agentteams doctor' can install it later.", false)
|
|
120
|
-
// Explicit opt-in only. There is deliberately no `--no-device-auth`: the default
|
|
121
|
-
// already is the browser callback, so the way to turn this off is not to pass it.
|
|
122
|
-
.option('--device-auth', DEVICE_AUTH_OPTION_DESCRIPTION, false)
|
|
123
|
-
.option('--set-default', DEVICE_AUTH_SET_DEFAULT_DESCRIPTION, false)
|
|
124
|
-
.option('--format <format>', 'Output format (json; defaults to human-readable view)')
|
|
125
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
126
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
127
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
128
|
-
.action(async (options) => {
|
|
129
|
-
try {
|
|
130
|
-
const result = await executeCommand('init', 'start', {
|
|
131
|
-
authMode: options.auth,
|
|
132
|
-
agentFiles: options.agentFiles,
|
|
133
|
-
agentFilesExample: options.agentFilesExample === true,
|
|
134
|
-
installWorktreeHook: options.installWorktreeHook === true,
|
|
135
|
-
deviceAuth: options.deviceAuth === true,
|
|
136
|
-
setDefault: options.setDefault === true,
|
|
137
|
-
});
|
|
138
|
-
const format = normalizeInteractiveFormat(options.format);
|
|
139
|
-
printInitResult(result, format);
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
console.error(handleError(error));
|
|
143
|
-
process.exit(1);
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
program
|
|
147
|
-
.command('auth')
|
|
148
|
-
.description('Manage the personal AgentTeams login used by default')
|
|
149
|
-
.argument('<action>', 'Action to perform (login, status, logout)')
|
|
150
|
-
.option('--api-url <url>', 'API server to authenticate against (defaults to the project config or env)')
|
|
151
|
-
.option('--local', 'logout only: clear the local credential without contacting the server (the token stays valid — revoke it in the web app)', false)
|
|
152
|
-
// Same flag name as `init` on purpose — one vocabulary for one behaviour.
|
|
153
|
-
// Same flag name and same wording as `init` — one vocabulary for one behaviour.
|
|
154
|
-
.option('--device-auth', DEVICE_AUTH_OPTION_DESCRIPTION, false)
|
|
155
|
-
.option('--set-default', DEVICE_AUTH_SET_DEFAULT_DESCRIPTION, false)
|
|
156
|
-
.option('--format <format>', 'Output format (json; defaults to human-readable text)')
|
|
157
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
158
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
159
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
160
|
-
.action(async (action, options) => {
|
|
161
|
-
try {
|
|
162
|
-
const result = await executeCommand('auth', action, {
|
|
163
|
-
apiUrl: options.apiUrl,
|
|
164
|
-
local: options.local === true,
|
|
165
|
-
deviceAuth: options.deviceAuth === true,
|
|
166
|
-
setDefault: options.setDefault === true,
|
|
167
|
-
});
|
|
168
|
-
// `auth` is read by a person, so text is the default; scripts that read the
|
|
169
|
-
// documented fields ask for JSON explicitly.
|
|
170
|
-
const wantsJson = options.format !== undefined;
|
|
171
|
-
printCommandResult({
|
|
172
|
-
result: wantsJson ? result : formatAuthResultText(action, result),
|
|
173
|
-
format: normalizeFormat(options.format),
|
|
174
|
-
outputFile: options.outputFile,
|
|
175
|
-
verbose: options.verbose,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
console.error(handleError(error));
|
|
180
|
-
process.exit(1);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
program
|
|
184
|
-
.command('doctor')
|
|
185
|
-
.description('Diagnose convention reachability and install the worktree bootstrap hook')
|
|
186
|
-
.option('--format <format>', 'Output format (json; defaults to human-readable view)')
|
|
187
|
-
// The doctor honors the same gate `init` does — a repository with no linked
|
|
188
|
-
// worktree keeps its shared .git/hooks untouched — so opting in needs a flag
|
|
189
|
-
// on this command too, not just on `init`.
|
|
190
|
-
.option('--install-worktree-hook', 'Install the managed git post-checkout hook even if this repository has no linked worktrees yet.', false)
|
|
191
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
192
|
-
.action(async (options) => {
|
|
193
|
-
try {
|
|
194
|
-
const { result, format } = await executeValidatedInteractiveCommand(options.format, async () => executeCommand('doctor', 'run', {
|
|
195
|
-
cwd: process.cwd(),
|
|
196
|
-
installWorktreeHook: options.installWorktreeHook === true,
|
|
197
|
-
}));
|
|
198
|
-
printDoctorResult(result, format);
|
|
199
|
-
// exitCode (not process.exit) lets stdout flush before termination.
|
|
200
|
-
process.exitCode = resolveDoctorExitCode(result);
|
|
201
|
-
}
|
|
202
|
-
catch (error) {
|
|
203
|
-
console.error(handleError(error));
|
|
204
|
-
process.exit(1);
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
program
|
|
208
|
-
.command('sync')
|
|
209
|
-
.description('Sync local convention files from API')
|
|
210
|
-
.option('--format <format>', 'Output format (json; defaults to human-readable view)')
|
|
211
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
212
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
213
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
214
|
-
.action(async (options) => {
|
|
215
|
-
try {
|
|
216
|
-
const result = await executeCommand('sync', 'download', {
|
|
217
|
-
cwd: process.cwd(),
|
|
218
|
-
});
|
|
219
|
-
const format = normalizeInteractiveFormat(options.format);
|
|
220
|
-
if (format === 'human' && !options.outputFile) {
|
|
221
|
-
console.log(typeof result === 'string' ? result : formatOutput(result));
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
printCommandResult({
|
|
225
|
-
result: format === 'json' && typeof result === 'string' ? { message: result } : result,
|
|
226
|
-
format: 'json',
|
|
227
|
-
outputFile: options.outputFile,
|
|
228
|
-
verbose: options.verbose,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
catch (error) {
|
|
232
|
-
console.error(handleError(error));
|
|
233
|
-
process.exit(1);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
program
|
|
237
|
-
.command('worktree')
|
|
238
|
-
.description('Report Orca worktree lifecycle events')
|
|
239
|
-
.argument('<action>', 'Action to perform (notify-created, notify-deleted)')
|
|
240
|
-
.option('--repository-id <id>', 'AgentTeams repository ID (optional when remote origin matches)')
|
|
241
|
-
.option('--local-key <key>', 'Opaque worktree identity (defaults to a Git-derived key)')
|
|
242
|
-
.option('--event-id <id>', 'Stable event ID for retries')
|
|
243
|
-
.option('--occurred-at <timestamp>', 'Event timestamp in ISO 8601 format')
|
|
244
|
-
.option('--after-removal', 'Send a deleted event only after the worktree path disappears', false)
|
|
245
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
246
|
-
.option('--quiet', 'Do not print a successful result', false)
|
|
247
|
-
.action(async (action, options) => {
|
|
248
|
-
try {
|
|
249
|
-
const result = await executeCommand('worktree', action, {
|
|
250
|
-
cwd: process.cwd(),
|
|
251
|
-
repositoryId: options.repositoryId,
|
|
252
|
-
localKey: options.localKey,
|
|
253
|
-
eventId: options.eventId,
|
|
254
|
-
occurredAt: options.occurredAt,
|
|
255
|
-
afterRemoval: options.afterRemoval,
|
|
256
|
-
});
|
|
257
|
-
if (!options.quiet) {
|
|
258
|
-
printCommandResult({ result, format: normalizeFormat(options.format), resource: 'worktree', action });
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
catch (error) {
|
|
262
|
-
console.error(handleError(error));
|
|
263
|
-
process.exit(1);
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
program
|
|
267
|
-
.command('plan')
|
|
268
|
-
.description('Manage plans')
|
|
269
|
-
.argument('<action>', 'Action to perform (list, get, show, create, update, delete, download, cleanup, start, finish, quick, status, set-status, upload-html, link-issue, unlink-issue, list-issues)')
|
|
270
|
-
.option('--id <id>', 'Plan ID')
|
|
271
|
-
.option('--title <title>', 'Plan title')
|
|
272
|
-
.option('--search <text>', 'Plan title/ID search keyword (list only)')
|
|
273
|
-
.option('--content <content>', 'Plan content (plain text or Tiptap JSON)')
|
|
274
|
-
.option('--interpret-escapes', 'Interpret \\n sequences in --content as newlines (create/update only)', false)
|
|
275
|
-
.option('--file <path>', 'Read plan content from a local file (create/update/upload-html)')
|
|
276
|
-
.option('--keep-temp', 'Keep the uploaded file under .agentteams/cli/temp/ instead of deleting it after upload', false)
|
|
277
|
-
.option('--stdin', 'Read plan HTML summary from stdin (upload-html only)', false)
|
|
278
|
-
.option('--html-file <path>', 'Read a legacy V1 plan HTML preview from a local file (optional for create/update; not displayed for V2 plans)')
|
|
279
|
-
.option('--html-stdin', 'Read a legacy V1 plan HTML preview from stdin (optional for create/update; not displayed for V2 plans)', false)
|
|
280
|
-
.option('--source-label <label>', 'Optional source label for uploaded plan HTML summary')
|
|
281
|
-
.option('--template <name>', 'Plan content template (refactor-minimal, quick-minimal, create only)')
|
|
282
|
-
.option('--status <status>', 'Plan status for list/update/set-status; ignored by create because new plans start as BACKLOG')
|
|
283
|
-
.option('--type <type>', 'Plan type (FEATURE, BUG_FIX, ISSUE, REFACTOR, CHORE)')
|
|
284
|
-
.option('--complexity <level>', 'Plan complexity (MINIMAL, STANDARD, FULL; required for create)')
|
|
285
|
-
.option('--complexity-reason <text>', 'Reason for changing complexity (update only; recorded as a MODIFICATION comment)')
|
|
286
|
-
.option('--priority <priority>', 'Plan priority (LOW, MEDIUM, HIGH)')
|
|
287
|
-
.option('--repository-remote-url <url>', 'Repository remote origin URL (create/report attach; defaults to git origin)')
|
|
288
|
-
.option('--assigned-to <id>', 'Agent config ID or name. Filters plan list; assigns the agent on start/quick when the credential carries none (defaults to $AGENTTEAMS_AGENT_NAME)')
|
|
289
|
-
.option('--task <text>', 'Task summary for plan start/finish')
|
|
290
|
-
.option('--report-title <title>', 'Completion report title (plan finish)')
|
|
291
|
-
.option('--report-file <path>', 'Read completion report content from a local file (plan finish)')
|
|
292
|
-
.option('--report-status <status>', 'Completion report status: COMPLETED, FAILED, PARTIAL (plan finish)')
|
|
293
|
-
.option('--quality-score <n>', 'Quality score 0-100 (plan finish)')
|
|
294
|
-
.option('--review-recommendation <value>', 'Code review recommendation: REQUIRED or NOT_NEEDED (plan finish)')
|
|
295
|
-
.option('--review-reason <text>', 'One-line reason for the review recommendation (plan finish)')
|
|
296
|
-
.option('--commit-hash <hash>', 'Git commit hash (plan finish, manual override)')
|
|
297
|
-
.option('--branch-name <name>', 'Git branch name (plan finish, manual override)')
|
|
298
|
-
.option('--files-modified <n>', 'Number of modified files (plan finish, manual override)')
|
|
299
|
-
.option('--lines-added <n>', 'Number of added lines (plan finish, manual override)')
|
|
300
|
-
.option('--lines-deleted <n>', 'Number of deleted lines (plan finish, manual override)')
|
|
301
|
-
.option('--duration-seconds <n>', 'Duration in seconds (plan finish, manual only)')
|
|
302
|
-
.option('--commit-start <hash>', 'Commit range start hash (plan finish, manual only)')
|
|
303
|
-
.option('--commit-end <hash>', 'Commit range end hash (plan finish, manual only)')
|
|
304
|
-
.option('--pull-request-id <id>', 'Pull request ID (plan finish, manual only)')
|
|
305
|
-
.option('--runner-type <type>', 'Runner type snapshot: CLAUDE_CODE, CODEX, ANTIGRAVITY, AMP, OPENCODE (plan start/finish)')
|
|
306
|
-
.option('--model <model>', 'Model ID snapshot (plan start/finish)')
|
|
307
|
-
.option('--fast', 'Request fast mode for the selected model when supported', false)
|
|
308
|
-
.option('--no-git', 'Disable git metrics auto-collection (plan finish)')
|
|
309
|
-
.option('--page <number>', 'Page number (list only)')
|
|
310
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
311
|
-
.option('--provider <provider>', 'External issue provider (GITHUB, GITLAB, LINEAR)')
|
|
312
|
-
.option('--external-id <id>', 'External issue ID')
|
|
313
|
-
.option('--external-url <url>', 'External issue URL')
|
|
314
|
-
.option('--issue-id <id>', 'PlanExternalIssue ID (for unlink-issue)')
|
|
315
|
-
.option('--metadata <json>', 'Provider metadata as JSON (e.g. {"owner":"org","repo":"name"})')
|
|
316
|
-
.option('--include-deps', 'Include dependencies in plan get/show output', false)
|
|
317
|
-
.option('--format <format>', 'Output format (json)')
|
|
318
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
319
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
320
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
321
|
-
.action(async (action, options) => {
|
|
322
|
-
try {
|
|
323
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
324
|
-
const result = await executeCommand('plan', action, {
|
|
325
|
-
id: options.id,
|
|
326
|
-
title: options.title,
|
|
327
|
-
search: options.search,
|
|
328
|
-
content: options.content,
|
|
329
|
-
interpretEscapes: options.interpretEscapes,
|
|
330
|
-
file: options.file,
|
|
331
|
-
stdin: options.stdin,
|
|
332
|
-
htmlFile: options.htmlFile,
|
|
333
|
-
htmlStdin: options.htmlStdin,
|
|
334
|
-
sourceLabel: options.sourceLabel,
|
|
335
|
-
template: options.template,
|
|
336
|
-
status: options.status,
|
|
337
|
-
type: options.type,
|
|
338
|
-
complexity: options.complexity,
|
|
339
|
-
complexityReason: options.complexityReason,
|
|
340
|
-
priority: options.priority,
|
|
341
|
-
repositoryRemoteUrl: options.repositoryRemoteUrl,
|
|
342
|
-
assignedTo: options.assignedTo,
|
|
343
|
-
task: options.task,
|
|
344
|
-
reportTitle: options.reportTitle,
|
|
345
|
-
reportFile: options.reportFile,
|
|
346
|
-
reportStatus: options.reportStatus,
|
|
347
|
-
qualityScore: options.qualityScore,
|
|
348
|
-
reviewRecommendation: options.reviewRecommendation,
|
|
349
|
-
reviewReason: options.reviewReason,
|
|
350
|
-
commitHash: options.commitHash,
|
|
351
|
-
branchName: options.branchName,
|
|
352
|
-
filesModified: options.filesModified,
|
|
353
|
-
linesAdded: options.linesAdded,
|
|
354
|
-
linesDeleted: options.linesDeleted,
|
|
355
|
-
durationSeconds: options.durationSeconds,
|
|
356
|
-
commitStart: options.commitStart,
|
|
357
|
-
commitEnd: options.commitEnd,
|
|
358
|
-
pullRequestId: options.pullRequestId,
|
|
359
|
-
git: options.git,
|
|
360
|
-
page: options.page,
|
|
361
|
-
pageSize: options.pageSize,
|
|
362
|
-
provider: options.provider,
|
|
363
|
-
externalId: options.externalId,
|
|
364
|
-
externalUrl: options.externalUrl,
|
|
365
|
-
issueId: options.issueId,
|
|
366
|
-
metadata: options.metadata,
|
|
367
|
-
includeDeps: options.includeDeps,
|
|
368
|
-
runnerType: options.runnerType,
|
|
369
|
-
model: options.model,
|
|
370
|
-
fast: options.fast,
|
|
371
|
-
format: normalizedFormat,
|
|
372
|
-
formatExplicit: typeof options.format === 'string',
|
|
373
|
-
});
|
|
374
|
-
printCommandResult({
|
|
375
|
-
result,
|
|
376
|
-
format: normalizedFormat,
|
|
377
|
-
outputFile: options.outputFile,
|
|
378
|
-
verbose: options.verbose,
|
|
379
|
-
resource: 'plan',
|
|
380
|
-
action,
|
|
381
|
-
formatExplicit: typeof options.format === 'string',
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
catch (error) {
|
|
385
|
-
console.error(handleError(error));
|
|
386
|
-
process.exit(1);
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
program
|
|
390
|
-
.command('resolve')
|
|
391
|
-
.description('Resolve an entity reference token to the right entity and fetch it')
|
|
392
|
-
.argument('<ref>', 'Reference token, e.g. "plan:agentteams_pln_<uuid>", "agentteams_doc_<uuid>", or a whole [label](type:id) link')
|
|
393
|
-
.option('--format <format>', 'Output format (json)')
|
|
394
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
395
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
396
|
-
.addHelpText('after', `\nReturns a "kind" that tells you what to do next:\n file read "filePath" (the entity body was downloaded)\n record use "record" (structured payload, already inline)\n localFile read "filePath" (the reference carried a local path)\n external open "url" or run "suggestedCommand" (gh/glab)\n${CONVENTION_HINT}`)
|
|
397
|
-
.action(async (ref, options) => {
|
|
398
|
-
try {
|
|
399
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
400
|
-
const result = await executeCommand('resolve', 'get', {
|
|
401
|
-
ref,
|
|
402
|
-
format: normalizedFormat,
|
|
403
|
-
formatExplicit: typeof options.format === 'string',
|
|
404
|
-
});
|
|
405
|
-
printCommandResult({
|
|
406
|
-
result,
|
|
407
|
-
format: normalizedFormat,
|
|
408
|
-
outputFile: options.outputFile,
|
|
409
|
-
verbose: options.verbose,
|
|
410
|
-
resource: 'resolve',
|
|
411
|
-
action: 'get',
|
|
412
|
-
formatExplicit: typeof options.format === 'string',
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
catch (error) {
|
|
416
|
-
console.error(handleError(error));
|
|
417
|
-
process.exit(1);
|
|
418
|
-
}
|
|
419
|
-
});
|
|
420
|
-
program
|
|
421
|
-
.command('task')
|
|
422
|
-
.description('Manage plan tasks')
|
|
423
|
-
.argument('<action>', 'Action to perform (get, start, finish)')
|
|
424
|
-
.option('--plan-id <id>', 'Plan ID (optional for get: bare task-id focus; required for start/finish)')
|
|
425
|
-
.option('--task-id <id>', 'Plan task ID')
|
|
426
|
-
.option('--status <status>', 'Task finish status: DONE, BLOCKED, or SKIPPED')
|
|
427
|
-
.option('--format <format>', 'Output format (json)')
|
|
428
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
429
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
430
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
431
|
-
.action(async (action, options) => {
|
|
432
|
-
try {
|
|
433
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
434
|
-
const result = await executeCommand('task', action, {
|
|
435
|
-
planId: options.planId,
|
|
436
|
-
taskId: options.taskId,
|
|
437
|
-
status: options.status,
|
|
438
|
-
format: normalizedFormat,
|
|
439
|
-
formatExplicit: typeof options.format === 'string',
|
|
440
|
-
});
|
|
441
|
-
printCommandResult({
|
|
442
|
-
result,
|
|
443
|
-
format: normalizedFormat,
|
|
444
|
-
outputFile: options.outputFile,
|
|
445
|
-
verbose: options.verbose,
|
|
446
|
-
resource: 'task',
|
|
447
|
-
action,
|
|
448
|
-
formatExplicit: typeof options.format === 'string',
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
catch (error) {
|
|
452
|
-
console.error(handleError(error));
|
|
453
|
-
process.exit(1);
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
program
|
|
457
|
-
.command('comment')
|
|
458
|
-
.description('Manage plan, finding, and task comments with 1-depth replies')
|
|
459
|
-
.argument('<action>', 'Action to perform (list, get, create, update, delete, reply-list, reply-get, reply-create, reply-update, reply-delete)')
|
|
460
|
-
.option('--id <id>', 'Comment ID (parent comment ID for reply-list/reply-create)')
|
|
461
|
-
.option('--reply-id <id>', 'Reply ID (for reply-get/reply-update/reply-delete)')
|
|
462
|
-
.option('--plan-id <id>', 'Plan ID')
|
|
463
|
-
.option('--finding-id <id>', 'Code review finding ID')
|
|
464
|
-
.option('--task-id <id>', 'Plan task ID')
|
|
465
|
-
.option('--type <type>', 'Comment type (RISK, MODIFICATION, GENERAL)')
|
|
466
|
-
.option('--content <content>', 'Comment content')
|
|
467
|
-
.option('--affected-files <files>', 'Comma-separated list of affected file paths (create/update)')
|
|
468
|
-
.option('--page <number>', 'Page number (list only)')
|
|
469
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
470
|
-
.option('--guide-hash <hash>', 'Hash of the comment guide you followed (create/update/delete). Stale hash is rejected with GUIDE_OUTDATED.')
|
|
471
|
-
.option('--idempotency-key <key>', 'Retry-safe key (create/update/delete). Repeating the same key with the same request replays the first result.')
|
|
472
|
-
.option('--expected-updated-at <iso>', "The comment's updatedAt as you last read it (update/delete). Rejects the write if it changed meanwhile.")
|
|
473
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
474
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
475
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
476
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
477
|
-
.action(async (action, options) => {
|
|
478
|
-
try {
|
|
479
|
-
const result = await executeCommand('comment', action, {
|
|
480
|
-
id: options.id,
|
|
481
|
-
replyId: options.replyId,
|
|
482
|
-
planId: options.planId,
|
|
483
|
-
findingId: options.findingId,
|
|
484
|
-
taskId: options.taskId,
|
|
485
|
-
type: options.type,
|
|
486
|
-
content: options.content,
|
|
487
|
-
affectedFiles: options.affectedFiles,
|
|
488
|
-
page: options.page,
|
|
489
|
-
pageSize: options.pageSize,
|
|
490
|
-
guideHash: options.guideHash,
|
|
491
|
-
idempotencyKey: options.idempotencyKey,
|
|
492
|
-
expectedUpdatedAt: options.expectedUpdatedAt,
|
|
493
|
-
});
|
|
494
|
-
printCommandResult({
|
|
495
|
-
result,
|
|
496
|
-
format: normalizeFormat(options.format),
|
|
497
|
-
outputFile: options.outputFile,
|
|
498
|
-
verbose: options.verbose,
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
catch (error) {
|
|
502
|
-
console.error(handleError(error));
|
|
503
|
-
process.exit(1);
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
program
|
|
507
|
-
.command('attachment')
|
|
508
|
-
.description('Manage trigger, document, and evidence attachments')
|
|
509
|
-
.argument('<action>', 'Action to perform (list, create)')
|
|
510
|
-
.option('--trigger-id <id>', 'Daemon trigger ID (list)')
|
|
511
|
-
.option('--document-id <id>', 'Document ID (list or create)')
|
|
512
|
-
.option('--file <path>', 'Local file to upload (create)')
|
|
513
|
-
.option('--code-review-id <id>', 'Attach to this code review (create)')
|
|
514
|
-
.option('--completion-report-id <id>', 'Attach to this completion report (create)')
|
|
515
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
516
|
-
.addOption(createApiKeyOption())
|
|
517
|
-
.addOption(createApiKeyFileOption())
|
|
518
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
519
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
520
|
-
.option('--format <format>', 'Output format (json)')
|
|
521
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
522
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
523
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
524
|
-
.action(async (action, options) => {
|
|
525
|
-
try {
|
|
526
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
527
|
-
const result = await executeCommand('attachment', action, {
|
|
528
|
-
triggerId: options.triggerId,
|
|
529
|
-
documentId: options.documentId,
|
|
530
|
-
file: options.file,
|
|
531
|
-
codeReviewId: options.codeReviewId,
|
|
532
|
-
completionReportId: options.completionReportId,
|
|
533
|
-
apiUrl: options.apiUrl,
|
|
534
|
-
apiKey: options.apiKey,
|
|
535
|
-
projectId: options.projectId,
|
|
536
|
-
teamId: options.teamId,
|
|
537
|
-
});
|
|
538
|
-
printCommandResult({
|
|
539
|
-
result,
|
|
540
|
-
format: normalizedFormat,
|
|
541
|
-
outputFile: options.outputFile,
|
|
542
|
-
verbose: options.verbose,
|
|
543
|
-
resource: 'attachment',
|
|
544
|
-
action,
|
|
545
|
-
formatExplicit: typeof options.format === 'string',
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
catch (error) {
|
|
549
|
-
console.error(handleError(error));
|
|
550
|
-
process.exit(1);
|
|
551
|
-
}
|
|
552
|
-
});
|
|
553
|
-
program
|
|
554
|
-
.command('report')
|
|
555
|
-
.description('Manage completion reports')
|
|
556
|
-
.argument('<action>', 'Action to perform (list, get, create, update, dismiss-review, delete)')
|
|
557
|
-
.option('--id <id>', 'Report ID')
|
|
558
|
-
.option('--plan-id <id>', 'Plan ID (optional)')
|
|
559
|
-
.option('--title <title>', 'Report title')
|
|
560
|
-
.option('--file <path>', 'Read report content from a local file (create/update)')
|
|
561
|
-
.option('--keep-temp', 'Keep the uploaded file under .agentteams/cli/temp/ instead of deleting it after upload', false)
|
|
562
|
-
.option('--status <status>', 'Report status (COMPLETED, FAILED, PARTIAL)')
|
|
563
|
-
.option('--commit-hash <hash>', 'Git commit hash (manual override)')
|
|
564
|
-
.option('--branch-name <name>', 'Git branch name (manual override)')
|
|
565
|
-
.option('--files-modified <n>', 'Number of modified files (manual override)')
|
|
566
|
-
.option('--lines-added <n>', 'Number of added lines (manual override)')
|
|
567
|
-
.option('--lines-deleted <n>', 'Number of deleted lines (manual override)')
|
|
568
|
-
.option('--duration-seconds <n>', 'Duration in seconds (manual only)')
|
|
569
|
-
.option('--commit-start <hash>', 'Commit range start hash (manual only)')
|
|
570
|
-
.option('--commit-end <hash>', 'Commit range end hash (manual only)')
|
|
571
|
-
.option('--pull-request-id <id>', 'Pull request ID (manual only)')
|
|
572
|
-
.option('--quality-score <n>', 'Quality score 0-100')
|
|
573
|
-
.option('--review-recommendation <value>', 'Code review recommendation: REQUIRED or NOT_NEEDED (create)')
|
|
574
|
-
.option('--review-reason <text>', 'One-line reason for the review recommendation (create)')
|
|
575
|
-
.option('--repository-remote-url <url>', 'Repository remote origin URL (create; defaults to git origin)')
|
|
576
|
-
.option('--runner-type <type>', 'Runner type snapshot: CLAUDE_CODE, CODEX, ANTIGRAVITY, AMP, OPENCODE (required for create)')
|
|
577
|
-
.option('--model <model>', 'Model ID snapshot (required for create)')
|
|
578
|
-
.option('--no-git', 'Disable git metrics auto-collection')
|
|
579
|
-
.option('--page <number>', 'Page number (list only)')
|
|
580
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
581
|
-
.option('--search <text>', 'Title keyword search (list only)')
|
|
582
|
-
.option('--limit <n>', 'Max results per page, alias for --page-size (list only)')
|
|
583
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
584
|
-
.addOption(createApiKeyOption())
|
|
585
|
-
.addOption(createApiKeyFileOption())
|
|
586
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
587
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
588
|
-
.option('--format <format>', 'Output format (json)')
|
|
589
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
590
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
591
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
592
|
-
.action(async (action, options) => {
|
|
593
|
-
try {
|
|
594
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
595
|
-
const result = await executeCommand('report', action, {
|
|
596
|
-
id: options.id,
|
|
597
|
-
planId: options.planId,
|
|
598
|
-
title: options.title,
|
|
599
|
-
file: options.file,
|
|
600
|
-
status: options.status,
|
|
601
|
-
commitHash: options.commitHash,
|
|
602
|
-
branchName: options.branchName,
|
|
603
|
-
filesModified: options.filesModified,
|
|
604
|
-
linesAdded: options.linesAdded,
|
|
605
|
-
linesDeleted: options.linesDeleted,
|
|
606
|
-
durationSeconds: options.durationSeconds,
|
|
607
|
-
commitStart: options.commitStart,
|
|
608
|
-
commitEnd: options.commitEnd,
|
|
609
|
-
pullRequestId: options.pullRequestId,
|
|
610
|
-
qualityScore: options.qualityScore,
|
|
611
|
-
reviewRecommendation: options.reviewRecommendation,
|
|
612
|
-
reviewReason: options.reviewReason,
|
|
613
|
-
repositoryRemoteUrl: options.repositoryRemoteUrl,
|
|
614
|
-
git: options.git,
|
|
615
|
-
page: options.page,
|
|
616
|
-
pageSize: options.pageSize,
|
|
617
|
-
search: options.search,
|
|
618
|
-
limit: options.limit,
|
|
619
|
-
apiUrl: options.apiUrl,
|
|
620
|
-
apiKey: options.apiKey,
|
|
621
|
-
projectId: options.projectId,
|
|
622
|
-
teamId: options.teamId,
|
|
623
|
-
runnerType: options.runnerType,
|
|
624
|
-
model: options.model,
|
|
625
|
-
});
|
|
626
|
-
printCommandResult({
|
|
627
|
-
result,
|
|
628
|
-
format: normalizedFormat,
|
|
629
|
-
outputFile: options.outputFile,
|
|
630
|
-
verbose: options.verbose,
|
|
631
|
-
resource: 'report',
|
|
632
|
-
action,
|
|
633
|
-
formatExplicit: typeof options.format === 'string',
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
catch (error) {
|
|
637
|
-
console.error(handleError(error));
|
|
638
|
-
process.exit(1);
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
program
|
|
642
|
-
.command('code-review')
|
|
643
|
-
.description('Manage independent code reviews')
|
|
644
|
-
.argument('<action>', 'Action to perform (list, get, show, create, update, create-plan, submit-result, cancel, delete, dismiss, resolve, undismiss)')
|
|
645
|
-
.option('--id <id>', 'Code review ID')
|
|
646
|
-
.option('--finding-id <id>', 'Finding ID for get (single-finding focus), dismiss/resolve/undismiss')
|
|
647
|
-
.option('--title <title>', 'Code review or generated plan title')
|
|
648
|
-
.option('--target-type <type>', 'Review target type (BRANCH_DIFF, GITHUB_PR, GITLAB_MR, BITBUCKET_PR, LOCAL_DIFF, UPLOADED_DIFF, COMMIT_RANGE)')
|
|
649
|
-
.option('--target-ref <ref>', 'Target reference such as branch, PR URL, MR URL, or commit range')
|
|
650
|
-
.option('--repository-remote-url <url>', 'Repository remote origin URL (create; defaults to git origin)')
|
|
651
|
-
.option('--source-plan-id <id>', 'Source plan ID')
|
|
652
|
-
.option('--source-completion-report-id <id>', 'Source completion report ID')
|
|
653
|
-
.option('--source-commit-start <hash>', 'Source commit range start')
|
|
654
|
-
.option('--source-commit-end <hash>', 'Source commit range end')
|
|
655
|
-
.option('--source-branch-name <name>', 'Source branch name')
|
|
656
|
-
.option('--base-branch-name <name>', 'Base branch name')
|
|
657
|
-
.option('--diff-summary <text>', 'Diff summary text')
|
|
658
|
-
.option('--diff-file <path>', 'Read diff summary from a local file')
|
|
659
|
-
.option('--test-summary <text>', 'Verification summary text')
|
|
660
|
-
.option('--test-file <path>', 'Read verification summary from a local file')
|
|
661
|
-
.option('--reviewer-context <text>', 'Reviewer context or instructions')
|
|
662
|
-
.option('--recommendation-reason <text>', 'Why this review is recommended')
|
|
663
|
-
.option('--findings-file <path>', 'Read findings JSON array from a local file (create, submit-result)')
|
|
664
|
-
.option('--result-summary <text>', 'Review result summary (submit-result)')
|
|
665
|
-
.option('--error-message <text>', 'Failure reason when --status FAILED (submit-result)')
|
|
666
|
-
.option('--finding-ids <ids>', 'Comma-separated finding IDs for create-plan or resolve')
|
|
667
|
-
.option('--priority <priority>', 'Generated plan priority (LOW, MEDIUM, HIGH)')
|
|
668
|
-
.option('--type <type>', 'Generated plan type (FEATURE, BUG_FIX, ISSUE, REFACTOR, CHORE)')
|
|
669
|
-
.option('--runner-type <type>', 'Runner type snapshot: CLAUDE_CODE, CODEX, ANTIGRAVITY, AMP, OPENCODE')
|
|
670
|
-
.option('--model <model>', 'Model ID snapshot')
|
|
671
|
-
.option('--status <status>', 'Status filter (list); result status COMPLETED|FAILED (submit-result)')
|
|
672
|
-
.option('--search <text>', 'Search keyword (list only)')
|
|
673
|
-
.option('--page <number>', 'Page number (list only)')
|
|
674
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
675
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
676
|
-
.addOption(createApiKeyOption())
|
|
677
|
-
.addOption(createApiKeyFileOption())
|
|
678
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
679
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
680
|
-
.option('--format <format>', 'Output format (json)')
|
|
681
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
682
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
683
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
684
|
-
.action(async (action, options) => {
|
|
685
|
-
try {
|
|
686
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
687
|
-
const result = await executeCommand('code-review', action, {
|
|
688
|
-
id: options.id,
|
|
689
|
-
findingId: options.findingId,
|
|
690
|
-
title: options.title,
|
|
691
|
-
targetType: options.targetType,
|
|
692
|
-
targetRef: options.targetRef,
|
|
693
|
-
repositoryRemoteUrl: options.repositoryRemoteUrl,
|
|
694
|
-
sourcePlanId: options.sourcePlanId,
|
|
695
|
-
sourceCompletionReportId: options.sourceCompletionReportId,
|
|
696
|
-
sourceCommitStart: options.sourceCommitStart,
|
|
697
|
-
sourceCommitEnd: options.sourceCommitEnd,
|
|
698
|
-
sourceBranchName: options.sourceBranchName,
|
|
699
|
-
baseBranchName: options.baseBranchName,
|
|
700
|
-
diffSummary: options.diffSummary,
|
|
701
|
-
diffFile: options.diffFile,
|
|
702
|
-
testSummary: options.testSummary,
|
|
703
|
-
testFile: options.testFile,
|
|
704
|
-
reviewerContext: options.reviewerContext,
|
|
705
|
-
recommendationReason: options.recommendationReason,
|
|
706
|
-
findingsFile: options.findingsFile,
|
|
707
|
-
resultSummary: options.resultSummary,
|
|
708
|
-
errorMessage: options.errorMessage,
|
|
709
|
-
findingIds: options.findingIds,
|
|
710
|
-
priority: options.priority,
|
|
711
|
-
type: options.type,
|
|
712
|
-
runnerType: options.runnerType,
|
|
713
|
-
model: options.model,
|
|
714
|
-
status: options.status,
|
|
715
|
-
search: options.search,
|
|
716
|
-
page: options.page,
|
|
717
|
-
pageSize: options.pageSize,
|
|
718
|
-
apiUrl: options.apiUrl,
|
|
719
|
-
apiKey: options.apiKey,
|
|
720
|
-
projectId: options.projectId,
|
|
721
|
-
teamId: options.teamId,
|
|
722
|
-
});
|
|
723
|
-
printCommandResult({
|
|
724
|
-
result,
|
|
725
|
-
format: normalizedFormat,
|
|
726
|
-
outputFile: options.outputFile,
|
|
727
|
-
verbose: options.verbose,
|
|
728
|
-
resource: 'code-review',
|
|
729
|
-
action,
|
|
730
|
-
formatExplicit: typeof options.format === 'string',
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
catch (error) {
|
|
734
|
-
console.error(handleError(error));
|
|
735
|
-
process.exit(1);
|
|
736
|
-
}
|
|
737
|
-
});
|
|
738
|
-
program
|
|
739
|
-
.command('change-set')
|
|
740
|
-
.description('Manage cross-repository change sets and merge order')
|
|
741
|
-
.argument('<action>', 'Action to perform (create, list, get, update, delete, add-item, remove-item)')
|
|
742
|
-
.option('--id <id>', 'Change set ID')
|
|
743
|
-
.option('--change-set-id <id>', 'Change set ID for item actions')
|
|
744
|
-
.option('--item-id <id>', 'Change set item ID')
|
|
745
|
-
.option('--title <title>', 'Change set title')
|
|
746
|
-
.option('--description <text>', 'Change set description')
|
|
747
|
-
.option('--status <status>', 'Status (OPEN, COMPLETED, CANCELLED)')
|
|
748
|
-
.option('--repository-id <id>', 'Project repository ID')
|
|
749
|
-
.option('--repository-remote-url <url>', 'Repository remote URL (add-item; defaults to git origin)')
|
|
750
|
-
.option('--no-git', 'Disable automatic git origin detection')
|
|
751
|
-
.option('--branch-name <name>', 'Branch name')
|
|
752
|
-
.option('--target-url <url>', 'Pull or merge request URL')
|
|
753
|
-
.option('--merge-order <number>', 'Merge order (positive integer)')
|
|
754
|
-
.option('--code-review-id <id>', 'Linked code review ID')
|
|
755
|
-
.option('--note <text>', 'Item note')
|
|
756
|
-
.option('--page <number>', 'Page number (list only)')
|
|
757
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
758
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
759
|
-
.addOption(createApiKeyOption())
|
|
760
|
-
.addOption(createApiKeyFileOption())
|
|
761
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
762
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
763
|
-
.option('--format <format>', 'Output format (json)')
|
|
764
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
765
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
766
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
767
|
-
.action(async (action, options) => {
|
|
768
|
-
try {
|
|
769
|
-
const result = await executeCommand('change-set', action, options);
|
|
770
|
-
printCommandResult({
|
|
771
|
-
result,
|
|
772
|
-
format: normalizeFormat(options.format),
|
|
773
|
-
outputFile: options.outputFile,
|
|
774
|
-
verbose: options.verbose,
|
|
775
|
-
resource: 'change-set',
|
|
776
|
-
action,
|
|
777
|
-
formatExplicit: typeof options.format === 'string',
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
catch (error) {
|
|
781
|
-
console.error(handleError(error));
|
|
782
|
-
process.exit(1);
|
|
783
|
-
}
|
|
784
|
-
});
|
|
785
|
-
program
|
|
786
|
-
.command('postmortem')
|
|
787
|
-
.description('Manage post mortems')
|
|
788
|
-
.argument('<action>', 'Action to perform (list, get, create, update, delete)')
|
|
789
|
-
.option('--id <id>', 'Post mortem ID')
|
|
790
|
-
.option('--plan-id <id>', 'Plan ID (optional)')
|
|
791
|
-
.option('--title <title>', 'Post mortem title')
|
|
792
|
-
.option('--content <content>', 'Post mortem markdown content (short text; use --file for long content)')
|
|
793
|
-
.option('--file <path>', 'Read postmortem content from a local file (create/update)')
|
|
794
|
-
.option('--keep-temp', 'Keep the uploaded file under .agentteams/cli/temp/ instead of deleting it after upload', false)
|
|
795
|
-
.option('--action-items <csv>', 'Action items (comma-separated)')
|
|
796
|
-
.option('--status <status>', 'Post mortem status (OPEN, IN_PROGRESS, RESOLVED)')
|
|
797
|
-
.option('--repository-remote-url <url>', 'Repository remote origin URL (create; defaults to git origin)')
|
|
798
|
-
.option('--page <number>', 'Page number (list only)')
|
|
799
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
800
|
-
.option('--search <text>', 'Title keyword search (list only)')
|
|
801
|
-
.option('--limit <n>', 'Max results per page, alias for --page-size (list only)')
|
|
802
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
803
|
-
.addOption(createApiKeyOption())
|
|
804
|
-
.addOption(createApiKeyFileOption())
|
|
805
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
806
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
807
|
-
.option('--format <format>', 'Output format (json)')
|
|
808
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
809
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
810
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
811
|
-
.action(async (action, options) => {
|
|
812
|
-
try {
|
|
813
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
814
|
-
const result = await executeCommand('postmortem', action, {
|
|
815
|
-
id: options.id,
|
|
816
|
-
planId: options.planId,
|
|
817
|
-
title: options.title,
|
|
818
|
-
content: options.content,
|
|
819
|
-
file: options.file,
|
|
820
|
-
actionItems: options.actionItems,
|
|
821
|
-
status: options.status,
|
|
822
|
-
repositoryRemoteUrl: options.repositoryRemoteUrl,
|
|
823
|
-
page: options.page,
|
|
824
|
-
pageSize: options.pageSize,
|
|
825
|
-
search: options.search,
|
|
826
|
-
limit: options.limit,
|
|
827
|
-
apiUrl: options.apiUrl,
|
|
828
|
-
apiKey: options.apiKey,
|
|
829
|
-
projectId: options.projectId,
|
|
830
|
-
teamId: options.teamId,
|
|
831
|
-
});
|
|
832
|
-
printCommandResult({
|
|
833
|
-
result,
|
|
834
|
-
format: normalizedFormat,
|
|
835
|
-
outputFile: options.outputFile,
|
|
836
|
-
verbose: options.verbose,
|
|
837
|
-
resource: 'postmortem',
|
|
838
|
-
action,
|
|
839
|
-
formatExplicit: typeof options.format === 'string',
|
|
840
|
-
});
|
|
841
|
-
}
|
|
842
|
-
catch (error) {
|
|
843
|
-
console.error(handleError(error));
|
|
844
|
-
process.exit(1);
|
|
845
|
-
}
|
|
846
|
-
});
|
|
847
|
-
program
|
|
848
|
-
.command('coaction')
|
|
849
|
-
.description('Manage co-actions (session context dumps)')
|
|
850
|
-
.argument('<action>', 'Action to perform (list, get, create, update, delete, download, cleanup, takeaway-list, takeaway-create, takeaway-update, takeaway-delete, history, link-plan, unlink-plan, link-completion-report, unlink-completion-report, link-post-mortem, unlink-post-mortem)')
|
|
851
|
-
.option('--id <id>', 'Co-action ID')
|
|
852
|
-
.option('--takeaway-id <id>', 'Co-action takeaway ID (for takeaway-update/takeaway-delete)')
|
|
853
|
-
.option('--plan-id <id>', 'Plan ID (for link-plan/unlink-plan)')
|
|
854
|
-
.option('--completion-report-id <id>', 'Completion report ID for linking/unlinking')
|
|
855
|
-
.option('--post-mortem-id <id>', 'Post-mortem ID for linking/unlinking')
|
|
856
|
-
.option('--title <title>', 'Co-action title')
|
|
857
|
-
.option('--content <content>', 'Co-action content (short text; use --file for long content)')
|
|
858
|
-
.option('--file <path>', 'Read co-action content from a local file (create/update)')
|
|
859
|
-
.option('--keep-temp', 'Keep the uploaded file under .agentteams/cli/temp/ instead of deleting it after upload', false)
|
|
860
|
-
.option('--status <status>', 'Co-action status (OPEN, CLOSED)')
|
|
861
|
-
.option('--visibility <visibility>', 'Co-action visibility (PRIVATE, PROJECT; also filters list)')
|
|
862
|
-
.option('--source <source>', 'Filter by source (MANUAL, AUTO_SESSION, ALL; list only, default MANUAL)')
|
|
863
|
-
.option('--page <number>', 'Page number (list only)')
|
|
864
|
-
.option('--page-size <number>', 'Page size (list only)')
|
|
865
|
-
.option('--search <text>', 'Title keyword search (list only)')
|
|
866
|
-
.option('--limit <n>', 'Max results per page, alias for --page-size (list only)')
|
|
867
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
868
|
-
.addOption(createApiKeyOption())
|
|
869
|
-
.addOption(createApiKeyFileOption())
|
|
870
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
871
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
872
|
-
.option('--format <format>', 'Output format (json)')
|
|
873
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
874
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
875
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
876
|
-
.action(async (action, options) => {
|
|
877
|
-
try {
|
|
878
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
879
|
-
const result = await executeCommand('coaction', action, {
|
|
880
|
-
id: options.id,
|
|
881
|
-
takeawayId: options.takeawayId,
|
|
882
|
-
planId: options.planId,
|
|
883
|
-
completionReportId: options.completionReportId,
|
|
884
|
-
postMortemId: options.postMortemId,
|
|
885
|
-
title: options.title,
|
|
886
|
-
content: options.content,
|
|
887
|
-
file: options.file,
|
|
888
|
-
status: options.status,
|
|
889
|
-
visibility: options.visibility,
|
|
890
|
-
source: options.source,
|
|
891
|
-
page: options.page,
|
|
892
|
-
pageSize: options.pageSize,
|
|
893
|
-
search: options.search,
|
|
894
|
-
limit: options.limit,
|
|
895
|
-
apiUrl: options.apiUrl,
|
|
896
|
-
apiKey: options.apiKey,
|
|
897
|
-
projectId: options.projectId,
|
|
898
|
-
teamId: options.teamId,
|
|
899
|
-
});
|
|
900
|
-
printCommandResult({
|
|
901
|
-
result,
|
|
902
|
-
format: normalizedFormat,
|
|
903
|
-
outputFile: options.outputFile,
|
|
904
|
-
verbose: options.verbose,
|
|
905
|
-
resource: 'coaction',
|
|
906
|
-
action,
|
|
907
|
-
formatExplicit: typeof options.format === 'string',
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
catch (error) {
|
|
911
|
-
console.error(handleError(error));
|
|
912
|
-
process.exit(1);
|
|
913
|
-
}
|
|
914
|
-
});
|
|
915
|
-
program
|
|
916
|
-
.command('feedback')
|
|
917
|
-
.description('Manage platform feedback')
|
|
918
|
-
.argument('<action>', 'Action to perform (create)')
|
|
919
|
-
.option('--category <category>', 'Feedback category (BUG, SUGGESTION, CONVENTION, UX)')
|
|
920
|
-
.option('--title <title>', 'Feedback title')
|
|
921
|
-
.option('--content <content>', 'Feedback content')
|
|
922
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
923
|
-
.addOption(createApiKeyOption())
|
|
924
|
-
.addOption(createApiKeyFileOption())
|
|
925
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
926
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
927
|
-
.option('--format <format>', 'Output format (json)')
|
|
928
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
929
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
930
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
931
|
-
.action(async (action, options) => {
|
|
932
|
-
try {
|
|
933
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
934
|
-
const result = await executeCommand('feedback', action, {
|
|
935
|
-
category: options.category,
|
|
936
|
-
title: options.title,
|
|
937
|
-
content: options.content,
|
|
938
|
-
apiUrl: options.apiUrl,
|
|
939
|
-
apiKey: options.apiKey,
|
|
940
|
-
projectId: options.projectId,
|
|
941
|
-
teamId: options.teamId,
|
|
942
|
-
});
|
|
943
|
-
printCommandResult({
|
|
944
|
-
result,
|
|
945
|
-
format: normalizedFormat,
|
|
946
|
-
outputFile: options.outputFile,
|
|
947
|
-
verbose: options.verbose,
|
|
948
|
-
resource: 'feedback',
|
|
949
|
-
action,
|
|
950
|
-
formatExplicit: typeof options.format === 'string',
|
|
951
|
-
});
|
|
952
|
-
}
|
|
953
|
-
catch (error) {
|
|
954
|
-
console.error(handleError(error));
|
|
955
|
-
process.exit(1);
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
program
|
|
959
|
-
.command('convention')
|
|
960
|
-
.description('Manage project conventions')
|
|
961
|
-
.argument('<action>', 'Action to perform (list, show, download, status, create, update, delete)')
|
|
962
|
-
.option('--cwd <path>', 'Working directory (defaults to current)')
|
|
963
|
-
.option('-f, --file <path>', 'Target convention markdown file (repeatable; create requires a file under .agentteams/<category>/)', (value, previous = []) => previous.concat([value]), [])
|
|
964
|
-
.option('--apply', 'Apply changes to server (default: dry-run)', false)
|
|
965
|
-
.addOption(new Option('--scope <scope>', 'Convention scope (create only; defaults to PROJECT)').choices([
|
|
966
|
-
'PROJECT',
|
|
967
|
-
'PERSONAL',
|
|
968
|
-
]))
|
|
969
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
970
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
971
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
972
|
-
.action(async (action, options) => {
|
|
973
|
-
try {
|
|
974
|
-
const result = await executeCommand('convention', action, {
|
|
975
|
-
cwd: options.cwd ?? process.cwd(),
|
|
976
|
-
file: options.file,
|
|
977
|
-
apply: options.apply,
|
|
978
|
-
scope: options.scope,
|
|
979
|
-
});
|
|
980
|
-
printCommandResult({
|
|
981
|
-
result,
|
|
982
|
-
format: 'json',
|
|
983
|
-
outputFile: options.outputFile,
|
|
984
|
-
verbose: options.verbose,
|
|
985
|
-
});
|
|
986
|
-
}
|
|
987
|
-
catch (error) {
|
|
988
|
-
console.error(handleError(error));
|
|
989
|
-
process.exit(1);
|
|
990
|
-
}
|
|
991
|
-
});
|
|
992
|
-
program
|
|
993
|
-
.command('document')
|
|
994
|
-
.description('Manage project documents')
|
|
995
|
-
.argument('<action>', 'Action to perform (create, update, download, list, tags, delete, archive, unarchive, revisions, revision-get, revision-restore, comment-list, comment-create, comment-update, comment-delete)')
|
|
996
|
-
.option('--id <id>', 'Document ID')
|
|
997
|
-
.option('--title <title>', 'Document title')
|
|
998
|
-
.option('--file <path>', 'Read markdown body from a local file')
|
|
999
|
-
.option('--tags <tags>', 'Comma-separated tags. List: filter. Create/update: sent as suggestions (not confirmed).')
|
|
1000
|
-
.option('--suggested-tags <tags>', 'Comma-separated AI-suggested tags (auto-promoted when they match existing tags, else await user review)')
|
|
1001
|
-
.option('--visibility <visibility>', 'Document visibility: PRIVATE or PROJECT (default: PRIVATE)')
|
|
1002
|
-
.option('--archived <state>', 'Archive filter for list (ACTIVE, ARCHIVED, ALL)')
|
|
1003
|
-
.option('--revision-id <id>', 'Document revision ID')
|
|
1004
|
-
.option('--comment-id <id>', 'Document comment ID')
|
|
1005
|
-
.option('--content <text>', 'Markdown content for document comments')
|
|
1006
|
-
.option('--order <order>', 'Comment order (asc or desc)')
|
|
1007
|
-
.option('--query <q>', 'Search query (list only)')
|
|
1008
|
-
.option('--limit <n>', 'Max results per page, alias for --page-size (list/revisions/comment-list)')
|
|
1009
|
-
.option('--page <number>', 'Page number (list/revisions/comment-list)')
|
|
1010
|
-
.option('--page-size <number>', 'Page size (list/revisions/comment-list)')
|
|
1011
|
-
.option('--guide-hash <hash>', 'Hash of the document guide you followed (create/update/delete). Stale hash is rejected with GUIDE_OUTDATED.')
|
|
1012
|
-
.option('--idempotency-key <key>', 'Retry-safe key (create/update/delete). Repeating the same key with the same request replays the first result.')
|
|
1013
|
-
.option('--expected-updated-at <iso>', "The document's updatedAt as you last read it (update/delete). Rejects the write if it changed meanwhile.")
|
|
1014
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
1015
|
-
.addOption(createApiKeyOption())
|
|
1016
|
-
.addOption(createApiKeyFileOption())
|
|
1017
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
1018
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
1019
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1020
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1021
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1022
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1023
|
-
.action(async (action, options) => {
|
|
1024
|
-
try {
|
|
1025
|
-
const result = await executeCommand('document', action, options);
|
|
1026
|
-
printCommandResult({
|
|
1027
|
-
result,
|
|
1028
|
-
format: normalizeFormat(options.format),
|
|
1029
|
-
outputFile: options.outputFile,
|
|
1030
|
-
verbose: options.verbose,
|
|
1031
|
-
resource: 'document',
|
|
1032
|
-
action,
|
|
1033
|
-
formatExplicit: typeof options.format === 'string',
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
catch (error) {
|
|
1037
|
-
console.error(handleError(error));
|
|
1038
|
-
process.exit(1);
|
|
1039
|
-
}
|
|
1040
|
-
});
|
|
1041
|
-
program
|
|
1042
|
-
.command('dependency')
|
|
1043
|
-
.description('Manage plan dependencies')
|
|
1044
|
-
.argument('<action>', 'Action to perform (list, create, delete)')
|
|
1045
|
-
.option('--plan-id <id>', 'Plan ID')
|
|
1046
|
-
.option('--blocking-plan-id <id>', 'Blocking plan ID')
|
|
1047
|
-
.option('--dep-id <id>', 'Dependency ID to delete')
|
|
1048
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1049
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1050
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1051
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1052
|
-
.action(async (action, options) => {
|
|
1053
|
-
try {
|
|
1054
|
-
const result = await executeCommand('dependency', action, {
|
|
1055
|
-
planId: options.planId,
|
|
1056
|
-
blockingPlanId: options.blockingPlanId,
|
|
1057
|
-
depId: options.depId,
|
|
1058
|
-
});
|
|
1059
|
-
printCommandResult({
|
|
1060
|
-
result,
|
|
1061
|
-
format: normalizeFormat(options.format),
|
|
1062
|
-
outputFile: options.outputFile,
|
|
1063
|
-
verbose: options.verbose,
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
catch (error) {
|
|
1067
|
-
console.error(handleError(error));
|
|
1068
|
-
process.exit(1);
|
|
1069
|
-
}
|
|
1070
|
-
});
|
|
1071
|
-
program
|
|
1072
|
-
.command('agent-config')
|
|
1073
|
-
.description('Manage agent configurations')
|
|
1074
|
-
.argument('<action>', 'Action to perform (list, get, delete)')
|
|
1075
|
-
.option('--id <id>', 'Agent config ID')
|
|
1076
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1077
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1078
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1079
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1080
|
-
.action(async (action, options) => {
|
|
1081
|
-
try {
|
|
1082
|
-
const result = await executeCommand('agent-config', action, {
|
|
1083
|
-
id: options.id,
|
|
1084
|
-
});
|
|
1085
|
-
printCommandResult({
|
|
1086
|
-
result,
|
|
1087
|
-
format: normalizeFormat(options.format),
|
|
1088
|
-
outputFile: options.outputFile,
|
|
1089
|
-
verbose: options.verbose,
|
|
1090
|
-
});
|
|
1091
|
-
}
|
|
1092
|
-
catch (error) {
|
|
1093
|
-
console.error(handleError(error));
|
|
1094
|
-
process.exit(1);
|
|
1095
|
-
}
|
|
1096
|
-
});
|
|
1097
|
-
program
|
|
1098
|
-
.command('config')
|
|
1099
|
-
.description('Manage configuration')
|
|
1100
|
-
.argument('<action>', 'Action to perform (whoami)')
|
|
1101
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1102
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1103
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1104
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1105
|
-
.action(async (action, options) => {
|
|
1106
|
-
try {
|
|
1107
|
-
const result = await executeCommand('config', action, {});
|
|
1108
|
-
printCommandResult({
|
|
1109
|
-
result,
|
|
1110
|
-
format: normalizeFormat(options.format),
|
|
1111
|
-
outputFile: options.outputFile,
|
|
1112
|
-
verbose: options.verbose,
|
|
1113
|
-
});
|
|
1114
|
-
}
|
|
1115
|
-
catch (error) {
|
|
1116
|
-
console.error(handleError(error));
|
|
1117
|
-
process.exit(1);
|
|
1118
|
-
}
|
|
1119
|
-
});
|
|
1120
|
-
program
|
|
1121
|
-
.command('search')
|
|
1122
|
-
.description('Search across all entity types (plans, co-actions, reports, post-mortems, conventions, code reviews, documents)')
|
|
1123
|
-
.option('--query <text>', 'Search query (required)')
|
|
1124
|
-
.option('--types <types>', 'Comma-separated entity types to filter (PLAN, CO_ACTION, COMPLETION_REPORT, POST_MORTEM, CONVENTION, CODE_REVIEW, DOCUMENT)')
|
|
1125
|
-
.option('--limit <n>', 'Max results (1-100, default: 20)')
|
|
1126
|
-
.option('--max-tokens <n>', 'Token budget for response')
|
|
1127
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
1128
|
-
.addOption(createApiKeyOption())
|
|
1129
|
-
.addOption(createApiKeyFileOption())
|
|
1130
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
1131
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
1132
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1133
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1134
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1135
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1136
|
-
.action(async (options) => {
|
|
1137
|
-
try {
|
|
1138
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
1139
|
-
const result = await executeCommand('search', '', {
|
|
1140
|
-
query: options.query,
|
|
1141
|
-
types: options.types,
|
|
1142
|
-
limit: options.limit,
|
|
1143
|
-
maxTokens: options.maxTokens,
|
|
1144
|
-
apiUrl: options.apiUrl,
|
|
1145
|
-
apiKey: options.apiKey,
|
|
1146
|
-
projectId: options.projectId,
|
|
1147
|
-
teamId: options.teamId,
|
|
1148
|
-
});
|
|
1149
|
-
printCommandResult({
|
|
1150
|
-
result,
|
|
1151
|
-
format: normalizedFormat,
|
|
1152
|
-
outputFile: options.outputFile,
|
|
1153
|
-
verbose: options.verbose,
|
|
1154
|
-
resource: 'search',
|
|
1155
|
-
formatExplicit: typeof options.format === 'string',
|
|
1156
|
-
});
|
|
1157
|
-
}
|
|
1158
|
-
catch (error) {
|
|
1159
|
-
console.error(handleError(error));
|
|
1160
|
-
process.exit(1);
|
|
1161
|
-
}
|
|
1162
|
-
});
|
|
1163
|
-
const mcpCommand = program
|
|
1164
|
-
.command('mcp')
|
|
1165
|
-
.description('Run an MCP server over stdio, exposing AgentTeams reads to MCP-capable coding agents')
|
|
1166
|
-
.option('--tool-profile <profile>', 'Tool catalog profile (full, read, documents, comments, minimal); full is the compatibility default, limited profiles reduce upfront schemas', 'full')
|
|
1167
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
1168
|
-
.addOption(createApiKeyOption())
|
|
1169
|
-
.addOption(createApiKeyFileOption())
|
|
1170
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
1171
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
1172
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1173
|
-
.action(async (options) => {
|
|
1174
|
-
try {
|
|
1175
|
-
// Loaded lazily so the MCP SDK — which requires a newer Node than some of
|
|
1176
|
-
// the CLI's other commands need — never enters the other command paths.
|
|
1177
|
-
const { startMcpServer } = await import('./commands/mcp.js');
|
|
1178
|
-
// stdout carries JSON-RPC frames only: this action deliberately bypasses
|
|
1179
|
-
// executeCommand()/printCommandResult() and never writes to stdout.
|
|
1180
|
-
await startMcpServer({
|
|
1181
|
-
apiUrl: options.apiUrl,
|
|
1182
|
-
apiKey: options.apiKey,
|
|
1183
|
-
projectId: options.projectId,
|
|
1184
|
-
teamId: options.teamId,
|
|
1185
|
-
toolProfile: options.toolProfile,
|
|
1186
|
-
});
|
|
1187
|
-
}
|
|
1188
|
-
catch (error) {
|
|
1189
|
-
// Staying alive without credentials would make the client retry forever.
|
|
1190
|
-
console.error(handleError(error));
|
|
1191
|
-
process.exit(1);
|
|
1192
|
-
}
|
|
1193
|
-
});
|
|
1194
|
-
const MCP_CLIENT_CHOICES = MCP_CLIENT_IDS.join(', ');
|
|
1195
|
-
function addMcpRegistrationOptions(command) {
|
|
1196
|
-
return command
|
|
1197
|
-
.option('--client <id>', `Target client (${MCP_CLIENT_CHOICES})`)
|
|
1198
|
-
.option('--scope <scope>', 'Configuration scope (user, project)', 'project')
|
|
1199
|
-
.option('--tool-profile <profile>', 'Tool catalog profile (full, read, documents, comments, minimal); full is the compatibility default, limited profiles reduce upfront schemas. A client whose backend rejects part of the catalog is narrowed automatically unless you name a profile here')
|
|
1200
|
-
.option('--server-entry <path>', 'Use a local `cli/dist/index.js` instead of the published package (for pre-release testing)')
|
|
1201
|
-
.option('--json', 'Print the machine-readable result instead of the human-readable report', false)
|
|
1202
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
1203
|
-
.addOption(createApiKeyOption())
|
|
1204
|
-
.addOption(createApiKeyFileOption())
|
|
1205
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
1206
|
-
.option('--team-id <id>', 'Override team ID (optional)');
|
|
1207
|
-
}
|
|
1208
|
-
/**
|
|
1209
|
-
* The registration surface is loaded lazily for the same reason the server is:
|
|
1210
|
-
* `agentteams mcp` must stay a thin stdio entry point, and no other command
|
|
1211
|
-
* should pay for the client registry.
|
|
1212
|
-
*/
|
|
1213
|
-
async function runMcpRegistration(action, options, command) {
|
|
1214
|
-
try {
|
|
1215
|
-
const parentOptions = command.parent?.opts() ?? {};
|
|
1216
|
-
const merged = { ...parentOptions, ...options };
|
|
1217
|
-
const { runMcpConfigCommand, runMcpInstallCommand } = await import('./mcp-registration/index.js');
|
|
1218
|
-
const output = action === 'config' ? runMcpConfigCommand(merged) : runMcpInstallCommand(merged);
|
|
1219
|
-
console.log(options.json ? formatOutput(output.json) : output.text);
|
|
1220
|
-
process.exitCode = output.exitCode;
|
|
1221
|
-
}
|
|
1222
|
-
catch (error) {
|
|
1223
|
-
console.error(handleError(error));
|
|
1224
|
-
process.exit(1);
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
addMcpRegistrationOptions(mcpCommand
|
|
1228
|
-
.command('config')
|
|
1229
|
-
.description('Print the MCP configuration snippet for a coding agent. Never writes files or credentials.'))
|
|
1230
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1231
|
-
.action((options, command) => runMcpRegistration('config', options, command));
|
|
1232
|
-
addMcpRegistrationOptions(mcpCommand
|
|
1233
|
-
.command('install')
|
|
1234
|
-
.description('Register AgentTeams with local MCP clients. Without --client it only prints a detection plan; batch apply requires --scope user --yes.'))
|
|
1235
|
-
.option('--yes', 'Apply an explicitly selected user-scope batch plan instead of only printing it', false)
|
|
1236
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1237
|
-
.action((options, command) => runMcpRegistration('install', options, command));
|
|
1238
|
-
mcpCommand
|
|
1239
|
-
.command('doctor')
|
|
1240
|
-
.description('Find legacy plaintext MCP key copies; cleanup is applied only with explicit --yes confirmation.')
|
|
1241
|
-
.option('--yes', 'Confirm safe cleanup after the audit', false)
|
|
1242
|
-
.option('--json', 'Print the machine-readable result instead of the human-readable report', false)
|
|
1243
|
-
.addHelpText('after', CONVENTION_HINT)
|
|
1244
|
-
.action(async (options) => {
|
|
1245
|
-
try {
|
|
1246
|
-
const { runMcpDoctorCommand } = await import('./mcp-registration/doctor.js');
|
|
1247
|
-
const output = await runMcpDoctorCommand({ yes: options.yes === true });
|
|
1248
|
-
console.log(options.json ? formatOutput(output.json) : output.text);
|
|
1249
|
-
process.exitCode = output.exitCode;
|
|
1250
|
-
}
|
|
1251
|
-
catch (error) {
|
|
1252
|
-
console.error(handleError(error));
|
|
1253
|
-
process.exit(1);
|
|
1254
|
-
}
|
|
1255
|
-
});
|
|
1256
|
-
const linearCommand = program
|
|
1257
|
-
.command('linear')
|
|
1258
|
-
.description('Read Linear issues and add comments through the AgentTeams API')
|
|
1259
|
-
.addHelpText('after', CONVENTION_HINT);
|
|
1260
|
-
linearCommand
|
|
1261
|
-
.command('issue')
|
|
1262
|
-
.description('Read, create, or update a Linear issue')
|
|
1263
|
-
.argument('<action>', 'Action to perform (get, create, update)')
|
|
1264
|
-
.option('--issue-id <id>', 'Linear issue ID (required for get, update)')
|
|
1265
|
-
.option('--team-id <id>', 'Linear team ID (required for create)')
|
|
1266
|
-
.option('--title <text>', 'Issue title (required for create)')
|
|
1267
|
-
.option('--description <text>', 'Issue description (optional, for create)')
|
|
1268
|
-
.option('--state <name>', 'Issue state name, e.g. "Done", "Todo" (required for update, optional for create)')
|
|
1269
|
-
.option('--parent-id <id>', 'Linear parent issue UUID for creating a sub-issue (optional, for create)')
|
|
1270
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
1271
|
-
.addOption(createApiKeyOption())
|
|
1272
|
-
.addOption(createApiKeyFileOption())
|
|
1273
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
1274
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1275
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1276
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1277
|
-
.action(async (action, options) => {
|
|
1278
|
-
try {
|
|
1279
|
-
if (action !== 'get' && action !== 'create' && action !== 'update') {
|
|
1280
|
-
throw new Error(`Unknown action: ${action}`);
|
|
1281
|
-
}
|
|
1282
|
-
const actionMap = { get: 'issue-get', create: 'issue-create', update: 'issue-update' };
|
|
1283
|
-
const commandAction = actionMap[action];
|
|
1284
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
1285
|
-
const result = await executeCommand('linear', commandAction, {
|
|
1286
|
-
issueId: options.issueId,
|
|
1287
|
-
teamId: options.teamId,
|
|
1288
|
-
title: options.title,
|
|
1289
|
-
description: options.description,
|
|
1290
|
-
state: options.state,
|
|
1291
|
-
parentId: options.parentId,
|
|
1292
|
-
apiUrl: options.apiUrl,
|
|
1293
|
-
apiKey: options.apiKey,
|
|
1294
|
-
projectId: options.projectId,
|
|
1295
|
-
});
|
|
1296
|
-
printCommandResult({
|
|
1297
|
-
result,
|
|
1298
|
-
format: normalizedFormat,
|
|
1299
|
-
outputFile: options.outputFile,
|
|
1300
|
-
verbose: options.verbose,
|
|
1301
|
-
resource: 'linear',
|
|
1302
|
-
action: commandAction,
|
|
1303
|
-
formatExplicit: typeof options.format === 'string',
|
|
1304
|
-
});
|
|
1305
|
-
}
|
|
1306
|
-
catch (error) {
|
|
1307
|
-
console.error(handleError(error));
|
|
1308
|
-
process.exit(1);
|
|
1309
|
-
}
|
|
1310
|
-
});
|
|
1311
|
-
linearCommand
|
|
1312
|
-
.command('comment')
|
|
1313
|
-
.description('Manage comments on a Linear issue')
|
|
1314
|
-
.argument('<action>', 'Action to perform (list, create)')
|
|
1315
|
-
.option('--issue-id <id>', 'Linear issue ID')
|
|
1316
|
-
.option('--body <text>', 'Comment body')
|
|
1317
|
-
.option('--api-url <url>', 'Override API URL (optional)')
|
|
1318
|
-
.addOption(createApiKeyOption())
|
|
1319
|
-
.addOption(createApiKeyFileOption())
|
|
1320
|
-
.option('--project-id <id>', 'Override project ID (optional)')
|
|
1321
|
-
.option('--team-id <id>', 'Override team ID (optional)')
|
|
1322
|
-
.option('--format <format>', 'Output format (json)', 'json')
|
|
1323
|
-
.option('--output-file <path>', 'Write full output to a file (stdout prints a short summary)')
|
|
1324
|
-
.option('--verbose', 'Print full raw output to stdout; with --output-file, also echo it', false)
|
|
1325
|
-
.action(async (action, options) => {
|
|
1326
|
-
try {
|
|
1327
|
-
if (action !== 'list' && action !== 'create') {
|
|
1328
|
-
throw new Error(`Unknown action: ${action}`);
|
|
1329
|
-
}
|
|
1330
|
-
const commentAction = action === 'list' ? 'comment-list' : 'comment-create';
|
|
1331
|
-
const normalizedFormat = normalizeFormat(options.format);
|
|
1332
|
-
const result = await executeCommand('linear', commentAction, {
|
|
1333
|
-
issueId: options.issueId,
|
|
1334
|
-
body: options.body,
|
|
1335
|
-
apiUrl: options.apiUrl,
|
|
1336
|
-
apiKey: options.apiKey,
|
|
1337
|
-
projectId: options.projectId,
|
|
1338
|
-
teamId: options.teamId,
|
|
1339
|
-
});
|
|
1340
|
-
printCommandResult({
|
|
1341
|
-
result,
|
|
1342
|
-
format: normalizedFormat,
|
|
1343
|
-
outputFile: options.outputFile,
|
|
1344
|
-
verbose: options.verbose,
|
|
1345
|
-
resource: 'linear',
|
|
1346
|
-
action: commentAction,
|
|
1347
|
-
formatExplicit: typeof options.format === 'string',
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
catch (error) {
|
|
1351
|
-
console.error(handleError(error));
|
|
1352
|
-
process.exit(1);
|
|
1353
|
-
}
|
|
1354
|
-
});
|
|
7
|
+
const program = createProgram(pkg.version);
|
|
1355
8
|
startUpdateCheck(pkg.version);
|
|
1356
9
|
program.parse();
|
|
1357
10
|
process.on('beforeExit', () => {
|