@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.
Files changed (70) hide show
  1. package/bin/taskapp.js +2 -0
  2. package/dist/api-client.d.ts +2 -0
  3. package/dist/api-client.js +27 -0
  4. package/dist/api-client.js.map +1 -0
  5. package/dist/commands/activity.d.ts +2 -0
  6. package/dist/commands/activity.js +88 -0
  7. package/dist/commands/activity.js.map +1 -0
  8. package/dist/commands/ball.d.ts +2 -0
  9. package/dist/commands/ball.js +69 -0
  10. package/dist/commands/ball.js.map +1 -0
  11. package/dist/commands/client.d.ts +2 -0
  12. package/dist/commands/client.js +149 -0
  13. package/dist/commands/client.js.map +1 -0
  14. package/dist/commands/config-cmd.d.ts +2 -0
  15. package/dist/commands/config-cmd.js +95 -0
  16. package/dist/commands/config-cmd.js.map +1 -0
  17. package/dist/commands/meeting.d.ts +2 -0
  18. package/dist/commands/meeting.js +100 -0
  19. package/dist/commands/meeting.js.map +1 -0
  20. package/dist/commands/milestone.d.ts +2 -0
  21. package/dist/commands/milestone.js +98 -0
  22. package/dist/commands/milestone.js.map +1 -0
  23. package/dist/commands/minutes.d.ts +2 -0
  24. package/dist/commands/minutes.js +62 -0
  25. package/dist/commands/minutes.js.map +1 -0
  26. package/dist/commands/review.d.ts +2 -0
  27. package/dist/commands/review.js +98 -0
  28. package/dist/commands/review.js.map +1 -0
  29. package/dist/commands/scheduling.d.ts +2 -0
  30. package/dist/commands/scheduling.js +184 -0
  31. package/dist/commands/scheduling.js.map +1 -0
  32. package/dist/commands/space.d.ts +2 -0
  33. package/dist/commands/space.js +69 -0
  34. package/dist/commands/space.js.map +1 -0
  35. package/dist/commands/task.d.ts +2 -0
  36. package/dist/commands/task.js +192 -0
  37. package/dist/commands/task.js.map +1 -0
  38. package/dist/commands/wiki.d.ts +2 -0
  39. package/dist/commands/wiki.js +121 -0
  40. package/dist/commands/wiki.js.map +1 -0
  41. package/dist/config.d.ts +8 -0
  42. package/dist/config.js +41 -0
  43. package/dist/config.js.map +1 -0
  44. package/dist/defaults.d.ts +4 -0
  45. package/dist/defaults.js +8 -0
  46. package/dist/defaults.js.map +1 -0
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.js +48 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/output.d.ts +2 -0
  51. package/dist/output.js +140 -0
  52. package/dist/output.js.map +1 -0
  53. package/package.json +31 -0
  54. package/src/api-client.ts +32 -0
  55. package/src/commands/activity.ts +83 -0
  56. package/src/commands/ball.ts +64 -0
  57. package/src/commands/client.ts +135 -0
  58. package/src/commands/config-cmd.ts +106 -0
  59. package/src/commands/meeting.ts +91 -0
  60. package/src/commands/milestone.ts +89 -0
  61. package/src/commands/minutes.ts +57 -0
  62. package/src/commands/review.ts +89 -0
  63. package/src/commands/scheduling.ts +171 -0
  64. package/src/commands/space.ts +62 -0
  65. package/src/commands/task.ts +179 -0
  66. package/src/commands/wiki.ts +110 -0
  67. package/src/config.ts +56 -0
  68. package/src/index.ts +51 -0
  69. package/src/output.ts +139 -0
  70. 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
+ }