feat(cli): support stdin input for issue creation and solution commands

This commit is contained in:
catlog22
2025-12-30 14:51:25 +08:00
parent 6e99cd97ca
commit f6cc3736b2
2 changed files with 50 additions and 9 deletions

View File

@@ -175,7 +175,16 @@ if (clarityScore < 2 && (!issueData.context || issueData.context.length < 20)) {
**Issue Creation** (via CLI endpoint):
```bash
ccw issue create --data '{"title":"...", "context":"...", "priority":3, ...}'
# Option 1: Pipe input (recommended for complex JSON - avoids shell escaping)
echo '{"title":"...", "context":"...", "priority":3}' | ccw issue create
# Option 2: Heredoc (for multi-line JSON)
ccw issue create << 'EOF'
{"title":"...", "context":"含\"引号\"的内容", "priority":3}
EOF
# Option 3: --data parameter (simple cases only)
ccw issue create --data '{"title":"...", "priority":3}'
```
**CLI Endpoint Features:**
@@ -187,15 +196,20 @@ ccw issue create --data '{"title":"...", "context":"...", "priority":3, ...}'
**Example:**
```bash
# Create issue via CLI
ccw issue create --data '{
# Create issue via pipe (recommended)
echo '{"title": "Login fails with special chars", "context": "500 error when password contains quotes", "priority": 2}' | ccw issue create
# Or with heredoc for complex JSON
ccw issue create << 'EOF'
{
"title": "Login fails with special chars",
"context": "500 error when password contains quotes",
"context": "500 error when password contains \"quotes\"",
"priority": 2,
"source": "text",
"expected_behavior": "Login succeeds",
"actual_behavior": "500 Internal Server Error"
}'
}
EOF
# Output (JSON)
{

View File

@@ -617,17 +617,30 @@ function generateQueueItemId(queue: Queue, level: 'solution' | 'task' = 'solutio
/**
* create - Create issue from JSON data
* Usage: ccw issue create --data '{"title":"...", "context":"..."}'
* echo '{"title":"..."}' | ccw issue create
* Output: JSON with created issue (includes auto-generated ID)
*/
async function createAction(options: IssueOptions): Promise<void> {
if (!options.data) {
let jsonData: string | undefined = options.data;
// Support stdin pipe input (avoids shell escaping issues)
if (!jsonData && !process.stdin.isTTY) {
try {
jsonData = readFileSync(0, 'utf-8').trim();
} catch {
// stdin not available or empty
}
}
if (!jsonData) {
console.error(chalk.red('JSON data required'));
console.error(chalk.gray('Usage: ccw issue create --data \'{"title":"...", "context":"..."}\''));
console.error(chalk.gray(' echo \'{"title":"..."}\' | ccw issue create'));
process.exit(1);
}
try {
const data = JSON.parse(options.data);
const data = JSON.parse(jsonData);
const issue = createIssue(data);
console.log(JSON.stringify(issue, null, 2));
} catch (err) {
@@ -639,23 +652,37 @@ async function createAction(options: IssueOptions): Promise<void> {
/**
* solution - Create solution from JSON data
* Usage: ccw issue solution <issue-id> --data '{"tasks":[...]}'
* echo '{"tasks":[...]}' | ccw issue solution <issue-id>
* Output: JSON with created solution (includes auto-generated ID)
*/
async function solutionAction(issueId: string | undefined, options: IssueOptions): Promise<void> {
if (!issueId) {
console.error(chalk.red('Issue ID required'));
console.error(chalk.gray('Usage: ccw issue solution <issue-id> --data \'{"tasks":[...]}\''));
console.error(chalk.gray(' echo \'{"tasks":[...]}\' | ccw issue solution <issue-id>'));
process.exit(1);
}
if (!options.data) {
let jsonData: string | undefined = options.data;
// Support stdin pipe input (avoids shell escaping issues)
if (!jsonData && !process.stdin.isTTY) {
try {
jsonData = readFileSync(0, 'utf-8').trim();
} catch {
// stdin not available or empty
}
}
if (!jsonData) {
console.error(chalk.red('JSON data required'));
console.error(chalk.gray('Usage: ccw issue solution <issue-id> --data \'{"tasks":[...]}\''));
console.error(chalk.gray(' echo \'{"tasks":[...]}\' | ccw issue solution <issue-id>'));
process.exit(1);
}
try {
const data = JSON.parse(options.data);
const data = JSON.parse(jsonData);
const solution = createSolution(issueId, data);
console.log(JSON.stringify(solution, null, 2));
} catch (err) {