@uzukko/agentpm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/taskapp.js +2 -0
- package/dist/api-client.d.ts +2 -0
- package/dist/api-client.js +27 -0
- package/dist/api-client.js.map +1 -0
- package/dist/commands/activity.d.ts +2 -0
- package/dist/commands/activity.js +88 -0
- package/dist/commands/activity.js.map +1 -0
- package/dist/commands/ball.d.ts +2 -0
- package/dist/commands/ball.js +69 -0
- package/dist/commands/ball.js.map +1 -0
- package/dist/commands/client.d.ts +2 -0
- package/dist/commands/client.js +149 -0
- package/dist/commands/client.js.map +1 -0
- package/dist/commands/config-cmd.d.ts +2 -0
- package/dist/commands/config-cmd.js +95 -0
- package/dist/commands/config-cmd.js.map +1 -0
- package/dist/commands/meeting.d.ts +2 -0
- package/dist/commands/meeting.js +100 -0
- package/dist/commands/meeting.js.map +1 -0
- package/dist/commands/milestone.d.ts +2 -0
- package/dist/commands/milestone.js +98 -0
- package/dist/commands/milestone.js.map +1 -0
- package/dist/commands/minutes.d.ts +2 -0
- package/dist/commands/minutes.js +62 -0
- package/dist/commands/minutes.js.map +1 -0
- package/dist/commands/review.d.ts +2 -0
- package/dist/commands/review.js +98 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/scheduling.d.ts +2 -0
- package/dist/commands/scheduling.js +184 -0
- package/dist/commands/scheduling.js.map +1 -0
- package/dist/commands/space.d.ts +2 -0
- package/dist/commands/space.js +69 -0
- package/dist/commands/space.js.map +1 -0
- package/dist/commands/task.d.ts +2 -0
- package/dist/commands/task.js +192 -0
- package/dist/commands/task.js.map +1 -0
- package/dist/commands/wiki.d.ts +2 -0
- package/dist/commands/wiki.js +121 -0
- package/dist/commands/wiki.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +41 -0
- package/dist/config.js.map +1 -0
- package/dist/defaults.d.ts +4 -0
- package/dist/defaults.js +8 -0
- package/dist/defaults.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +2 -0
- package/dist/output.js +140 -0
- package/dist/output.js.map +1 -0
- package/package.json +31 -0
- package/src/api-client.ts +32 -0
- package/src/commands/activity.ts +83 -0
- package/src/commands/ball.ts +64 -0
- package/src/commands/client.ts +135 -0
- package/src/commands/config-cmd.ts +106 -0
- package/src/commands/meeting.ts +91 -0
- package/src/commands/milestone.ts +89 -0
- package/src/commands/minutes.ts +57 -0
- package/src/commands/review.ts +89 -0
- package/src/commands/scheduling.ts +171 -0
- package/src/commands/space.ts +62 -0
- package/src/commands/task.ts +179 -0
- package/src/commands/wiki.ts +110 -0
- package/src/config.ts +56 -0
- package/src/index.ts +51 -0
- package/src/output.ts +139 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { resolveSpaceId } from '../config.js'
|
|
3
|
+
import { callTool } from '../api-client.js'
|
|
4
|
+
import { output, outputError } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export function registerMinutesCommands(program: Command): void {
|
|
7
|
+
const minutes = program.command('minutes').description('Meeting minutes')
|
|
8
|
+
|
|
9
|
+
minutes
|
|
10
|
+
.command('get')
|
|
11
|
+
.description('Get meeting minutes')
|
|
12
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
13
|
+
.requiredOption('--meeting-id <id>', 'Meeting ID')
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
try {
|
|
16
|
+
const result = await callTool('minutes_get', {
|
|
17
|
+
spaceId: resolveSpaceId(opts),
|
|
18
|
+
meetingId: opts.meetingId,
|
|
19
|
+
})
|
|
20
|
+
output(result, program.opts().json)
|
|
21
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
minutes
|
|
25
|
+
.command('update')
|
|
26
|
+
.description('Update meeting minutes (overwrite)')
|
|
27
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
28
|
+
.requiredOption('--meeting-id <id>', 'Meeting ID')
|
|
29
|
+
.requiredOption('--minutes-md <md>', 'Minutes content (Markdown)')
|
|
30
|
+
.action(async (opts) => {
|
|
31
|
+
try {
|
|
32
|
+
const result = await callTool('minutes_update', {
|
|
33
|
+
spaceId: resolveSpaceId(opts),
|
|
34
|
+
meetingId: opts.meetingId,
|
|
35
|
+
minutesMd: opts.minutesMd,
|
|
36
|
+
})
|
|
37
|
+
output(result, program.opts().json)
|
|
38
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
minutes
|
|
42
|
+
.command('append')
|
|
43
|
+
.description('Append to meeting minutes')
|
|
44
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
45
|
+
.requiredOption('--meeting-id <id>', 'Meeting ID')
|
|
46
|
+
.requiredOption('--content <md>', 'Content to append (Markdown)')
|
|
47
|
+
.action(async (opts) => {
|
|
48
|
+
try {
|
|
49
|
+
const result = await callTool('minutes_append', {
|
|
50
|
+
spaceId: resolveSpaceId(opts),
|
|
51
|
+
meetingId: opts.meetingId,
|
|
52
|
+
content: opts.content,
|
|
53
|
+
})
|
|
54
|
+
output(result, program.opts().json)
|
|
55
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
56
|
+
})
|
|
57
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { resolveSpaceId } from '../config.js'
|
|
3
|
+
import { callTool } from '../api-client.js'
|
|
4
|
+
import { output, outputError } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export function registerReviewCommands(program: Command): void {
|
|
7
|
+
const review = program.command('review').description('Review management')
|
|
8
|
+
|
|
9
|
+
review
|
|
10
|
+
.command('list')
|
|
11
|
+
.description('List reviews')
|
|
12
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
13
|
+
.option('--status <status>', 'Filter: open|approved|changes_requested')
|
|
14
|
+
.option('--limit <n>', 'Max results', '20')
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
try {
|
|
17
|
+
const result = await callTool('review_list', {
|
|
18
|
+
spaceId: resolveSpaceId(opts),
|
|
19
|
+
status: opts.status,
|
|
20
|
+
limit: parseInt(opts.limit),
|
|
21
|
+
})
|
|
22
|
+
output(result, program.opts().json)
|
|
23
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
review
|
|
27
|
+
.command('open')
|
|
28
|
+
.description('Open a review')
|
|
29
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
30
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
31
|
+
.requiredOption('--reviewer-ids <ids...>', 'Reviewer UUIDs (1+)')
|
|
32
|
+
.action(async (opts) => {
|
|
33
|
+
try {
|
|
34
|
+
const result = await callTool('review_open', {
|
|
35
|
+
spaceId: resolveSpaceId(opts),
|
|
36
|
+
taskId: opts.taskId,
|
|
37
|
+
reviewerIds: opts.reviewerIds,
|
|
38
|
+
})
|
|
39
|
+
output(result, program.opts().json)
|
|
40
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
review
|
|
44
|
+
.command('approve')
|
|
45
|
+
.description('Approve a review')
|
|
46
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
47
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
48
|
+
.action(async (opts) => {
|
|
49
|
+
try {
|
|
50
|
+
const result = await callTool('review_approve', {
|
|
51
|
+
spaceId: resolveSpaceId(opts),
|
|
52
|
+
taskId: opts.taskId,
|
|
53
|
+
})
|
|
54
|
+
output(result, program.opts().json)
|
|
55
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
review
|
|
59
|
+
.command('block')
|
|
60
|
+
.description('Block a review (request changes)')
|
|
61
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
62
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
63
|
+
.requiredOption('--reason <reason>', 'Block reason')
|
|
64
|
+
.action(async (opts) => {
|
|
65
|
+
try {
|
|
66
|
+
const result = await callTool('review_block', {
|
|
67
|
+
spaceId: resolveSpaceId(opts),
|
|
68
|
+
taskId: opts.taskId,
|
|
69
|
+
reason: opts.reason,
|
|
70
|
+
})
|
|
71
|
+
output(result, program.opts().json)
|
|
72
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
review
|
|
76
|
+
.command('get')
|
|
77
|
+
.description('Get review details with approvals')
|
|
78
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
79
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
80
|
+
.action(async (opts) => {
|
|
81
|
+
try {
|
|
82
|
+
const result = await callTool('review_get', {
|
|
83
|
+
spaceId: resolveSpaceId(opts),
|
|
84
|
+
taskId: opts.taskId,
|
|
85
|
+
})
|
|
86
|
+
output(result, program.opts().json)
|
|
87
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
88
|
+
})
|
|
89
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { resolveSpaceId } from '../config.js'
|
|
3
|
+
import { callTool } from '../api-client.js'
|
|
4
|
+
import { output, outputError } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export function registerSchedulingCommands(program: Command): void {
|
|
7
|
+
const sched = program.command('scheduling').description('Scheduling management')
|
|
8
|
+
|
|
9
|
+
sched
|
|
10
|
+
.command('list')
|
|
11
|
+
.description('List scheduling proposals')
|
|
12
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
13
|
+
.option('--status <status>', 'Filter: open|confirmed|cancelled|expired')
|
|
14
|
+
.option('--limit <n>', 'Max results', '50')
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
try {
|
|
17
|
+
const result = await callTool('list_scheduling_proposals', {
|
|
18
|
+
spaceId: resolveSpaceId(opts),
|
|
19
|
+
status: opts.status,
|
|
20
|
+
limit: parseInt(opts.limit),
|
|
21
|
+
})
|
|
22
|
+
output(result, program.opts().json)
|
|
23
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
sched
|
|
27
|
+
.command('create')
|
|
28
|
+
.description('Create a scheduling proposal (use --stdin for complex input)')
|
|
29
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
30
|
+
.option('--stdin', 'Read JSON params from stdin')
|
|
31
|
+
.action(async (opts) => {
|
|
32
|
+
try {
|
|
33
|
+
let rawParams: Record<string, unknown>
|
|
34
|
+
|
|
35
|
+
if (opts.stdin) {
|
|
36
|
+
const chunks: Buffer[] = []
|
|
37
|
+
for await (const chunk of process.stdin) {
|
|
38
|
+
chunks.push(chunk as Buffer)
|
|
39
|
+
}
|
|
40
|
+
rawParams = JSON.parse(Buffer.concat(chunks).toString('utf-8'))
|
|
41
|
+
rawParams.spaceId ??= resolveSpaceId(opts)
|
|
42
|
+
} else {
|
|
43
|
+
console.error('Error: scheduling create requires --stdin with JSON input for slots/respondents.')
|
|
44
|
+
console.error('Example: echo \'{"title":"Meeting","slots":[...],"respondents":[...]}\' | agentpm scheduling create --stdin')
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const result = await callTool('create_scheduling_proposal', rawParams)
|
|
49
|
+
output(result, program.opts().json)
|
|
50
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
sched
|
|
54
|
+
.command('respond')
|
|
55
|
+
.description('Respond to a scheduling proposal (use --stdin)')
|
|
56
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
57
|
+
.option('--stdin', 'Read JSON params from stdin')
|
|
58
|
+
.requiredOption('--proposal-id <uuid>', 'Proposal UUID')
|
|
59
|
+
.action(async (opts) => {
|
|
60
|
+
try {
|
|
61
|
+
let rawParams: Record<string, unknown>
|
|
62
|
+
|
|
63
|
+
if (opts.stdin) {
|
|
64
|
+
const chunks: Buffer[] = []
|
|
65
|
+
for await (const chunk of process.stdin) {
|
|
66
|
+
chunks.push(chunk as Buffer)
|
|
67
|
+
}
|
|
68
|
+
rawParams = JSON.parse(Buffer.concat(chunks).toString('utf-8'))
|
|
69
|
+
rawParams.spaceId ??= resolveSpaceId(opts)
|
|
70
|
+
rawParams.proposalId ??= opts.proposalId
|
|
71
|
+
} else {
|
|
72
|
+
console.error('Error: scheduling respond requires --stdin with JSON responses.')
|
|
73
|
+
process.exit(1)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const result = await callTool('respond_to_proposal', rawParams)
|
|
77
|
+
output(result, program.opts().json)
|
|
78
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
sched
|
|
82
|
+
.command('confirm')
|
|
83
|
+
.description('Confirm a scheduling slot')
|
|
84
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
85
|
+
.requiredOption('--proposal-id <uuid>', 'Proposal UUID')
|
|
86
|
+
.requiredOption('--slot-id <uuid>', 'Slot UUID to confirm')
|
|
87
|
+
.action(async (opts) => {
|
|
88
|
+
try {
|
|
89
|
+
const result = await callTool('confirm_proposal_slot', {
|
|
90
|
+
spaceId: resolveSpaceId(opts),
|
|
91
|
+
proposalId: opts.proposalId,
|
|
92
|
+
slotId: opts.slotId,
|
|
93
|
+
})
|
|
94
|
+
output(result, program.opts().json)
|
|
95
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
sched
|
|
99
|
+
.command('cancel')
|
|
100
|
+
.description('Cancel or extend a proposal')
|
|
101
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
102
|
+
.requiredOption('--proposal-id <uuid>', 'Proposal UUID')
|
|
103
|
+
.requiredOption('--action <action>', 'cancel|extend')
|
|
104
|
+
.option('--new-expires-at <datetime>', 'New expiry (ISO8601, required for extend)')
|
|
105
|
+
.action(async (opts) => {
|
|
106
|
+
try {
|
|
107
|
+
const result = await callTool('cancel_scheduling_proposal', {
|
|
108
|
+
spaceId: resolveSpaceId(opts),
|
|
109
|
+
proposalId: opts.proposalId,
|
|
110
|
+
action: opts.action,
|
|
111
|
+
newExpiresAt: opts.newExpiresAt,
|
|
112
|
+
})
|
|
113
|
+
output(result, program.opts().json)
|
|
114
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
sched
|
|
118
|
+
.command('responses')
|
|
119
|
+
.description('Get proposal response status')
|
|
120
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
121
|
+
.requiredOption('--proposal-id <uuid>', 'Proposal UUID')
|
|
122
|
+
.action(async (opts) => {
|
|
123
|
+
try {
|
|
124
|
+
const result = await callTool('get_proposal_responses', {
|
|
125
|
+
spaceId: resolveSpaceId(opts),
|
|
126
|
+
proposalId: opts.proposalId,
|
|
127
|
+
})
|
|
128
|
+
output(result, program.opts().json)
|
|
129
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
sched
|
|
133
|
+
.command('suggest')
|
|
134
|
+
.description('Suggest available time slots from Google Calendar')
|
|
135
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
136
|
+
.requiredOption('--user-ids <ids...>', 'User UUIDs to check')
|
|
137
|
+
.requiredOption('--start-date <date>', 'Start date (YYYY-MM-DD)')
|
|
138
|
+
.requiredOption('--end-date <date>', 'End date (YYYY-MM-DD)')
|
|
139
|
+
.option('--duration-minutes <n>', 'Duration in minutes', '60')
|
|
140
|
+
.option('--business-hour-start <n>', 'Business start hour', '9')
|
|
141
|
+
.option('--business-hour-end <n>', 'Business end hour', '18')
|
|
142
|
+
.action(async (opts) => {
|
|
143
|
+
try {
|
|
144
|
+
const result = await callTool('suggest_available_slots', {
|
|
145
|
+
spaceId: resolveSpaceId(opts),
|
|
146
|
+
userIds: opts.userIds,
|
|
147
|
+
startDate: opts.startDate,
|
|
148
|
+
endDate: opts.endDate,
|
|
149
|
+
durationMinutes: parseInt(opts.durationMinutes),
|
|
150
|
+
businessHourStart: parseInt(opts.businessHourStart),
|
|
151
|
+
businessHourEnd: parseInt(opts.businessHourEnd),
|
|
152
|
+
})
|
|
153
|
+
output(result, program.opts().json)
|
|
154
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
sched
|
|
158
|
+
.command('reminder')
|
|
159
|
+
.description('Send reminder to unresponded users')
|
|
160
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
161
|
+
.requiredOption('--proposal-id <uuid>', 'Proposal UUID')
|
|
162
|
+
.action(async (opts) => {
|
|
163
|
+
try {
|
|
164
|
+
const result = await callTool('send_proposal_reminder', {
|
|
165
|
+
spaceId: resolveSpaceId(opts),
|
|
166
|
+
proposalId: opts.proposalId,
|
|
167
|
+
})
|
|
168
|
+
output(result, program.opts().json)
|
|
169
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
170
|
+
})
|
|
171
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { resolveSpaceId } from '../config.js'
|
|
3
|
+
import { callTool } from '../api-client.js'
|
|
4
|
+
import { output, outputError } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export function registerSpaceCommands(program: Command): void {
|
|
7
|
+
const space = program.command('space').description('Space/project management')
|
|
8
|
+
|
|
9
|
+
space
|
|
10
|
+
.command('list')
|
|
11
|
+
.description('List spaces')
|
|
12
|
+
.option('--type <type>', 'Filter: project|personal')
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
try {
|
|
15
|
+
const result = await callTool('space_list', { type: opts.type })
|
|
16
|
+
output(result, program.opts().json)
|
|
17
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
space
|
|
21
|
+
.command('create')
|
|
22
|
+
.description('Create a space')
|
|
23
|
+
.requiredOption('--name <name>', 'Space name')
|
|
24
|
+
.option('--type <type>', 'project|personal', 'project')
|
|
25
|
+
.action(async (opts) => {
|
|
26
|
+
try {
|
|
27
|
+
const result = await callTool('space_create', {
|
|
28
|
+
name: opts.name,
|
|
29
|
+
type: opts.type,
|
|
30
|
+
})
|
|
31
|
+
output(result, program.opts().json)
|
|
32
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
space
|
|
36
|
+
.command('update')
|
|
37
|
+
.description('Update a space')
|
|
38
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
39
|
+
.option('--name <name>', 'New name')
|
|
40
|
+
.action(async (opts) => {
|
|
41
|
+
try {
|
|
42
|
+
const result = await callTool('space_update', {
|
|
43
|
+
spaceId: resolveSpaceId(opts),
|
|
44
|
+
name: opts.name,
|
|
45
|
+
})
|
|
46
|
+
output(result, program.opts().json)
|
|
47
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
space
|
|
51
|
+
.command('get')
|
|
52
|
+
.description('Get space details')
|
|
53
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
54
|
+
.action(async (opts) => {
|
|
55
|
+
try {
|
|
56
|
+
const result = await callTool('space_get', {
|
|
57
|
+
spaceId: resolveSpaceId(opts),
|
|
58
|
+
})
|
|
59
|
+
output(result, program.opts().json)
|
|
60
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
61
|
+
})
|
|
62
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { resolveSpaceId } from '../config.js'
|
|
3
|
+
import { callTool } from '../api-client.js'
|
|
4
|
+
import { output, outputError } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export function registerTaskCommands(program: Command): void {
|
|
7
|
+
const task = program.command('task').description('Task management')
|
|
8
|
+
|
|
9
|
+
task
|
|
10
|
+
.command('list')
|
|
11
|
+
.description('List tasks')
|
|
12
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
13
|
+
.option('--ball <side>', 'Filter: client|internal')
|
|
14
|
+
.option('--status <status>', 'Filter: backlog|todo|in_progress|in_review|done|considering')
|
|
15
|
+
.option('--type <type>', 'Filter: task|spec')
|
|
16
|
+
.option('--client-scope <scope>', 'Filter: deliverable|internal')
|
|
17
|
+
.option('--limit <n>', 'Max results', '50')
|
|
18
|
+
.action(async (opts) => {
|
|
19
|
+
try {
|
|
20
|
+
const result = await callTool('task_list', {
|
|
21
|
+
spaceId: resolveSpaceId(opts),
|
|
22
|
+
ball: opts.ball,
|
|
23
|
+
status: opts.status,
|
|
24
|
+
type: opts.type,
|
|
25
|
+
clientScope: opts.clientScope,
|
|
26
|
+
limit: parseInt(opts.limit),
|
|
27
|
+
})
|
|
28
|
+
output(result, program.opts().json)
|
|
29
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
task
|
|
33
|
+
.command('create')
|
|
34
|
+
.description('Create a task')
|
|
35
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
36
|
+
.requiredOption('--title <title>', 'Task title')
|
|
37
|
+
.option('--description <desc>', 'Task description')
|
|
38
|
+
.option('--type <type>', 'task|spec', 'task')
|
|
39
|
+
.option('--ball <side>', 'client|internal', 'internal')
|
|
40
|
+
.option('--origin <origin>', 'client|internal', 'internal')
|
|
41
|
+
.option('--client-scope <scope>', 'deliverable|internal', 'deliverable')
|
|
42
|
+
.option('--client-owner-ids <ids...>', 'Client owner UUIDs')
|
|
43
|
+
.option('--internal-owner-ids <ids...>', 'Internal owner UUIDs')
|
|
44
|
+
.option('--due-date <date>', 'Due date (YYYY-MM-DD)')
|
|
45
|
+
.option('--assignee-id <uuid>', 'Assignee UUID')
|
|
46
|
+
.option('--milestone-id <uuid>', 'Milestone UUID')
|
|
47
|
+
.option('--spec-path <path>', 'Spec path (required for type=spec)')
|
|
48
|
+
.option('--decision-state <state>', 'considering|decided|implemented')
|
|
49
|
+
.action(async (opts) => {
|
|
50
|
+
try {
|
|
51
|
+
const result = await callTool('task_create', {
|
|
52
|
+
spaceId: resolveSpaceId(opts),
|
|
53
|
+
title: opts.title,
|
|
54
|
+
description: opts.description,
|
|
55
|
+
type: opts.type,
|
|
56
|
+
ball: opts.ball,
|
|
57
|
+
origin: opts.origin,
|
|
58
|
+
clientScope: opts.clientScope,
|
|
59
|
+
clientOwnerIds: opts.clientOwnerIds || [],
|
|
60
|
+
internalOwnerIds: opts.internalOwnerIds || [],
|
|
61
|
+
dueDate: opts.dueDate,
|
|
62
|
+
assigneeId: opts.assigneeId,
|
|
63
|
+
milestoneId: opts.milestoneId,
|
|
64
|
+
specPath: opts.specPath,
|
|
65
|
+
decisionState: opts.decisionState,
|
|
66
|
+
})
|
|
67
|
+
output(result, program.opts().json)
|
|
68
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
task
|
|
72
|
+
.command('get')
|
|
73
|
+
.description('Get task details')
|
|
74
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
75
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
76
|
+
.action(async (opts) => {
|
|
77
|
+
try {
|
|
78
|
+
const result = await callTool('task_get', {
|
|
79
|
+
spaceId: resolveSpaceId(opts),
|
|
80
|
+
taskId: opts.taskId,
|
|
81
|
+
})
|
|
82
|
+
output(result, program.opts().json)
|
|
83
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
task
|
|
87
|
+
.command('update')
|
|
88
|
+
.description('Update a task')
|
|
89
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
90
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
91
|
+
.option('--title <title>', 'New title')
|
|
92
|
+
.option('--description <desc>', 'New description')
|
|
93
|
+
.option('--status <status>', 'New status')
|
|
94
|
+
.option('--due-date <date>', 'New due date')
|
|
95
|
+
.option('--assignee-id <uuid>', 'New assignee')
|
|
96
|
+
.option('--priority <n>', 'Priority (0-3)')
|
|
97
|
+
.option('--client-scope <scope>', 'deliverable|internal')
|
|
98
|
+
.option('--start-date <date>', 'Start date')
|
|
99
|
+
.option('--parent-task-id <uuid>', 'Parent task UUID')
|
|
100
|
+
.option('--actual-hours <n>', 'Actual hours')
|
|
101
|
+
.option('--milestone-id <uuid>', 'Milestone UUID')
|
|
102
|
+
.action(async (opts) => {
|
|
103
|
+
try {
|
|
104
|
+
const result = await callTool('task_update', {
|
|
105
|
+
spaceId: resolveSpaceId(opts),
|
|
106
|
+
taskId: opts.taskId,
|
|
107
|
+
title: opts.title,
|
|
108
|
+
description: opts.description,
|
|
109
|
+
status: opts.status,
|
|
110
|
+
dueDate: opts.dueDate,
|
|
111
|
+
assigneeId: opts.assigneeId,
|
|
112
|
+
priority: opts.priority !== undefined ? parseInt(opts.priority) : undefined,
|
|
113
|
+
clientScope: opts.clientScope,
|
|
114
|
+
startDate: opts.startDate,
|
|
115
|
+
parentTaskId: opts.parentTaskId,
|
|
116
|
+
actualHours: opts.actualHours !== undefined ? parseFloat(opts.actualHours) : undefined,
|
|
117
|
+
milestoneId: opts.milestoneId,
|
|
118
|
+
})
|
|
119
|
+
output(result, program.opts().json)
|
|
120
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
task
|
|
124
|
+
.command('delete')
|
|
125
|
+
.description('Delete a task (dry-run by default)')
|
|
126
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
127
|
+
.requiredOption('--task-id <uuid>', 'Task UUID')
|
|
128
|
+
.option('--no-dry-run', 'Actually delete (requires --confirm-token)')
|
|
129
|
+
.option('--confirm-token <token>', 'Confirmation token from dry-run')
|
|
130
|
+
.action(async (opts) => {
|
|
131
|
+
try {
|
|
132
|
+
const result = await callTool('task_delete', {
|
|
133
|
+
spaceId: resolveSpaceId(opts),
|
|
134
|
+
taskId: opts.taskId,
|
|
135
|
+
dryRun: opts.dryRun !== false,
|
|
136
|
+
confirmToken: opts.confirmToken,
|
|
137
|
+
})
|
|
138
|
+
output(result, program.opts().json)
|
|
139
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
task
|
|
143
|
+
.command('list-my')
|
|
144
|
+
.description('List my tasks across all spaces (scope=user API key required)')
|
|
145
|
+
.option('--ball <side>', 'Filter: client|internal')
|
|
146
|
+
.option('--status <status>', 'Filter by status')
|
|
147
|
+
.option('--client-scope <scope>', 'Filter: deliverable|internal')
|
|
148
|
+
.option('--limit <n>', 'Max results', '50')
|
|
149
|
+
.action(async (opts) => {
|
|
150
|
+
try {
|
|
151
|
+
const result = await callTool('task_list_my', {
|
|
152
|
+
ball: opts.ball,
|
|
153
|
+
status: opts.status,
|
|
154
|
+
clientScope: opts.clientScope,
|
|
155
|
+
limit: parseInt(opts.limit),
|
|
156
|
+
})
|
|
157
|
+
output(result, program.opts().json)
|
|
158
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
task
|
|
162
|
+
.command('stale')
|
|
163
|
+
.description('Find stale tasks')
|
|
164
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
165
|
+
.option('--stale-days <n>', 'Days threshold', '7')
|
|
166
|
+
.option('--ball <side>', 'Filter: client|internal')
|
|
167
|
+
.option('--limit <n>', 'Max results', '50')
|
|
168
|
+
.action(async (opts) => {
|
|
169
|
+
try {
|
|
170
|
+
const result = await callTool('task_stale', {
|
|
171
|
+
spaceId: resolveSpaceId(opts),
|
|
172
|
+
staleDays: parseInt(opts.staleDays),
|
|
173
|
+
ball: opts.ball,
|
|
174
|
+
limit: parseInt(opts.limit),
|
|
175
|
+
})
|
|
176
|
+
output(result, program.opts().json)
|
|
177
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
178
|
+
})
|
|
179
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { resolveSpaceId } from '../config.js'
|
|
3
|
+
import { callTool } from '../api-client.js'
|
|
4
|
+
import { output, outputError } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export function registerWikiCommands(program: Command): void {
|
|
7
|
+
const wiki = program.command('wiki').description('Wiki management')
|
|
8
|
+
|
|
9
|
+
wiki
|
|
10
|
+
.command('list')
|
|
11
|
+
.description('List wiki pages')
|
|
12
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
13
|
+
.option('--limit <n>', 'Max results', '50')
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
try {
|
|
16
|
+
const result = await callTool('wiki_list', {
|
|
17
|
+
spaceId: resolveSpaceId(opts),
|
|
18
|
+
limit: parseInt(opts.limit),
|
|
19
|
+
})
|
|
20
|
+
output(result, program.opts().json)
|
|
21
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
wiki
|
|
25
|
+
.command('get')
|
|
26
|
+
.description('Get wiki page details')
|
|
27
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
28
|
+
.requiredOption('--page-id <id>', 'Wiki page ID')
|
|
29
|
+
.action(async (opts) => {
|
|
30
|
+
try {
|
|
31
|
+
const result = await callTool('wiki_get', {
|
|
32
|
+
spaceId: resolveSpaceId(opts),
|
|
33
|
+
pageId: opts.pageId,
|
|
34
|
+
})
|
|
35
|
+
output(result, program.opts().json)
|
|
36
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
wiki
|
|
40
|
+
.command('create')
|
|
41
|
+
.description('Create a wiki page')
|
|
42
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
43
|
+
.requiredOption('--title <title>', 'Page title')
|
|
44
|
+
.option('--body <body>', 'Page body (Markdown)')
|
|
45
|
+
.option('--tags <tags...>', 'Tags')
|
|
46
|
+
.action(async (opts) => {
|
|
47
|
+
try {
|
|
48
|
+
const result = await callTool('wiki_create', {
|
|
49
|
+
spaceId: resolveSpaceId(opts),
|
|
50
|
+
title: opts.title,
|
|
51
|
+
body: opts.body,
|
|
52
|
+
tags: opts.tags,
|
|
53
|
+
})
|
|
54
|
+
output(result, program.opts().json)
|
|
55
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
wiki
|
|
59
|
+
.command('update')
|
|
60
|
+
.description('Update a wiki page')
|
|
61
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
62
|
+
.requiredOption('--page-id <id>', 'Wiki page ID')
|
|
63
|
+
.option('--title <title>', 'New title')
|
|
64
|
+
.option('--body <body>', 'New body (Markdown)')
|
|
65
|
+
.option('--tags <tags...>', 'New tags')
|
|
66
|
+
.action(async (opts) => {
|
|
67
|
+
try {
|
|
68
|
+
const result = await callTool('wiki_update', {
|
|
69
|
+
spaceId: resolveSpaceId(opts),
|
|
70
|
+
pageId: opts.pageId,
|
|
71
|
+
title: opts.title,
|
|
72
|
+
body: opts.body,
|
|
73
|
+
tags: opts.tags,
|
|
74
|
+
})
|
|
75
|
+
output(result, program.opts().json)
|
|
76
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
wiki
|
|
80
|
+
.command('delete')
|
|
81
|
+
.description('Delete a wiki page')
|
|
82
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
83
|
+
.requiredOption('--page-id <id>', 'Wiki page ID')
|
|
84
|
+
.action(async (opts) => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await callTool('wiki_delete', {
|
|
87
|
+
spaceId: resolveSpaceId(opts),
|
|
88
|
+
pageId: opts.pageId,
|
|
89
|
+
})
|
|
90
|
+
output(result, program.opts().json)
|
|
91
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
wiki
|
|
95
|
+
.command('versions')
|
|
96
|
+
.description('Get wiki page version history')
|
|
97
|
+
.option('-s, --space-id <uuid>', 'Space UUID')
|
|
98
|
+
.requiredOption('--page-id <id>', 'Wiki page ID')
|
|
99
|
+
.option('--limit <n>', 'Max results', '20')
|
|
100
|
+
.action(async (opts) => {
|
|
101
|
+
try {
|
|
102
|
+
const result = await callTool('wiki_versions', {
|
|
103
|
+
spaceId: resolveSpaceId(opts),
|
|
104
|
+
pageId: opts.pageId,
|
|
105
|
+
limit: parseInt(opts.limit),
|
|
106
|
+
})
|
|
107
|
+
output(result, program.opts().json)
|
|
108
|
+
} catch (e) { outputError(e, program.opts().json) }
|
|
109
|
+
})
|
|
110
|
+
}
|