@proletariat/cli 0.3.25 → 0.3.27
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/action/index.js +2 -2
- package/dist/commands/action/show.js +7 -1
- package/dist/commands/agent/auth.js +1 -1
- package/dist/commands/agent/cleanup.js +6 -6
- package/dist/commands/agent/discover.js +1 -1
- package/dist/commands/agent/remove.js +4 -4
- package/dist/commands/autocomplete/setup.d.ts +2 -2
- package/dist/commands/autocomplete/setup.js +5 -5
- package/dist/commands/branch/create.js +31 -30
- package/dist/commands/branch/list.js +14 -11
- package/dist/commands/branch/validate.js +10 -1
- package/dist/commands/category/create.js +4 -5
- package/dist/commands/category/delete.js +2 -3
- package/dist/commands/category/rename.js +2 -3
- package/dist/commands/claude.d.ts +2 -8
- package/dist/commands/claude.js +26 -26
- package/dist/commands/commit.d.ts +2 -8
- package/dist/commands/commit.js +4 -26
- package/dist/commands/config/index.d.ts +2 -10
- package/dist/commands/config/index.js +8 -34
- package/dist/commands/docker/clean.js +7 -9
- package/dist/commands/docker/index.d.ts +2 -2
- package/dist/commands/docker/index.js +13 -12
- package/dist/commands/docker/list.d.ts +1 -0
- package/dist/commands/docker/list.js +31 -17
- package/dist/commands/docker/status.d.ts +3 -1
- package/dist/commands/docker/status.js +28 -2
- package/dist/commands/docker/sync.js +7 -6
- package/dist/commands/epic/delete.js +4 -5
- package/dist/commands/epic/list.js +17 -2
- package/dist/commands/execution/list.js +25 -17
- package/dist/commands/feedback/submit.d.ts +2 -2
- package/dist/commands/feedback/submit.js +9 -9
- package/dist/commands/link/index.js +2 -2
- package/dist/commands/pmo/init.d.ts +2 -2
- package/dist/commands/pmo/init.js +29 -10
- package/dist/commands/project/spec.js +6 -6
- package/dist/commands/repo/list.js +14 -8
- package/dist/commands/repo/view.js +2 -1
- package/dist/commands/roadmap/list.js +16 -1
- package/dist/commands/session/health.d.ts +29 -0
- package/dist/commands/session/health.js +496 -0
- package/dist/commands/session/index.js +4 -0
- package/dist/commands/session/list.js +15 -8
- package/dist/commands/spec/edit.js +2 -3
- package/dist/commands/staff/add.d.ts +2 -2
- package/dist/commands/staff/add.js +15 -14
- package/dist/commands/staff/index.js +2 -2
- package/dist/commands/staff/list.d.ts +3 -1
- package/dist/commands/staff/list.js +15 -1
- package/dist/commands/staff/remove.js +4 -4
- package/dist/commands/status/index.js +6 -7
- package/dist/commands/template/apply.js +10 -11
- package/dist/commands/template/create.js +18 -17
- package/dist/commands/template/index.d.ts +2 -2
- package/dist/commands/template/index.js +6 -6
- package/dist/commands/template/save.js +8 -7
- package/dist/commands/template/update.js +6 -7
- package/dist/commands/terminal/title.d.ts +2 -26
- package/dist/commands/terminal/title.js +4 -33
- package/dist/commands/theme/index.d.ts +2 -2
- package/dist/commands/theme/index.js +19 -18
- package/dist/commands/theme/list.d.ts +3 -0
- package/dist/commands/theme/list.js +25 -0
- package/dist/commands/theme/set.d.ts +2 -2
- package/dist/commands/theme/set.js +5 -5
- package/dist/commands/ticket/complete.js +4 -1
- package/dist/commands/ticket/create.d.ts +1 -0
- package/dist/commands/ticket/create.js +64 -16
- package/dist/commands/ticket/delete.js +18 -16
- package/dist/commands/ticket/edit.js +22 -14
- package/dist/commands/ticket/epic.js +12 -10
- package/dist/commands/ticket/list.js +24 -5
- package/dist/commands/ticket/move.js +4 -1
- package/dist/commands/ticket/project.js +11 -9
- package/dist/commands/ticket/reassign.js +23 -19
- package/dist/commands/ticket/spec.js +7 -5
- package/dist/commands/ticket/update.js +55 -53
- package/dist/commands/ticket/view.js +4 -2
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.js +22 -4
- package/dist/commands/work/complete.js +2 -2
- package/dist/commands/work/ready.js +9 -9
- package/dist/commands/work/revise.js +15 -13
- package/dist/commands/work/spawn.js +154 -57
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +299 -177
- package/dist/commands/workspace/prune.d.ts +3 -2
- package/dist/commands/workspace/prune.js +70 -10
- package/dist/hooks/init.js +4 -0
- package/dist/lib/agents/commands.js +4 -0
- package/dist/lib/agents/index.js +12 -0
- package/dist/lib/execution/devcontainer.d.ts +4 -0
- package/dist/lib/execution/devcontainer.js +63 -0
- package/dist/lib/mcp/helpers.d.ts +15 -0
- package/dist/lib/mcp/helpers.js +15 -0
- package/dist/lib/mcp/tools/action.js +5 -5
- package/dist/lib/mcp/tools/board.js +7 -7
- package/dist/lib/mcp/tools/category.js +5 -5
- package/dist/lib/mcp/tools/cli-passthrough.js +30 -30
- package/dist/lib/mcp/tools/epic.js +8 -8
- package/dist/lib/mcp/tools/phase.js +7 -7
- package/dist/lib/mcp/tools/project.js +10 -10
- package/dist/lib/mcp/tools/roadmap.js +7 -7
- package/dist/lib/mcp/tools/spec.js +9 -9
- package/dist/lib/mcp/tools/status.js +6 -6
- package/dist/lib/mcp/tools/template.js +6 -6
- package/dist/lib/mcp/tools/ticket.js +19 -19
- package/dist/lib/mcp/tools/view.js +4 -4
- package/dist/lib/mcp/tools/work.js +6 -6
- package/dist/lib/mcp/tools/workflow.js +5 -5
- package/dist/lib/pmo/index.js +4 -0
- package/dist/lib/pmo/storage/base.js +49 -0
- package/dist/lib/pr/index.d.ts +9 -0
- package/dist/lib/pr/index.js +101 -14
- package/dist/lib/prompt-command.d.ts +3 -0
- package/dist/lib/prompt-json.d.ts +72 -1
- package/dist/lib/prompt-json.js +46 -0
- package/dist/lib/repos/index.js +4 -0
- package/dist/lib/string-utils.d.ts +10 -0
- package/dist/lib/string-utils.js +16 -0
- package/oclif.manifest.json +594 -449
- package/package.json +3 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import inquirer from 'inquirer';
|
|
4
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
4
5
|
import { getWorkspaceInfo, validateAgentNames, addAgentsToWorkspace } from '../../lib/agents/commands.js';
|
|
5
6
|
import { ensureBuiltinThemes, BUILTIN_THEMES, isValidAgentName, normalizeAgentName } from '../../lib/themes.js';
|
|
6
7
|
import { getTheme, getThemes, getAvailableThemeNames, getActiveTheme } from '../../lib/database/index.js';
|
|
7
8
|
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
8
|
-
export default class Add extends
|
|
9
|
+
export default class Add extends PromptCommand {
|
|
9
10
|
static description = 'Add new agents to the workspace';
|
|
10
11
|
static examples = [
|
|
11
12
|
'<%= config.bin %> <%= command.id %> zeus',
|
|
@@ -82,13 +83,13 @@ export default class Add extends Command {
|
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
85
|
// Interactive selection from theme
|
|
85
|
-
const { selected } = await
|
|
86
|
+
const { selected } = await this.prompt([{
|
|
86
87
|
type: 'checkbox',
|
|
87
88
|
name: 'selected',
|
|
88
89
|
message: selectMessage,
|
|
89
90
|
choices: nameChoices,
|
|
90
91
|
validate: (input) => input.length > 0 || 'Please select at least one name'
|
|
91
|
-
}]);
|
|
92
|
+
}], null);
|
|
92
93
|
agentNames = selected;
|
|
93
94
|
}
|
|
94
95
|
// Interactive mode: show names from workspace's active theme
|
|
@@ -127,19 +128,19 @@ export default class Add extends Command {
|
|
|
127
128
|
new inquirer.Separator(),
|
|
128
129
|
{ name: chalk.blue(nameChoices[nameChoices.length - 1].name), value: nameChoices[nameChoices.length - 1].value }
|
|
129
130
|
];
|
|
130
|
-
const { selected } = await
|
|
131
|
+
const { selected } = await this.prompt([{
|
|
131
132
|
type: 'checkbox',
|
|
132
133
|
name: 'selected',
|
|
133
134
|
message: selectMessage,
|
|
134
135
|
choices,
|
|
135
136
|
pageSize: 20,
|
|
136
137
|
validate: (input) => input.length > 0 || 'Please select at least one name'
|
|
137
|
-
}]);
|
|
138
|
+
}], null);
|
|
138
139
|
// Check if custom was selected
|
|
139
140
|
const hasCustom = selected.includes('__custom__');
|
|
140
141
|
const themedSelections = selected.filter((s) => s !== '__custom__');
|
|
141
142
|
if (hasCustom) {
|
|
142
|
-
const { customNames } = await
|
|
143
|
+
const { customNames } = await this.prompt([{
|
|
143
144
|
type: 'input',
|
|
144
145
|
name: 'customNames',
|
|
145
146
|
message: 'Enter custom agent names (space-separated):',
|
|
@@ -148,7 +149,7 @@ export default class Add extends Command {
|
|
|
148
149
|
return 'Please enter at least one name';
|
|
149
150
|
return true;
|
|
150
151
|
}
|
|
151
|
-
}]);
|
|
152
|
+
}], null);
|
|
152
153
|
const rawNames = customNames.trim().split(/\s+/);
|
|
153
154
|
const normalizedCustom = rawNames.map((n) => normalizeAgentName(n)).filter((n) => n && isValidAgentName(n));
|
|
154
155
|
agentNames.push(...normalizedCustom);
|
|
@@ -187,14 +188,14 @@ export default class Add extends Command {
|
|
|
187
188
|
new inquirer.Separator(),
|
|
188
189
|
{ name: chalk.blue(themeChoices[themeChoices.length - 1].name), value: themeChoices[themeChoices.length - 1].value }
|
|
189
190
|
];
|
|
190
|
-
const { selectedTheme } = await
|
|
191
|
+
const { selectedTheme } = await this.prompt([{
|
|
191
192
|
type: 'list',
|
|
192
193
|
name: 'selectedTheme',
|
|
193
194
|
message: selectMessage,
|
|
194
195
|
choices: interactiveChoices
|
|
195
|
-
}]);
|
|
196
|
+
}], null);
|
|
196
197
|
if (selectedTheme === '__custom__') {
|
|
197
|
-
const { customNames } = await
|
|
198
|
+
const { customNames } = await this.prompt([{
|
|
198
199
|
type: 'input',
|
|
199
200
|
name: 'customNames',
|
|
200
201
|
message: 'Enter custom agent names (space-separated):',
|
|
@@ -203,7 +204,7 @@ export default class Add extends Command {
|
|
|
203
204
|
return 'Please enter at least one name';
|
|
204
205
|
return true;
|
|
205
206
|
}
|
|
206
|
-
}]);
|
|
207
|
+
}], null);
|
|
207
208
|
const rawNames = customNames.trim().split(/\s+/);
|
|
208
209
|
const normalizedCustom = rawNames.map((n) => ({
|
|
209
210
|
original: n,
|
|
@@ -222,14 +223,14 @@ export default class Add extends Command {
|
|
|
222
223
|
themeId = selectedTheme;
|
|
223
224
|
const theme = getTheme(workspaceInfo.path, selectedTheme);
|
|
224
225
|
const availableNames = getAvailableThemeNames(workspaceInfo.path, selectedTheme);
|
|
225
|
-
const { selected } = await
|
|
226
|
+
const { selected } = await this.prompt([{
|
|
226
227
|
type: 'checkbox',
|
|
227
228
|
name: 'selected',
|
|
228
229
|
message: `Select agents from ${theme?.display_name}:`,
|
|
229
230
|
choices: availableNames.map(name => ({ name, value: name })),
|
|
230
231
|
pageSize: 20,
|
|
231
232
|
validate: (input) => input.length > 0 || 'Please select at least one name'
|
|
232
|
-
}]);
|
|
233
|
+
}], null);
|
|
233
234
|
agentNames = selected;
|
|
234
235
|
}
|
|
235
236
|
}
|
|
@@ -46,7 +46,7 @@ export default class Staff extends PMOCommand {
|
|
|
46
46
|
}
|
|
47
47
|
this.log(colors.primary('Staff Agents'));
|
|
48
48
|
this.log(colors.textMuted('Persistent agents with dedicated worktrees.\n'));
|
|
49
|
-
const { action } = await
|
|
49
|
+
const { action } = await this.prompt([{
|
|
50
50
|
type: 'list',
|
|
51
51
|
name: 'action',
|
|
52
52
|
message,
|
|
@@ -57,7 +57,7 @@ export default class Staff extends PMOCommand {
|
|
|
57
57
|
new inquirer.Separator(),
|
|
58
58
|
{ name: '❌ ' + menuChoices[3].name, value: menuChoices[3].value },
|
|
59
59
|
]
|
|
60
|
-
}]);
|
|
60
|
+
}], null);
|
|
61
61
|
if (action === 'cancel') {
|
|
62
62
|
this.log(colors.textMuted('Operation cancelled.'));
|
|
63
63
|
return;
|
|
@@ -2,6 +2,8 @@ import { Command } from '@oclif/core';
|
|
|
2
2
|
export default class List extends Command {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
|
-
static flags: {
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
6
8
|
run(): Promise<void>;
|
|
7
9
|
}
|
|
@@ -3,25 +3,39 @@ import chalk from 'chalk';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import * as fs from 'node:fs';
|
|
5
5
|
import { getWorkspaceInfo, getAllAgentsStatus } from '../../lib/agents/commands.js';
|
|
6
|
+
import { shouldOutputJson } from '../../lib/prompt-json.js';
|
|
7
|
+
import { machineOutputFlags } from '../../lib/pmo/index.js';
|
|
6
8
|
export default class List extends Command {
|
|
7
9
|
static description = 'List all staff (persistent) agents and their status';
|
|
8
10
|
static examples = [
|
|
9
11
|
'<%= config.bin %> <%= command.id %>',
|
|
10
12
|
];
|
|
11
|
-
static flags = {
|
|
13
|
+
static flags = {
|
|
14
|
+
...machineOutputFlags,
|
|
15
|
+
};
|
|
12
16
|
async run() {
|
|
17
|
+
const { flags } = await this.parse(List);
|
|
18
|
+
const jsonMode = shouldOutputJson(flags);
|
|
13
19
|
try {
|
|
14
20
|
// Get workspace information
|
|
15
21
|
const workspaceInfo = getWorkspaceInfo();
|
|
16
22
|
// Filter to staff agents only
|
|
17
23
|
const staffAgents = workspaceInfo.agents.filter(a => a.type === 'persistent');
|
|
18
24
|
if (staffAgents.length === 0) {
|
|
25
|
+
if (jsonMode) {
|
|
26
|
+
this.log(JSON.stringify([], null, 2));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
19
29
|
this.log(chalk.yellow('No staff agents found. Add staff agents with "prlt staff add"'));
|
|
20
30
|
return;
|
|
21
31
|
}
|
|
22
32
|
// Get status for all agents and filter to staff
|
|
23
33
|
const agentsStatus = getAllAgentsStatus(workspaceInfo);
|
|
24
34
|
const staffStatus = agentsStatus.filter(a => staffAgents.some(s => s.name === a.name));
|
|
35
|
+
if (jsonMode) {
|
|
36
|
+
this.log(JSON.stringify(staffStatus, null, 2));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
25
39
|
this.log(chalk.bold.cyan('\n Staff Agents:\n'));
|
|
26
40
|
for (const agentStatus of staffStatus) {
|
|
27
41
|
// Agent info line
|
|
@@ -71,7 +71,7 @@ export default class Remove extends PMOCommand {
|
|
|
71
71
|
outputPromptAsJson(buildPromptConfig('list', 'name', selectMessage, agentChoices), createMetadata('staff remove', flags));
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
const { selected } = await
|
|
74
|
+
const { selected } = await this.prompt([
|
|
75
75
|
{
|
|
76
76
|
type: 'list',
|
|
77
77
|
name: 'selected',
|
|
@@ -82,7 +82,7 @@ export default class Remove extends PMOCommand {
|
|
|
82
82
|
{ name: '❌ ' + agentChoices[agentChoices.length - 1].name, value: agentChoices[agentChoices.length - 1].value }
|
|
83
83
|
]
|
|
84
84
|
}
|
|
85
|
-
]);
|
|
85
|
+
], null);
|
|
86
86
|
if (selected === 'cancel') {
|
|
87
87
|
this.log(colors.textMuted('Operation cancelled.'));
|
|
88
88
|
return;
|
|
@@ -109,7 +109,7 @@ export default class Remove extends PMOCommand {
|
|
|
109
109
|
outputPromptAsJson(buildPromptConfig('list', 'confirmed', confirmMessage, confirmChoices), createMetadata('staff remove', flags));
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
112
|
-
const { confirm } = await
|
|
112
|
+
const { confirm } = await this.prompt([
|
|
113
113
|
{
|
|
114
114
|
type: 'list',
|
|
115
115
|
name: 'confirm',
|
|
@@ -120,7 +120,7 @@ export default class Remove extends PMOCommand {
|
|
|
120
120
|
],
|
|
121
121
|
default: 0 // Default to "No, cancel"
|
|
122
122
|
}
|
|
123
|
-
]);
|
|
123
|
+
], null);
|
|
124
124
|
if (!confirm) {
|
|
125
125
|
this.log(colors.textMuted('Removal cancelled.'));
|
|
126
126
|
return;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import inquirer from 'inquirer';
|
|
2
1
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
3
2
|
import { FlagResolver, shouldOutputJson } from '../../lib/flags/index.js';
|
|
4
3
|
export default class Status extends PMOCommand {
|
|
@@ -62,34 +61,34 @@ export default class Status extends PMOCommand {
|
|
|
62
61
|
case 'update': {
|
|
63
62
|
// First list statuses, then prompt for selection
|
|
64
63
|
await this.config.runCommand('status:list', []);
|
|
65
|
-
const { statusId } = await
|
|
64
|
+
const { statusId } = await this.prompt([{
|
|
66
65
|
type: 'input',
|
|
67
66
|
name: 'statusId',
|
|
68
67
|
message: 'Status ID to update:',
|
|
69
68
|
validate: (input) => input.length > 0 || 'Status ID is required',
|
|
70
|
-
}]);
|
|
69
|
+
}], null);
|
|
71
70
|
await this.config.runCommand('status:update', [statusId]);
|
|
72
71
|
break;
|
|
73
72
|
}
|
|
74
73
|
case 'move': {
|
|
75
74
|
await this.config.runCommand('status:list', []);
|
|
76
|
-
const { statusId } = await
|
|
75
|
+
const { statusId } = await this.prompt([{
|
|
77
76
|
type: 'input',
|
|
78
77
|
name: 'statusId',
|
|
79
78
|
message: 'Status ID to move:',
|
|
80
79
|
validate: (input) => input.length > 0 || 'Status ID is required',
|
|
81
|
-
}]);
|
|
80
|
+
}], null);
|
|
82
81
|
await this.config.runCommand('status:move', [statusId]);
|
|
83
82
|
break;
|
|
84
83
|
}
|
|
85
84
|
case 'delete': {
|
|
86
85
|
await this.config.runCommand('status:list', []);
|
|
87
|
-
const { statusId } = await
|
|
86
|
+
const { statusId } = await this.prompt([{
|
|
88
87
|
type: 'input',
|
|
89
88
|
name: 'statusId',
|
|
90
89
|
message: 'Status ID to delete:',
|
|
91
90
|
validate: (input) => input.length > 0 || 'Status ID is required',
|
|
92
|
-
}]);
|
|
91
|
+
}], null);
|
|
93
92
|
await this.config.runCommand('status:delete', [statusId]);
|
|
94
93
|
break;
|
|
95
94
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Flags, Args } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
|
|
4
3
|
import { PRIORITIES, PRIORITY_LABELS } from '../../lib/pmo/types.js';
|
|
5
4
|
import { styles } from '../../lib/styles.js';
|
|
@@ -92,7 +91,7 @@ export default class TemplateApply extends PMOCommand {
|
|
|
92
91
|
]), createMetadata('template apply', flags));
|
|
93
92
|
return;
|
|
94
93
|
}
|
|
95
|
-
const { selectedType } = await
|
|
94
|
+
const { selectedType } = await this.prompt([{
|
|
96
95
|
type: 'list',
|
|
97
96
|
name: 'selectedType',
|
|
98
97
|
message: 'What type of template?',
|
|
@@ -100,7 +99,7 @@ export default class TemplateApply extends PMOCommand {
|
|
|
100
99
|
{ name: 'Ticket template', value: 'ticket' },
|
|
101
100
|
{ name: 'Phase template', value: 'phase' },
|
|
102
101
|
],
|
|
103
|
-
}]);
|
|
102
|
+
}], null);
|
|
104
103
|
templateType = selectedType;
|
|
105
104
|
}
|
|
106
105
|
if (templateType === 'ticket') {
|
|
@@ -127,12 +126,12 @@ export default class TemplateApply extends PMOCommand {
|
|
|
127
126
|
if (templates.length === 0) {
|
|
128
127
|
return handleError('NO_TEMPLATES', 'No ticket templates. Create with: prlt template create --type ticket');
|
|
129
128
|
}
|
|
130
|
-
const { selected } = await
|
|
129
|
+
const { selected } = await this.prompt([{
|
|
131
130
|
type: 'list',
|
|
132
131
|
name: 'selected',
|
|
133
132
|
message: 'Select template:',
|
|
134
133
|
choices: templates.map(t => ({ name: `${t.name}${t.description ? ` - ${t.description}` : ''}`, value: t.id })),
|
|
135
|
-
}]);
|
|
134
|
+
}], null);
|
|
136
135
|
templateId = selected;
|
|
137
136
|
}
|
|
138
137
|
const template = await this.storage.getTicketTemplate(templateId);
|
|
@@ -159,10 +158,10 @@ export default class TemplateApply extends PMOCommand {
|
|
|
159
158
|
outputPromptAsJson(buildFormPromptConfig(fields), createMetadata('template apply', flags));
|
|
160
159
|
return;
|
|
161
160
|
}
|
|
162
|
-
const answers = await
|
|
161
|
+
const answers = await this.prompt(fields.map(f => ({
|
|
163
162
|
...f,
|
|
164
163
|
validate: f.name === 'title' ? ((i) => i.length > 0 || 'Required') : undefined,
|
|
165
|
-
})));
|
|
164
|
+
})), null);
|
|
166
165
|
title = answers.title;
|
|
167
166
|
column = answers.column;
|
|
168
167
|
priority = answers.priority || undefined;
|
|
@@ -215,12 +214,12 @@ export default class TemplateApply extends PMOCommand {
|
|
|
215
214
|
if (templates.length === 0) {
|
|
216
215
|
return handleError('NO_TEMPLATES', 'No phase templates. Create with: prlt template create --type phase');
|
|
217
216
|
}
|
|
218
|
-
const { selected } = await
|
|
217
|
+
const { selected } = await this.prompt([{
|
|
219
218
|
type: 'list',
|
|
220
219
|
name: 'selected',
|
|
221
220
|
message: 'Select phase template:',
|
|
222
221
|
choices: templates.map(t => ({ name: `${t.name}${t.description ? ` - ${t.description}` : ''}`, value: t.id })),
|
|
223
|
-
}]);
|
|
222
|
+
}], null);
|
|
224
223
|
templateId = selected;
|
|
225
224
|
}
|
|
226
225
|
const template = await this.storage.getPhaseTemplate(templateId);
|
|
@@ -238,7 +237,7 @@ export default class TemplateApply extends PMOCommand {
|
|
|
238
237
|
return;
|
|
239
238
|
}
|
|
240
239
|
this.log(styles.warning(`\nThis will REPLACE ${existingPhases.length} existing phase(s).`));
|
|
241
|
-
const { confirm } = await
|
|
240
|
+
const { confirm } = await this.prompt([{
|
|
242
241
|
type: 'list',
|
|
243
242
|
name: 'confirm',
|
|
244
243
|
message: `Apply template "${template.name}"?`,
|
|
@@ -246,7 +245,7 @@ export default class TemplateApply extends PMOCommand {
|
|
|
246
245
|
{ name: 'No', value: false },
|
|
247
246
|
{ name: 'Yes', value: true },
|
|
248
247
|
],
|
|
249
|
-
}]);
|
|
248
|
+
}], null);
|
|
250
249
|
if (!confirm) {
|
|
251
250
|
this.log(styles.muted('Cancelled'));
|
|
252
251
|
return;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { PRIORITIES, PRIORITY_LABELS, TICKET_CATEGORIES } from '../../lib/pmo/types.js';
|
|
5
4
|
import { styles } from '../../lib/styles.js';
|
|
@@ -82,15 +81,15 @@ export default class TemplateCreate extends PMOCommand {
|
|
|
82
81
|
]), createMetadata('template create', flags));
|
|
83
82
|
return;
|
|
84
83
|
}
|
|
85
|
-
const { selectedType } = await
|
|
84
|
+
const { selectedType } = await this.prompt([{
|
|
86
85
|
type: 'list',
|
|
87
86
|
name: 'selectedType',
|
|
88
87
|
message: 'What type of template?',
|
|
89
88
|
choices: [
|
|
90
|
-
{ name: 'Ticket template', value: 'ticket' },
|
|
91
|
-
{ name: 'Phase template', value: 'phase' },
|
|
89
|
+
{ name: 'Ticket template', value: 'ticket', command: 'prlt template create --type ticket --json' },
|
|
90
|
+
{ name: 'Phase template', value: 'phase', command: 'prlt template create --type phase --json' },
|
|
92
91
|
],
|
|
93
|
-
}]);
|
|
92
|
+
}], jsonMode ? { flags, commandName: 'template create' } : null);
|
|
94
93
|
templateType = selectedType;
|
|
95
94
|
}
|
|
96
95
|
if (templateType === 'ticket') {
|
|
@@ -129,12 +128,13 @@ export default class TemplateCreate extends PMOCommand {
|
|
|
129
128
|
outputPromptAsJson(buildFormPromptConfig(fields), createMetadata('template create', flags));
|
|
130
129
|
return;
|
|
131
130
|
}
|
|
132
|
-
const {
|
|
131
|
+
const jsonModeConfig = jsonMode ? { flags: flags, commandName: 'template create' } : null;
|
|
132
|
+
const { templateName } = await this.prompt([{
|
|
133
133
|
type: 'input',
|
|
134
134
|
name: 'templateName',
|
|
135
135
|
message: 'Template name:',
|
|
136
136
|
validate: (input) => input.trim() ? true : 'Name required',
|
|
137
|
-
}]);
|
|
137
|
+
}], jsonModeConfig);
|
|
138
138
|
name = templateName;
|
|
139
139
|
}
|
|
140
140
|
// Get optional values
|
|
@@ -148,13 +148,13 @@ export default class TemplateCreate extends PMOCommand {
|
|
|
148
148
|
let descriptionTemplate = flags['description-template'];
|
|
149
149
|
// Interactive prompts for missing optional values
|
|
150
150
|
if (!jsonMode && description === undefined) {
|
|
151
|
-
const { desc } = await
|
|
151
|
+
const { desc } = await this.prompt([{
|
|
152
152
|
type: 'input', name: 'desc', message: 'Description (optional):',
|
|
153
|
-
}]);
|
|
153
|
+
}], null);
|
|
154
154
|
description = desc || undefined;
|
|
155
155
|
}
|
|
156
156
|
if (!jsonMode && priority === undefined) {
|
|
157
|
-
const { p } = await
|
|
157
|
+
const { p } = await this.prompt([{
|
|
158
158
|
type: 'list',
|
|
159
159
|
name: 'p',
|
|
160
160
|
message: 'Default priority:',
|
|
@@ -162,11 +162,11 @@ export default class TemplateCreate extends PMOCommand {
|
|
|
162
162
|
{ name: 'None', value: '' },
|
|
163
163
|
...PRIORITIES.map(pr => ({ name: PRIORITY_LABELS[pr], value: pr })),
|
|
164
164
|
],
|
|
165
|
-
}]);
|
|
165
|
+
}], null);
|
|
166
166
|
priority = p || undefined;
|
|
167
167
|
}
|
|
168
168
|
if (!jsonMode && category === undefined) {
|
|
169
|
-
const { c } = await
|
|
169
|
+
const { c } = await this.prompt([{
|
|
170
170
|
type: 'list',
|
|
171
171
|
name: 'c',
|
|
172
172
|
message: 'Default category:',
|
|
@@ -174,7 +174,7 @@ export default class TemplateCreate extends PMOCommand {
|
|
|
174
174
|
{ name: 'None', value: '' },
|
|
175
175
|
...TICKET_CATEGORIES.map(cat => ({ name: cat, value: cat })),
|
|
176
176
|
],
|
|
177
|
-
}]);
|
|
177
|
+
}], null);
|
|
178
178
|
category = c || undefined;
|
|
179
179
|
}
|
|
180
180
|
// Build description template with ACs
|
|
@@ -207,19 +207,20 @@ export default class TemplateCreate extends PMOCommand {
|
|
|
207
207
|
outputErrorAsJson('NAME_REQUIRED', 'Name required: prlt template create --type phase "Name"', createMetadata('template create', flags));
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
|
-
const {
|
|
210
|
+
const jsonModeConfig = jsonMode ? { flags: flags, commandName: 'template create' } : null;
|
|
211
|
+
const { templateName } = await this.prompt([{
|
|
211
212
|
type: 'input',
|
|
212
213
|
name: 'templateName',
|
|
213
214
|
message: 'Template name:',
|
|
214
215
|
validate: (input) => input.trim() ? true : 'Name required',
|
|
215
|
-
}]);
|
|
216
|
+
}], jsonModeConfig);
|
|
216
217
|
name = templateName;
|
|
217
218
|
}
|
|
218
219
|
let description = flags.description;
|
|
219
220
|
if (!jsonMode && description === undefined) {
|
|
220
|
-
const { desc } = await
|
|
221
|
+
const { desc } = await this.prompt([{
|
|
221
222
|
type: 'input', name: 'desc', message: 'Description (optional):',
|
|
222
|
-
}]);
|
|
223
|
+
}], null);
|
|
223
224
|
description = desc || undefined;
|
|
224
225
|
}
|
|
225
226
|
const template = await this.storage.savePhaseTemplate(name, description);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class Template extends
|
|
1
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
2
|
+
export default class Template extends PromptCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static aliases: string[];
|
|
5
5
|
static examples: string[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import inquirer from 'inquirer';
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
3
2
|
import { styles } from '../../lib/styles.js';
|
|
4
3
|
import { shouldOutputJson, outputPromptAsJson, buildPromptConfig, createMetadata } from '../../lib/prompt-json.js';
|
|
5
|
-
|
|
4
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
5
|
+
export default class Template extends PromptCommand {
|
|
6
6
|
static description = 'Manage templates (ticket and phase)';
|
|
7
7
|
static aliases = ['templates'];
|
|
8
8
|
static examples = [
|
|
@@ -37,12 +37,12 @@ export default class Template extends Command {
|
|
|
37
37
|
}
|
|
38
38
|
this.log(`\n${styles.emphasis('Templates')}`);
|
|
39
39
|
this.log(styles.muted('Manage ticket and phase templates\n'));
|
|
40
|
-
const { action } = await
|
|
40
|
+
const { action } = await this.prompt([{
|
|
41
41
|
type: 'list',
|
|
42
42
|
name: 'action',
|
|
43
43
|
message: 'What would you like to do?',
|
|
44
|
-
choices: menuChoices.map(c => ({ name: c.name, value: c.value })),
|
|
45
|
-
}]);
|
|
44
|
+
choices: menuChoices.map(c => ({ name: c.name, value: c.value, command: c.command })),
|
|
45
|
+
}], null);
|
|
46
46
|
if (action === 'cancel')
|
|
47
47
|
return;
|
|
48
48
|
switch (action) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Flags, Args } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { shouldOutputJson, outputPromptAsJson, outputSuccessAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
@@ -58,12 +57,13 @@ export default class TemplateSave extends PMOCommand {
|
|
|
58
57
|
outputPromptAsJson(buildPromptConfig('list', 'ticket', 'Select ticket:', choices), createMetadata('template save', flags));
|
|
59
58
|
return;
|
|
60
59
|
}
|
|
61
|
-
const {
|
|
60
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'template save' } : null;
|
|
61
|
+
const { selected } = await this.prompt([{
|
|
62
62
|
type: 'list',
|
|
63
63
|
name: 'selected',
|
|
64
64
|
message: 'Select ticket:',
|
|
65
|
-
choices: tickets.slice(0, 20).map(t => ({ name: `${t.id} - ${t.title}`, value: t.id })),
|
|
66
|
-
}]);
|
|
65
|
+
choices: tickets.slice(0, 20).map(t => ({ name: `${t.id} - ${t.title}`, value: t.id, command: `prlt template save ${t.id} --json` })),
|
|
66
|
+
}], jsonModeConfig);
|
|
67
67
|
ticketId = selected;
|
|
68
68
|
}
|
|
69
69
|
const ticket = await this.storage.getTicket(ticketId);
|
|
@@ -77,19 +77,20 @@ export default class TemplateSave extends PMOCommand {
|
|
|
77
77
|
outputPromptAsJson(buildPromptConfig('input', 'name', 'Template name:', undefined, ticket.category || ticket.title.split(' ')[0]), createMetadata('template save', flags));
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
|
-
const {
|
|
80
|
+
const jsonModeConfig2 = jsonMode ? { flags, commandName: 'template save' } : null;
|
|
81
|
+
const { name } = await this.prompt([{
|
|
81
82
|
type: 'input',
|
|
82
83
|
name: 'name',
|
|
83
84
|
message: 'Template name:',
|
|
84
85
|
default: ticket.category || ticket.title.split(' ')[0],
|
|
85
86
|
validate: (i) => i.length > 0 || 'Required',
|
|
86
|
-
}]);
|
|
87
|
+
}], jsonModeConfig2);
|
|
87
88
|
templateName = name;
|
|
88
89
|
}
|
|
89
90
|
// Get description
|
|
90
91
|
let description = flags.description;
|
|
91
92
|
if (description === undefined && !jsonMode) {
|
|
92
|
-
const { desc } = await
|
|
93
|
+
const { desc } = await this.prompt([{ type: 'input', name: 'desc', message: 'Description (optional):' }], null);
|
|
93
94
|
description = desc || undefined;
|
|
94
95
|
}
|
|
95
96
|
const template = await this.storage.createTicketTemplateFromTicket(ticketId, templateName, description);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Flags, Args } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { shouldOutputJson, outputPromptAsJson, outputSuccessAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
@@ -57,26 +56,26 @@ export default class TemplateUpdate extends PMOCommand {
|
|
|
57
56
|
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select template:', choices), createMetadata('template update', flags));
|
|
58
57
|
return;
|
|
59
58
|
}
|
|
60
|
-
const { selected } = await
|
|
59
|
+
const { selected } = await this.prompt([{
|
|
61
60
|
type: 'list',
|
|
62
61
|
name: 'selected',
|
|
63
62
|
message: 'Select template:',
|
|
64
63
|
choices: editable.map(t => ({ name: `${t.name}${t.description ? ` - ${t.description}` : ''}`, value: t.id })),
|
|
65
|
-
}]);
|
|
64
|
+
}], null);
|
|
66
65
|
templateId = selected;
|
|
67
66
|
}
|
|
68
67
|
// Get updates
|
|
69
68
|
let newName = flags.name;
|
|
70
69
|
let newDescription = flags.description;
|
|
71
70
|
if (!newName && newDescription === undefined && !jsonMode) {
|
|
72
|
-
const { updateName } = await
|
|
71
|
+
const { updateName } = await this.prompt([{
|
|
73
72
|
type: 'input', name: 'updateName', message: 'New name (leave empty to keep):',
|
|
74
|
-
}]);
|
|
73
|
+
}], null);
|
|
75
74
|
if (updateName)
|
|
76
75
|
newName = updateName;
|
|
77
|
-
const { updateDesc } = await
|
|
76
|
+
const { updateDesc } = await this.prompt([{
|
|
78
77
|
type: 'input', name: 'updateDesc', message: 'New description (leave empty to keep):',
|
|
79
|
-
}]);
|
|
78
|
+
}], null);
|
|
80
79
|
if (updateDesc)
|
|
81
80
|
newDescription = updateDesc;
|
|
82
81
|
if (!newName && !newDescription) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export default class TerminalTitle extends Command {
|
|
1
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
2
|
+
export default class TerminalTitle extends PromptCommand {
|
|
4
3
|
static description: string;
|
|
5
4
|
static examples: string[];
|
|
6
5
|
static args: {
|
|
@@ -10,28 +9,5 @@ export default class TerminalTitle extends Command {
|
|
|
10
9
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
10
|
reset: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
11
|
};
|
|
13
|
-
/**
|
|
14
|
-
* Prompt wrapper - drop-in replacement for inquirer.prompt with JSON mode support.
|
|
15
|
-
* Matches the pattern from PMOCommand.prompt().
|
|
16
|
-
*
|
|
17
|
-
* In JSON mode: outputs prompt config as JSON and exits
|
|
18
|
-
* In interactive mode: shows normal inquirer prompt
|
|
19
|
-
*/
|
|
20
|
-
protected prompt<T extends Record<string, unknown>>(questions: Array<{
|
|
21
|
-
type: string;
|
|
22
|
-
name: string;
|
|
23
|
-
message: string;
|
|
24
|
-
choices?: Array<string | {
|
|
25
|
-
name: string;
|
|
26
|
-
value: unknown;
|
|
27
|
-
disabled?: boolean | string;
|
|
28
|
-
command?: string;
|
|
29
|
-
} | unknown>;
|
|
30
|
-
default?: unknown;
|
|
31
|
-
validate?: (input: unknown) => boolean | string;
|
|
32
|
-
}>, jsonModeConfig?: {
|
|
33
|
-
flags: JsonFlags & Record<string, unknown>;
|
|
34
|
-
commandName: string;
|
|
35
|
-
} | null): Promise<T>;
|
|
36
12
|
run(): Promise<void>;
|
|
37
13
|
}
|