@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
package/src/config.ts ADDED
@@ -0,0 +1,56 @@
1
+ import { readFileSync, existsSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+ import { homedir } from 'node:os'
4
+ import { setApiConfig } from './api-client.js'
5
+
6
+ const CONFIG_PATH = join(homedir(), '.taskapprc.json')
7
+
8
+ interface CliConfig {
9
+ apiUrl?: string
10
+ apiKey?: string
11
+ defaultSpaceId?: string
12
+ }
13
+
14
+ export function getConfigPath(): string {
15
+ return CONFIG_PATH
16
+ }
17
+
18
+ export function loadCliConfig(cliOpts: {
19
+ apiKey?: string
20
+ spaceId?: string
21
+ }): void {
22
+ let fileConfig: CliConfig = {}
23
+ if (existsSync(CONFIG_PATH)) {
24
+ try {
25
+ fileConfig = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'))
26
+ } catch {
27
+ // ignore invalid config file
28
+ }
29
+ }
30
+
31
+ // Priority: CLI flags > env vars > config file
32
+ const apiUrl = process.env.TASKAPP_API_URL || fileConfig.apiUrl
33
+ const apiKey = cliOpts.apiKey || process.env.TASKAPP_API_KEY || fileConfig.apiKey
34
+
35
+ if (!apiUrl || !apiKey) {
36
+ console.error('Error: Not configured. Run: agentpm login')
37
+ process.exit(1)
38
+ }
39
+
40
+ setApiConfig(apiUrl, apiKey)
41
+
42
+ // Set space ID for resolveSpaceId
43
+ const spaceId = cliOpts.spaceId || process.env.TASKAPP_SPACE_ID || fileConfig.defaultSpaceId
44
+ if (spaceId) {
45
+ process.env.TASKAPP_SPACE_ID = spaceId
46
+ }
47
+ }
48
+
49
+ export function resolveSpaceId(opts: { spaceId?: string }): string {
50
+ const spaceId = opts.spaceId || process.env.TASKAPP_SPACE_ID
51
+ if (!spaceId) {
52
+ console.error('Error: --space-id is required (or set TASKAPP_SPACE_ID / defaultSpaceId in ~/.taskapprc.json)')
53
+ process.exit(1)
54
+ }
55
+ return spaceId
56
+ }
package/src/index.ts ADDED
@@ -0,0 +1,51 @@
1
+ import { Command } from 'commander'
2
+ import { loadCliConfig } from './config.js'
3
+ import { registerTaskCommands } from './commands/task.js'
4
+ import { registerBallCommands } from './commands/ball.js'
5
+ import { registerMeetingCommands } from './commands/meeting.js'
6
+ import { registerReviewCommands } from './commands/review.js'
7
+ import { registerMilestoneCommands } from './commands/milestone.js'
8
+ import { registerSpaceCommands } from './commands/space.js'
9
+ import { registerActivityCommands } from './commands/activity.js'
10
+ import { registerClientCommands } from './commands/client.js'
11
+ import { registerWikiCommands } from './commands/wiki.js'
12
+ import { registerMinutesCommands } from './commands/minutes.js'
13
+ import { registerSchedulingCommands } from './commands/scheduling.js'
14
+ import { registerConfigCommand } from './commands/config-cmd.js'
15
+
16
+ const program = new Command()
17
+
18
+ program
19
+ .name('agentpm')
20
+ .version('0.1.0')
21
+ .description('AgentPM CLI - AI-first task management')
22
+ .option('--json', 'Output raw JSON')
23
+ .option('-s, --space-id <uuid>', 'Override default space ID')
24
+ .option('--api-key <key>', 'Override API key')
25
+ .hook('preAction', (thisCommand, actionCommand) => {
26
+ // Walk up to find the root command name (handles nested subcommands)
27
+ let cmd = actionCommand
28
+ while (cmd.parent && cmd.parent !== thisCommand) {
29
+ cmd = cmd.parent
30
+ }
31
+ // config/login subcommands don't need auth
32
+ if (cmd.name() === 'config' || cmd.name() === 'login') return
33
+
34
+ const opts = thisCommand.opts()
35
+ loadCliConfig({ apiKey: opts.apiKey, spaceId: opts.spaceId })
36
+ })
37
+
38
+ registerTaskCommands(program)
39
+ registerBallCommands(program)
40
+ registerMeetingCommands(program)
41
+ registerReviewCommands(program)
42
+ registerMilestoneCommands(program)
43
+ registerSpaceCommands(program)
44
+ registerActivityCommands(program)
45
+ registerClientCommands(program)
46
+ registerWikiCommands(program)
47
+ registerMinutesCommands(program)
48
+ registerSchedulingCommands(program)
49
+ registerConfigCommand(program)
50
+
51
+ program.parseAsync()
package/src/output.ts ADDED
@@ -0,0 +1,139 @@
1
+ import chalk from 'chalk'
2
+ import Table from 'cli-table3'
3
+
4
+ export function output(data: unknown, jsonMode: boolean): void {
5
+ if (jsonMode) {
6
+ console.log(JSON.stringify(data, null, 2))
7
+ } else {
8
+ if (Array.isArray(data)) {
9
+ printTable(data)
10
+ } else if (data && typeof data === 'object') {
11
+ const obj = data as Record<string, unknown>
12
+ const entries = Object.entries(obj)
13
+
14
+ // Display all array-of-objects properties as tables
15
+ for (const [key, value] of entries) {
16
+ if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'object' && value[0] !== null) {
17
+ console.log(chalk.bold(`${key}:`))
18
+ printTable(value as Record<string, unknown>[])
19
+ console.log()
20
+ }
21
+ }
22
+
23
+ // Print remaining non-array-of-objects values
24
+ for (const [key, value] of entries) {
25
+ if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'object' && value[0] !== null) {
26
+ continue // already printed as table
27
+ }
28
+ if (value === null || value === undefined) continue
29
+ if (Array.isArray(value)) {
30
+ console.log(`${chalk.gray(key)}: ${value.map(v => String(v)).join(', ')}`)
31
+ } else if (typeof value === 'object') {
32
+ console.log(`${chalk.gray(key)}: ${JSON.stringify(value, null, 2)}`)
33
+ } else {
34
+ console.log(`${chalk.gray(key)}: ${formatValue(key, value)}`)
35
+ }
36
+ }
37
+ } else {
38
+ console.log(data)
39
+ }
40
+ }
41
+ }
42
+
43
+ function printTable(rows: unknown[]): void {
44
+ if (rows.length === 0) {
45
+ console.log(chalk.gray('(no results)'))
46
+ return
47
+ }
48
+
49
+ // Collect scalar keys from ALL rows (preserving insertion order from first occurrence)
50
+ const seen = new Set<string>()
51
+ const keys: string[] = []
52
+ for (const row of rows) {
53
+ const r = row as Record<string, unknown>
54
+ for (const k of Object.keys(r)) {
55
+ if (seen.has(k)) continue
56
+ seen.add(k)
57
+ // Include only scalar-ish columns (skip nested objects/arrays)
58
+ const v = r[k]
59
+ if (v === null || v === undefined || typeof v !== 'object' || v instanceof Date) {
60
+ keys.push(k)
61
+ }
62
+ }
63
+ }
64
+
65
+ // Limit columns for readability
66
+ const displayKeys = keys.slice(0, 8)
67
+
68
+ const table = new Table({
69
+ head: displayKeys.map((k) => chalk.cyan(k)),
70
+ style: { head: [], border: [] },
71
+ wordWrap: true,
72
+ })
73
+
74
+ for (const row of rows) {
75
+ const r = row as Record<string, unknown>
76
+ table.push(displayKeys.map((k) => {
77
+ const v = r[k]
78
+ return formatValue(k, v)
79
+ }))
80
+ }
81
+
82
+ console.log(table.toString())
83
+ console.log(chalk.gray(`${rows.length} row(s)`))
84
+ }
85
+
86
+ function formatValue(key: string, value: unknown): string {
87
+ if (value === null || value === undefined) return chalk.gray('-')
88
+ if (typeof value === 'string') {
89
+ // Status coloring
90
+ if (key === 'status' || key === 'ball') {
91
+ return colorStatus(value)
92
+ }
93
+ // Truncate long strings
94
+ if (value.length > 50) return value.slice(0, 47) + '...'
95
+ return value
96
+ }
97
+ if (typeof value === 'number') return chalk.yellow(String(value))
98
+ if (typeof value === 'boolean') return value ? chalk.green('true') : chalk.red('false')
99
+ return String(value)
100
+ }
101
+
102
+ function colorStatus(status: string): string {
103
+ switch (status) {
104
+ case 'done':
105
+ case 'approved':
106
+ case 'confirmed':
107
+ case 'accepted':
108
+ return chalk.green(status)
109
+ case 'in_progress':
110
+ case 'in_review':
111
+ case 'open':
112
+ case 'internal':
113
+ return chalk.blue(status)
114
+ case 'backlog':
115
+ case 'todo':
116
+ case 'planned':
117
+ case 'pending':
118
+ return chalk.yellow(status)
119
+ case 'considering':
120
+ return chalk.magenta(status)
121
+ case 'cancelled':
122
+ case 'expired':
123
+ case 'changes_requested':
124
+ case 'client':
125
+ return chalk.red(status)
126
+ default:
127
+ return status
128
+ }
129
+ }
130
+
131
+ export function outputError(error: unknown, jsonMode: boolean): void {
132
+ const message = error instanceof Error ? error.message : String(error)
133
+ if (jsonMode) {
134
+ console.error(JSON.stringify({ error: message }))
135
+ } else {
136
+ console.error(chalk.red(`Error: ${message}`))
137
+ }
138
+ process.exit(1)
139
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "declaration": true,
14
+ "sourceMap": true,
15
+ "resolveJsonModule": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }