kantban-cli 0.1.8 → 0.1.11

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 (155) hide show
  1. package/dist/chunk-ZCUIGFSP.js +4111 -0
  2. package/dist/chunk-ZCUIGFSP.js.map +1 -0
  3. package/dist/context-7YDNTI3P.js +30 -0
  4. package/dist/context-7YDNTI3P.js.map +1 -0
  5. package/dist/cron-OKQP6QDF.js +112 -0
  6. package/dist/cron-OKQP6QDF.js.map +1 -0
  7. package/dist/index.d.ts +0 -2
  8. package/dist/index.js +179 -44
  9. package/dist/index.js.map +1 -1
  10. package/dist/pipeline-7LG74YA2.js +4098 -0
  11. package/dist/pipeline-7LG74YA2.js.map +1 -0
  12. package/dist/pipeline-init-IGZZOOLK.js +103 -0
  13. package/dist/pipeline-init-IGZZOOLK.js.map +1 -0
  14. package/dist/status-4GFXMVIM.js +128 -0
  15. package/dist/status-4GFXMVIM.js.map +1 -0
  16. package/dist/work-2V33NZAT.js +81 -0
  17. package/dist/work-2V33NZAT.js.map +1 -0
  18. package/package.json +5 -4
  19. package/dist/client.d.ts +0 -38
  20. package/dist/client.d.ts.map +0 -1
  21. package/dist/client.js +0 -163
  22. package/dist/client.js.map +0 -1
  23. package/dist/commands/context.d.ts +0 -3
  24. package/dist/commands/context.d.ts.map +0 -1
  25. package/dist/commands/context.js +0 -27
  26. package/dist/commands/context.js.map +0 -1
  27. package/dist/commands/cron.d.ts +0 -3
  28. package/dist/commands/cron.d.ts.map +0 -1
  29. package/dist/commands/cron.js +0 -106
  30. package/dist/commands/cron.js.map +0 -1
  31. package/dist/commands/pipeline-init.d.ts +0 -2
  32. package/dist/commands/pipeline-init.d.ts.map +0 -1
  33. package/dist/commands/pipeline-init.js +0 -100
  34. package/dist/commands/pipeline-init.js.map +0 -1
  35. package/dist/commands/pipeline.d.ts +0 -4
  36. package/dist/commands/pipeline.d.ts.map +0 -1
  37. package/dist/commands/pipeline.js +0 -1222
  38. package/dist/commands/pipeline.js.map +0 -1
  39. package/dist/commands/status.d.ts +0 -3
  40. package/dist/commands/status.d.ts.map +0 -1
  41. package/dist/commands/status.js +0 -135
  42. package/dist/commands/status.js.map +0 -1
  43. package/dist/commands/work.d.ts +0 -3
  44. package/dist/commands/work.d.ts.map +0 -1
  45. package/dist/commands/work.js +0 -76
  46. package/dist/commands/work.js.map +0 -1
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/lib/advisor.d.ts +0 -108
  49. package/dist/lib/advisor.d.ts.map +0 -1
  50. package/dist/lib/advisor.js +0 -139
  51. package/dist/lib/advisor.js.map +0 -1
  52. package/dist/lib/checkpoint.d.ts +0 -15
  53. package/dist/lib/checkpoint.d.ts.map +0 -1
  54. package/dist/lib/checkpoint.js +0 -49
  55. package/dist/lib/checkpoint.js.map +0 -1
  56. package/dist/lib/constraint-evaluator.d.ts +0 -40
  57. package/dist/lib/constraint-evaluator.d.ts.map +0 -1
  58. package/dist/lib/constraint-evaluator.js +0 -189
  59. package/dist/lib/constraint-evaluator.js.map +0 -1
  60. package/dist/lib/cost-tracker.d.ts +0 -46
  61. package/dist/lib/cost-tracker.d.ts.map +0 -1
  62. package/dist/lib/cost-tracker.js +0 -120
  63. package/dist/lib/cost-tracker.js.map +0 -1
  64. package/dist/lib/evaluator.d.ts +0 -17
  65. package/dist/lib/evaluator.d.ts.map +0 -1
  66. package/dist/lib/evaluator.js +0 -71
  67. package/dist/lib/evaluator.js.map +0 -1
  68. package/dist/lib/event-emitter.d.ts +0 -28
  69. package/dist/lib/event-emitter.d.ts.map +0 -1
  70. package/dist/lib/event-emitter.js +0 -100
  71. package/dist/lib/event-emitter.js.map +0 -1
  72. package/dist/lib/event-queue.d.ts +0 -28
  73. package/dist/lib/event-queue.d.ts.map +0 -1
  74. package/dist/lib/event-queue.js +0 -73
  75. package/dist/lib/event-queue.js.map +0 -1
  76. package/dist/lib/gate-config.d.ts +0 -7
  77. package/dist/lib/gate-config.d.ts.map +0 -1
  78. package/dist/lib/gate-config.js +0 -68
  79. package/dist/lib/gate-config.js.map +0 -1
  80. package/dist/lib/gate-proxy-server.d.ts +0 -16
  81. package/dist/lib/gate-proxy-server.d.ts.map +0 -1
  82. package/dist/lib/gate-proxy-server.js +0 -385
  83. package/dist/lib/gate-proxy-server.js.map +0 -1
  84. package/dist/lib/gate-proxy.d.ts +0 -46
  85. package/dist/lib/gate-proxy.d.ts.map +0 -1
  86. package/dist/lib/gate-proxy.js +0 -104
  87. package/dist/lib/gate-proxy.js.map +0 -1
  88. package/dist/lib/gate-runner.d.ts +0 -13
  89. package/dist/lib/gate-runner.d.ts.map +0 -1
  90. package/dist/lib/gate-runner.js +0 -104
  91. package/dist/lib/gate-runner.js.map +0 -1
  92. package/dist/lib/gate-snapshot.d.ts +0 -12
  93. package/dist/lib/gate-snapshot.d.ts.map +0 -1
  94. package/dist/lib/gate-snapshot.js +0 -49
  95. package/dist/lib/gate-snapshot.js.map +0 -1
  96. package/dist/lib/light-call.d.ts +0 -37
  97. package/dist/lib/light-call.d.ts.map +0 -1
  98. package/dist/lib/light-call.js +0 -62
  99. package/dist/lib/light-call.js.map +0 -1
  100. package/dist/lib/logger.d.ts +0 -22
  101. package/dist/lib/logger.d.ts.map +0 -1
  102. package/dist/lib/logger.js +0 -98
  103. package/dist/lib/logger.js.map +0 -1
  104. package/dist/lib/mcp-config.d.ts +0 -24
  105. package/dist/lib/mcp-config.d.ts.map +0 -1
  106. package/dist/lib/mcp-config.js +0 -115
  107. package/dist/lib/mcp-config.js.map +0 -1
  108. package/dist/lib/orchestrator.d.ts +0 -392
  109. package/dist/lib/orchestrator.d.ts.map +0 -1
  110. package/dist/lib/orchestrator.js +0 -1636
  111. package/dist/lib/orchestrator.js.map +0 -1
  112. package/dist/lib/parse-utils.d.ts +0 -6
  113. package/dist/lib/parse-utils.d.ts.map +0 -1
  114. package/dist/lib/parse-utils.js +0 -64
  115. package/dist/lib/parse-utils.js.map +0 -1
  116. package/dist/lib/prompt-composer.d.ts +0 -131
  117. package/dist/lib/prompt-composer.d.ts.map +0 -1
  118. package/dist/lib/prompt-composer.js +0 -317
  119. package/dist/lib/prompt-composer.js.map +0 -1
  120. package/dist/lib/ralph-loop.d.ts +0 -123
  121. package/dist/lib/ralph-loop.d.ts.map +0 -1
  122. package/dist/lib/ralph-loop.js +0 -383
  123. package/dist/lib/ralph-loop.js.map +0 -1
  124. package/dist/lib/reaper.d.ts +0 -14
  125. package/dist/lib/reaper.d.ts.map +0 -1
  126. package/dist/lib/reaper.js +0 -114
  127. package/dist/lib/reaper.js.map +0 -1
  128. package/dist/lib/replanner.d.ts +0 -49
  129. package/dist/lib/replanner.d.ts.map +0 -1
  130. package/dist/lib/replanner.js +0 -61
  131. package/dist/lib/replanner.js.map +0 -1
  132. package/dist/lib/run-memory.d.ts +0 -37
  133. package/dist/lib/run-memory.d.ts.map +0 -1
  134. package/dist/lib/run-memory.js +0 -115
  135. package/dist/lib/run-memory.js.map +0 -1
  136. package/dist/lib/stream-parser.d.ts +0 -20
  137. package/dist/lib/stream-parser.d.ts.map +0 -1
  138. package/dist/lib/stream-parser.js +0 -65
  139. package/dist/lib/stream-parser.js.map +0 -1
  140. package/dist/lib/stuck-detector.d.ts +0 -47
  141. package/dist/lib/stuck-detector.d.ts.map +0 -1
  142. package/dist/lib/stuck-detector.js +0 -105
  143. package/dist/lib/stuck-detector.js.map +0 -1
  144. package/dist/lib/tool-profiles.d.ts +0 -19
  145. package/dist/lib/tool-profiles.d.ts.map +0 -1
  146. package/dist/lib/tool-profiles.js +0 -22
  147. package/dist/lib/tool-profiles.js.map +0 -1
  148. package/dist/lib/worktree.d.ts +0 -12
  149. package/dist/lib/worktree.d.ts.map +0 -1
  150. package/dist/lib/worktree.js +0 -29
  151. package/dist/lib/worktree.js.map +0 -1
  152. package/dist/lib/ws-client.d.ts +0 -31
  153. package/dist/lib/ws-client.d.ts.map +0 -1
  154. package/dist/lib/ws-client.js +0 -113
  155. package/dist/lib/ws-client.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ // src/commands/pipeline-init.ts
2
+ import { existsSync, readFileSync, writeFileSync } from "fs";
3
+ import { join } from "path";
4
+ var GATE_FILE = "pipeline.gates.yaml";
5
+ function detectProjectType(cwd) {
6
+ if (existsSync(join(cwd, "package.json"))) {
7
+ const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
8
+ const scripts = pkg.scripts ?? {};
9
+ const pm = existsSync(join(cwd, "pnpm-lock.yaml")) ? "pnpm" : existsSync(join(cwd, "yarn.lock")) ? "yarn" : "npm";
10
+ return {
11
+ type: "node",
12
+ testCommand: scripts.test ? `${pm} test` : `${pm} vitest run`,
13
+ typecheckCommand: scripts.typecheck ? `${pm} typecheck` : `${pm} tsc --noEmit`,
14
+ lintCommand: scripts.lint ? `${pm} lint` : `${pm} eslint .`,
15
+ buildCommand: scripts.build ? `${pm} build` : 'echo "no build configured"'
16
+ };
17
+ }
18
+ if (existsSync(join(cwd, "Cargo.toml"))) {
19
+ return { type: "rust", testCommand: "cargo test", typecheckCommand: "cargo check", lintCommand: "cargo clippy", buildCommand: "cargo build" };
20
+ }
21
+ if (existsSync(join(cwd, "pyproject.toml")) || existsSync(join(cwd, "setup.py"))) {
22
+ return { type: "python", testCommand: "pytest", typecheckCommand: "mypy .", lintCommand: "ruff check .", buildCommand: 'echo "no build configured"' };
23
+ }
24
+ if (existsSync(join(cwd, "go.mod"))) {
25
+ return { type: "go", testCommand: "go test ./...", typecheckCommand: "go vet ./...", lintCommand: "golangci-lint run", buildCommand: "go build ./..." };
26
+ }
27
+ return { type: "unknown", testCommand: 'echo "configure your test command"', typecheckCommand: 'echo "configure your typecheck command"', lintCommand: 'echo "configure your lint command"', buildCommand: 'echo "configure your build command"' };
28
+ }
29
+ function yamlQuote(s) {
30
+ return `'${s.replace(/'/g, "''")}'`;
31
+ }
32
+ function generateGateFile(detection) {
33
+ return `# pipeline.gates.yaml \u2014 Gate definitions for KantBan pipeline
34
+ # Detected project type: ${detection.type}
35
+ #
36
+ # Gates are shell commands that produce pass/fail results.
37
+ # Required gates block ticket movement. Advisory gates show output but don't block.
38
+
39
+ default:
40
+ - name: typecheck
41
+ run: ${yamlQuote(detection.typecheckCommand)}
42
+ required: true
43
+ timeout: 60s
44
+
45
+ - name: tests
46
+ run: ${yamlQuote(detection.testCommand)}
47
+ required: true
48
+ timeout: 120s
49
+
50
+ - name: lint
51
+ run: ${yamlQuote(detection.lintCommand)}
52
+ required: false # advisory \u2014 output shown but doesn't block
53
+
54
+ # Column-specific overrides \u2014 matched by column name (case-insensitive)
55
+ # columns:
56
+ # implementation:
57
+ # extend: true # inherit default gates, add more
58
+ # gates:
59
+ # - name: build
60
+ # run: ${yamlQuote(detection.buildCommand)}
61
+ # required: true
62
+ # timeout: 120s
63
+ #
64
+ # qa:
65
+ # extend: false # replace default gates entirely
66
+ # gates:
67
+ # - name: e2e
68
+ # run: "echo 'configure your e2e test command'"
69
+ # required: true
70
+ # timeout: 300s
71
+
72
+ settings:
73
+ # cwd: .
74
+ env:
75
+ CI: "true"
76
+ total_timeout: 300s
77
+ budget:
78
+ max_input_tokens: 5000000
79
+ max_output_tokens: 1500000
80
+ warn_pct: 75
81
+ `;
82
+ }
83
+ async function runPipelineInit() {
84
+ const cwd = process.cwd();
85
+ const filePath = join(cwd, GATE_FILE);
86
+ if (existsSync(filePath)) {
87
+ console.error(`Error: ${GATE_FILE} already exists in ${cwd}`);
88
+ console.error("Edit the existing file or delete it to regenerate.");
89
+ process.exit(1);
90
+ }
91
+ const detection = detectProjectType(cwd);
92
+ const content = generateGateFile(detection);
93
+ writeFileSync(filePath, content);
94
+ console.log(`Created ${GATE_FILE} (detected: ${detection.type} project)`);
95
+ console.log(`
96
+ Next steps:`);
97
+ console.log(` 1. Review and customize the gate file`);
98
+ console.log(` 2. Run: kantban pipeline <board-id>`);
99
+ }
100
+ export {
101
+ runPipelineInit
102
+ };
103
+ //# sourceMappingURL=pipeline-init-IGZZOOLK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/pipeline-init.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst GATE_FILE = 'pipeline.gates.yaml';\n\ninterface ProjectDetection {\n type: string;\n testCommand: string;\n typecheckCommand: string;\n lintCommand: string;\n buildCommand: string;\n}\n\nfunction detectProjectType(cwd: string): ProjectDetection {\n if (existsSync(join(cwd, 'package.json'))) {\n const pkg = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf-8')) as {\n scripts?: Record<string, string>;\n };\n const scripts = pkg.scripts ?? {};\n const pm = existsSync(join(cwd, 'pnpm-lock.yaml')) ? 'pnpm'\n : existsSync(join(cwd, 'yarn.lock')) ? 'yarn' : 'npm';\n return {\n type: 'node',\n testCommand: scripts.test ? `${pm} test` : `${pm} vitest run`,\n typecheckCommand: scripts.typecheck ? `${pm} typecheck` : `${pm} tsc --noEmit`,\n lintCommand: scripts.lint ? `${pm} lint` : `${pm} eslint .`,\n buildCommand: scripts.build ? `${pm} build` : 'echo \"no build configured\"',\n };\n }\n if (existsSync(join(cwd, 'Cargo.toml'))) {\n return { type: 'rust', testCommand: 'cargo test', typecheckCommand: 'cargo check', lintCommand: 'cargo clippy', buildCommand: 'cargo build' };\n }\n if (existsSync(join(cwd, 'pyproject.toml')) || existsSync(join(cwd, 'setup.py'))) {\n return { type: 'python', testCommand: 'pytest', typecheckCommand: 'mypy .', lintCommand: 'ruff check .', buildCommand: 'echo \"no build configured\"' };\n }\n if (existsSync(join(cwd, 'go.mod'))) {\n return { type: 'go', testCommand: 'go test ./...', typecheckCommand: 'go vet ./...', lintCommand: 'golangci-lint run', buildCommand: 'go build ./...' };\n }\n return { type: 'unknown', testCommand: 'echo \"configure your test command\"', typecheckCommand: 'echo \"configure your typecheck command\"', lintCommand: 'echo \"configure your lint command\"', buildCommand: 'echo \"configure your build command\"' };\n}\n\n/** YAML-safe single-quoting: escapes internal single quotes by doubling them */\nfunction yamlQuote(s: string): string {\n return `'${s.replace(/'/g, \"''\")}'`;\n}\n\nfunction generateGateFile(detection: ProjectDetection): string {\n return `# pipeline.gates.yaml — Gate definitions for KantBan pipeline\n# Detected project type: ${detection.type}\n#\n# Gates are shell commands that produce pass/fail results.\n# Required gates block ticket movement. Advisory gates show output but don't block.\n\ndefault:\n - name: typecheck\n run: ${yamlQuote(detection.typecheckCommand)}\n required: true\n timeout: 60s\n\n - name: tests\n run: ${yamlQuote(detection.testCommand)}\n required: true\n timeout: 120s\n\n - name: lint\n run: ${yamlQuote(detection.lintCommand)}\n required: false # advisory — output shown but doesn't block\n\n# Column-specific overrides — matched by column name (case-insensitive)\n# columns:\n# implementation:\n# extend: true # inherit default gates, add more\n# gates:\n# - name: build\n# run: ${yamlQuote(detection.buildCommand)}\n# required: true\n# timeout: 120s\n#\n# qa:\n# extend: false # replace default gates entirely\n# gates:\n# - name: e2e\n# run: \"echo 'configure your e2e test command'\"\n# required: true\n# timeout: 300s\n\nsettings:\n # cwd: .\n env:\n CI: \"true\"\n total_timeout: 300s\n budget:\n max_input_tokens: 5000000\n max_output_tokens: 1500000\n warn_pct: 75\n`;\n}\n\nexport async function runPipelineInit(): Promise<void> {\n const cwd = process.cwd();\n const filePath = join(cwd, GATE_FILE);\n\n if (existsSync(filePath)) {\n console.error(`Error: ${GATE_FILE} already exists in ${cwd}`);\n console.error('Edit the existing file or delete it to regenerate.');\n process.exit(1);\n }\n\n const detection = detectProjectType(cwd);\n const content = generateGateFile(detection);\n writeFileSync(filePath, content);\n\n console.log(`Created ${GATE_FILE} (detected: ${detection.type} project)`);\n console.log(`\\nNext steps:`);\n console.log(` 1. Review and customize the gate file`);\n console.log(` 2. Run: kantban pipeline <board-id>`);\n}\n"],"mappings":";AAAA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,YAAY;AAErB,IAAM,YAAY;AAUlB,SAAS,kBAAkB,KAA+B;AACxD,MAAI,WAAW,KAAK,KAAK,cAAc,CAAC,GAAG;AACzC,UAAM,MAAM,KAAK,MAAM,aAAa,KAAK,KAAK,cAAc,GAAG,OAAO,CAAC;AAGvE,UAAM,UAAU,IAAI,WAAW,CAAC;AAChC,UAAM,KAAK,WAAW,KAAK,KAAK,gBAAgB,CAAC,IAAI,SACjD,WAAW,KAAK,KAAK,WAAW,CAAC,IAAI,SAAS;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa,QAAQ,OAAO,GAAG,EAAE,UAAU,GAAG,EAAE;AAAA,MAChD,kBAAkB,QAAQ,YAAY,GAAG,EAAE,eAAe,GAAG,EAAE;AAAA,MAC/D,aAAa,QAAQ,OAAO,GAAG,EAAE,UAAU,GAAG,EAAE;AAAA,MAChD,cAAc,QAAQ,QAAQ,GAAG,EAAE,WAAW;AAAA,IAChD;AAAA,EACF;AACA,MAAI,WAAW,KAAK,KAAK,YAAY,CAAC,GAAG;AACvC,WAAO,EAAE,MAAM,QAAQ,aAAa,cAAc,kBAAkB,eAAe,aAAa,gBAAgB,cAAc,cAAc;AAAA,EAC9I;AACA,MAAI,WAAW,KAAK,KAAK,gBAAgB,CAAC,KAAK,WAAW,KAAK,KAAK,UAAU,CAAC,GAAG;AAChF,WAAO,EAAE,MAAM,UAAU,aAAa,UAAU,kBAAkB,UAAU,aAAa,gBAAgB,cAAc,6BAA6B;AAAA,EACtJ;AACA,MAAI,WAAW,KAAK,KAAK,QAAQ,CAAC,GAAG;AACnC,WAAO,EAAE,MAAM,MAAM,aAAa,iBAAiB,kBAAkB,gBAAgB,aAAa,qBAAqB,cAAc,iBAAiB;AAAA,EACxJ;AACA,SAAO,EAAE,MAAM,WAAW,aAAa,sCAAsC,kBAAkB,2CAA2C,aAAa,sCAAsC,cAAc,sCAAsC;AACnP;AAGA,SAAS,UAAU,GAAmB;AACpC,SAAO,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC;AAClC;AAEA,SAAS,iBAAiB,WAAqC;AAC7D,SAAO;AAAA,2BACkB,UAAU,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAO9B,UAAU,UAAU,gBAAgB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,WAKrC,UAAU,UAAU,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,WAKhC,UAAU,UAAU,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAS1B,UAAU,UAAU,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBlD;AAEA,eAAsB,kBAAiC;AACrD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,WAAW,KAAK,KAAK,SAAS;AAEpC,MAAI,WAAW,QAAQ,GAAG;AACxB,YAAQ,MAAM,UAAU,SAAS,sBAAsB,GAAG,EAAE;AAC5D,YAAQ,MAAM,oDAAoD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,kBAAkB,GAAG;AACvC,QAAM,UAAU,iBAAiB,SAAS;AAC1C,gBAAc,UAAU,OAAO;AAE/B,UAAQ,IAAI,WAAW,SAAS,eAAe,UAAU,IAAI,WAAW;AACxE,UAAQ,IAAI;AAAA,YAAe;AAC3B,UAAQ,IAAI,yCAAyC;AACrD,UAAQ,IAAI,uCAAuC;AACrD;","names":[]}
@@ -0,0 +1,128 @@
1
+ // src/commands/status.ts
2
+ import { readFileSync, existsSync, statSync, readdirSync } from "fs";
3
+ import { homedir } from "os";
4
+ import { join } from "path";
5
+ function formatUptime(ms) {
6
+ const totalMinutes = Math.floor(ms / 6e4);
7
+ const hours = Math.floor(totalMinutes / 60);
8
+ const minutes = totalMinutes % 60;
9
+ if (hours > 0) return `${String(hours)}h ${String(minutes)}m`;
10
+ return `${String(minutes)}m`;
11
+ }
12
+ function isProcessRunning(pid) {
13
+ try {
14
+ process.kill(pid, 0);
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+ function showPipelineInfo(boardId) {
21
+ const pipelineDir = join(homedir(), ".kantban", "pipelines", boardId);
22
+ const pidFile = join(pipelineDir, "orchestrator.pid");
23
+ if (!existsSync(pidFile)) {
24
+ console.log("\nPipeline: not running");
25
+ return;
26
+ }
27
+ const pidContent = readFileSync(pidFile, "utf8").trim();
28
+ const pid = Number(pidContent);
29
+ if (isNaN(pid) || pid <= 0) {
30
+ console.log("\nOrchestrator: not running (invalid PID file)");
31
+ return;
32
+ }
33
+ if (!isProcessRunning(pid)) {
34
+ console.log("\nOrchestrator: not running (stale PID file)");
35
+ return;
36
+ }
37
+ const pidStat = statSync(pidFile);
38
+ const uptimeMs = Date.now() - pidStat.mtimeMs;
39
+ console.log(`
40
+ Orchestrator: running (PID: ${String(pid)}, uptime: ${formatUptime(uptimeMs)})`);
41
+ if (!existsSync(pipelineDir)) return;
42
+ const entries = readdirSync(pipelineDir, { withFileTypes: true });
43
+ const ticketDirs = entries.filter((e) => e.isDirectory());
44
+ if (ticketDirs.length === 0) return;
45
+ const recentLoops = [];
46
+ for (const dir of ticketDirs) {
47
+ const ticketDir = join(pipelineDir, dir.name);
48
+ const files = readdirSync(ticketDir).filter((f) => f.startsWith("iteration-") && f.endsWith(".log"));
49
+ if (files.length === 0) continue;
50
+ files.sort();
51
+ const latestFile = files[files.length - 1];
52
+ const logPath = join(ticketDir, latestFile);
53
+ try {
54
+ const logContent = readFileSync(logPath, "utf8");
55
+ const logData = JSON.parse(logContent);
56
+ recentLoops.push({
57
+ ticket: dir.name,
58
+ lastIteration: Number(logData["iteration"] ?? 0),
59
+ outcome: String(logData["outcome"] ?? "unknown"),
60
+ timestamp: String(logData["timestamp"] ?? "")
61
+ });
62
+ } catch {
63
+ }
64
+ }
65
+ if (recentLoops.length > 0) {
66
+ recentLoops.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
67
+ console.log(` Active/recent loops (${String(recentLoops.length)}):`);
68
+ for (const loop of recentLoops.slice(0, 10)) {
69
+ console.log(` ${loop.ticket} iter:${String(loop.lastIteration)} ${loop.outcome}`);
70
+ }
71
+ if (recentLoops.length > 10) {
72
+ console.log(` ... and ${String(recentLoops.length - 10)} more`);
73
+ }
74
+ }
75
+ }
76
+ async function runStatus(client, args) {
77
+ const [boardId] = args;
78
+ if (!boardId) {
79
+ console.error("Usage: kantban status <board-id>");
80
+ process.exit(1);
81
+ }
82
+ const projectId = process.env["KANTBAN_PROJECT_ID"];
83
+ if (!projectId) {
84
+ console.error("Error: KANTBAN_PROJECT_ID required");
85
+ process.exit(1);
86
+ }
87
+ const data = await client.get(
88
+ `/projects/${projectId}/pipeline-context`,
89
+ { boardId }
90
+ );
91
+ const columns = data["columns"];
92
+ const cb = data["circuit_breaker"];
93
+ const board = data["board"];
94
+ console.log(`Pipeline Status: ${board?.["name"] ?? "Unknown Board"}`);
95
+ console.log("\u2500".repeat(60));
96
+ if (columns) {
97
+ for (const col of columns) {
98
+ const prompt = col["has_prompt"] ? "\u{1F4C4}" : " ";
99
+ const name = String(col["name"] ?? "(unnamed)");
100
+ const count = Number(col["ticket_count"] ?? 0);
101
+ const goal = col["goal"] ? ` \u2014 ${String(col["goal"])}` : "";
102
+ console.log(`${prompt} ${name} (${count} tickets)${goal}`);
103
+ }
104
+ }
105
+ if (cb?.["threshold"]) {
106
+ console.log(`
107
+ Circuit Breaker: threshold=${String(cb["threshold"])}`);
108
+ }
109
+ const bottlenecks = await client.get(
110
+ `/projects/${projectId}/boards/${boardId}/bottlenecks`
111
+ );
112
+ const stuckCount = bottlenecks["stuck_tickets"]?.length ?? 0;
113
+ const wipCount = bottlenecks["wip_violations"]?.length ?? 0;
114
+ if (stuckCount > 0 || wipCount > 0) {
115
+ console.log(`
116
+ Warnings: ${stuckCount} stuck, ${wipCount} WIP violations`);
117
+ } else {
118
+ console.log("\nAll clear.");
119
+ }
120
+ try {
121
+ showPipelineInfo(boardId);
122
+ } catch {
123
+ }
124
+ }
125
+ export {
126
+ runStatus
127
+ };
128
+ //# sourceMappingURL=status-4GFXMVIM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/status.ts"],"sourcesContent":["import { readFileSync, existsSync, statSync, readdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { KantBanCLIClient } from '../client.js';\n\n// ---------------------------------------------------------------------------\n// Pipeline runtime info helper\n// ---------------------------------------------------------------------------\n\nfunction formatUptime(ms: number): string {\n const totalMinutes = Math.floor(ms / 60_000);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n if (hours > 0) return `${String(hours)}h ${String(minutes)}m`;\n return `${String(minutes)}m`;\n}\n\nfunction isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction showPipelineInfo(boardId: string): void {\n const pipelineDir = join(homedir(), '.kantban', 'pipelines', boardId);\n const pidFile = join(pipelineDir, 'orchestrator.pid');\n\n if (!existsSync(pidFile)) {\n console.log('\\nPipeline: not running');\n return;\n }\n\n const pidContent = readFileSync(pidFile, 'utf8').trim();\n const pid = Number(pidContent);\n if (isNaN(pid) || pid <= 0) {\n console.log('\\nOrchestrator: not running (invalid PID file)');\n return;\n }\n\n if (!isProcessRunning(pid)) {\n console.log('\\nOrchestrator: not running (stale PID file)');\n return;\n }\n\n // Process is running — calculate uptime from PID file mtime\n const pidStat = statSync(pidFile);\n const uptimeMs = Date.now() - pidStat.mtimeMs;\n console.log(`\\nOrchestrator: running (PID: ${String(pid)}, uptime: ${formatUptime(uptimeMs)})`);\n\n // Scan for recent iteration logs to show active/recent loop info\n if (!existsSync(pipelineDir)) return;\n\n const entries = readdirSync(pipelineDir, { withFileTypes: true });\n const ticketDirs = entries.filter((e) => e.isDirectory());\n\n if (ticketDirs.length === 0) return;\n\n const recentLoops: Array<{ ticket: string; lastIteration: number; outcome: string; timestamp: string }> = [];\n\n for (const dir of ticketDirs) {\n const ticketDir = join(pipelineDir, dir.name);\n const files = readdirSync(ticketDir).filter((f) => f.startsWith('iteration-') && f.endsWith('.log'));\n if (files.length === 0) continue;\n\n // Get the latest iteration log\n files.sort();\n const latestFile = files[files.length - 1]!;\n const logPath = join(ticketDir, latestFile);\n\n try {\n const logContent = readFileSync(logPath, 'utf8');\n const logData = JSON.parse(logContent) as Record<string, unknown>;\n recentLoops.push({\n ticket: dir.name,\n lastIteration: Number(logData['iteration'] ?? 0),\n outcome: String(logData['outcome'] ?? 'unknown'),\n timestamp: String(logData['timestamp'] ?? ''),\n });\n } catch {\n // Skip malformed log files\n }\n }\n\n if (recentLoops.length > 0) {\n // Sort by timestamp descending to show most recent first\n recentLoops.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n console.log(` Active/recent loops (${String(recentLoops.length)}):`);\n for (const loop of recentLoops.slice(0, 10)) {\n console.log(` ${loop.ticket} iter:${String(loop.lastIteration)} ${loop.outcome}`);\n }\n if (recentLoops.length > 10) {\n console.log(` ... and ${String(recentLoops.length - 10)} more`);\n }\n }\n}\n\nexport async function runStatus(client: KantBanCLIClient, args: string[]): Promise<void> {\n const [boardId] = args;\n if (!boardId) {\n console.error('Usage: kantban status <board-id>');\n process.exit(1);\n }\n\n const projectId = process.env['KANTBAN_PROJECT_ID'];\n if (!projectId) {\n console.error('Error: KANTBAN_PROJECT_ID required');\n process.exit(1);\n }\n\n const data = await client.get<Record<string, unknown>>(\n `/projects/${projectId}/pipeline-context`,\n { boardId },\n );\n\n const columns = data['columns'] as Array<Record<string, unknown>> | undefined;\n const cb = data['circuit_breaker'] as Record<string, unknown> | undefined;\n const board = data['board'] as Record<string, unknown> | undefined;\n\n console.log(`Pipeline Status: ${board?.['name'] ?? 'Unknown Board'}`);\n console.log('\\u2500'.repeat(60));\n\n if (columns) {\n for (const col of columns) {\n const prompt = col['has_prompt'] ? '\\u{1F4C4}' : ' ';\n const name = String(col['name'] ?? '(unnamed)');\n const count = Number(col['ticket_count'] ?? 0);\n const goal = col['goal'] ? ` \\u2014 ${String(col['goal'])}` : '';\n console.log(`${prompt} ${name} (${count} tickets)${goal}`);\n }\n }\n\n if (cb?.['threshold']) {\n console.log(`\\nCircuit Breaker: threshold=${String(cb['threshold'])}`);\n }\n\n // Fetch bottleneck info\n const bottlenecks = await client.get<Record<string, unknown>>(\n `/projects/${projectId}/boards/${boardId}/bottlenecks`,\n );\n const stuckCount = (bottlenecks['stuck_tickets'] as unknown[] | undefined)?.length ?? 0;\n const wipCount = (bottlenecks['wip_violations'] as unknown[] | undefined)?.length ?? 0;\n\n if (stuckCount > 0 || wipCount > 0) {\n console.log(`\\nWarnings: ${stuckCount} stuck, ${wipCount} WIP violations`);\n } else {\n console.log('\\nAll clear.');\n }\n\n // Show pipeline orchestrator runtime info (non-fatal on error)\n try {\n showPipelineInfo(boardId);\n } catch {\n // Pipeline info is supplementary — don't break the status command\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,81 @@
1
+ // src/commands/work.ts
2
+ import { spawn } from "child_process";
3
+ function asRecord(val) {
4
+ return typeof val === "object" && val !== null && !Array.isArray(val) ? val : void 0;
5
+ }
6
+ function asStringArray(val) {
7
+ return Array.isArray(val) ? val.map((v) => String(v)) : [];
8
+ }
9
+ async function runWork(client, args) {
10
+ const [ticketId] = args;
11
+ if (!ticketId) {
12
+ console.error("Usage: kantban work <ticket-id> [--dry-run]");
13
+ process.exit(1);
14
+ }
15
+ const projectId = process.env["KANTBAN_PROJECT_ID"];
16
+ if (!projectId) {
17
+ console.error("Error: KANTBAN_PROJECT_ID required");
18
+ process.exit(1);
19
+ }
20
+ const context = await client.get(
21
+ `/projects/${projectId}/pipeline-context`,
22
+ { ticketId }
23
+ );
24
+ const ticket = asRecord(context["ticket"]);
25
+ const signals = asStringArray(context["signals"]);
26
+ const rules = context["transition_rules"] ? String(context["transition_rules"]) : void 0;
27
+ const title = String(ticket?.["title"] ?? "Untitled");
28
+ const description = ticket?.["description"] ? String(ticket["description"]) : "";
29
+ const ticketIdStr = String(ticket?.["id"] ?? ticketId);
30
+ const promptLines = [
31
+ `# Task: ${title}`,
32
+ ""
33
+ ];
34
+ if (description) {
35
+ promptLines.push(description, "");
36
+ }
37
+ if (signals.length > 0) {
38
+ promptLines.push("## Signals");
39
+ for (const s of signals) {
40
+ promptLines.push(`- ${s}`);
41
+ }
42
+ promptLines.push("");
43
+ }
44
+ if (rules) {
45
+ promptLines.push("## Transition Rules", rules, "");
46
+ }
47
+ const toolPrefix = context["tool_prefix"] ? String(context["tool_prefix"]) : "kantban_";
48
+ promptLines.push(
49
+ `## Tool Prefix: ${toolPrefix}`,
50
+ `## Ticket ID: ${ticketIdStr}`,
51
+ `## Project ID: ${projectId}`
52
+ );
53
+ const prompt = promptLines.join("\n");
54
+ console.log(`Starting Claude session for: ${title}`);
55
+ console.log(`Ticket: ${ticketIdStr}`);
56
+ const dryRun = args.includes("--dry-run");
57
+ if (dryRun) {
58
+ console.log("\n--- Prompt (dry run) ---");
59
+ console.log(prompt);
60
+ return;
61
+ }
62
+ const child = spawn("claude", ["-p", prompt], {
63
+ stdio: "inherit",
64
+ env: { ...process.env }
65
+ });
66
+ await new Promise((resolve) => {
67
+ child.on("error", (err) => {
68
+ console.error(`Failed to start claude: ${err.message}`);
69
+ process.exitCode = 1;
70
+ resolve();
71
+ });
72
+ child.on("exit", (code) => {
73
+ process.exitCode = code ?? 0;
74
+ resolve();
75
+ });
76
+ });
77
+ }
78
+ export {
79
+ runWork
80
+ };
81
+ //# sourceMappingURL=work-2V33NZAT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/work.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\nimport type { KantBanCLIClient } from '../client.js';\n\nfunction asRecord(val: unknown): Record<string, unknown> | undefined {\n return typeof val === 'object' && val !== null && !Array.isArray(val)\n ? (val as Record<string, unknown>)\n : undefined;\n}\n\nfunction asStringArray(val: unknown): string[] {\n return Array.isArray(val) ? val.map((v) => String(v)) : [];\n}\n\nexport async function runWork(client: KantBanCLIClient, args: string[]): Promise<void> {\n const [ticketId] = args;\n if (!ticketId) {\n console.error('Usage: kantban work <ticket-id> [--dry-run]');\n process.exit(1);\n }\n\n const projectId = process.env['KANTBAN_PROJECT_ID'];\n if (!projectId) {\n console.error('Error: KANTBAN_PROJECT_ID required');\n process.exit(1);\n }\n\n // Fetch ticket-scope context\n const context = await client.get<Record<string, unknown>>(\n `/projects/${projectId}/pipeline-context`,\n { ticketId },\n );\n\n const ticket = asRecord(context['ticket']);\n const signals = asStringArray(context['signals']);\n const rules = context['transition_rules'] ? String(context['transition_rules']) : undefined;\n\n const title = String(ticket?.['title'] ?? 'Untitled');\n const description = ticket?.['description'] ? String(ticket['description']) : '';\n const ticketIdStr = String(ticket?.['id'] ?? ticketId);\n\n // Build prompt for Claude\n const promptLines = [\n `# Task: ${title}`,\n '',\n ];\n\n if (description) {\n promptLines.push(description, '');\n }\n\n if (signals.length > 0) {\n promptLines.push('## Signals');\n for (const s of signals) {\n promptLines.push(`- ${s}`);\n }\n promptLines.push('');\n }\n\n if (rules) {\n promptLines.push('## Transition Rules', rules, '');\n }\n\n const toolPrefix = context['tool_prefix'] ? String(context['tool_prefix']) : 'kantban_';\n promptLines.push(\n `## Tool Prefix: ${toolPrefix}`,\n `## Ticket ID: ${ticketIdStr}`,\n `## Project ID: ${projectId}`,\n );\n\n const prompt = promptLines.join('\\n');\n\n console.log(`Starting Claude session for: ${title}`);\n console.log(`Ticket: ${ticketIdStr}`);\n\n // Check for dry run\n const dryRun = args.includes('--dry-run');\n if (dryRun) {\n console.log('\\n--- Prompt (dry run) ---');\n console.log(prompt);\n return;\n }\n\n // Spawn Claude with the prompt\n const child = spawn('claude', ['-p', prompt], {\n stdio: 'inherit',\n env: { ...process.env },\n });\n\n await new Promise<void>((resolve) => {\n child.on('error', (err) => {\n console.error(`Failed to start claude: ${err.message}`);\n process.exitCode = 1;\n resolve();\n });\n child.on('exit', (code) => {\n process.exitCode = code ?? 0;\n resolve();\n });\n });\n}\n"],"mappings":";AAAA,SAAS,aAAa;AAGtB,SAAS,SAAS,KAAmD;AACnE,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,GAAG,IAC/D,MACD;AACN;AAEA,SAAS,cAAc,KAAwB;AAC7C,SAAO,MAAM,QAAQ,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC;AAC3D;AAEA,eAAsB,QAAQ,QAA0B,MAA+B;AACrF,QAAM,CAAC,QAAQ,IAAI;AACnB,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,6CAA6C;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,QAAQ,IAAI,oBAAoB;AAClD,MAAI,CAAC,WAAW;AACd,YAAQ,MAAM,oCAAoC;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,UAAU,MAAM,OAAO;AAAA,IAC3B,aAAa,SAAS;AAAA,IACtB,EAAE,SAAS;AAAA,EACb;AAEA,QAAM,SAAS,SAAS,QAAQ,QAAQ,CAAC;AACzC,QAAM,UAAU,cAAc,QAAQ,SAAS,CAAC;AAChD,QAAM,QAAQ,QAAQ,kBAAkB,IAAI,OAAO,QAAQ,kBAAkB,CAAC,IAAI;AAElF,QAAM,QAAQ,OAAO,SAAS,OAAO,KAAK,UAAU;AACpD,QAAM,cAAc,SAAS,aAAa,IAAI,OAAO,OAAO,aAAa,CAAC,IAAI;AAC9E,QAAM,cAAc,OAAO,SAAS,IAAI,KAAK,QAAQ;AAGrD,QAAM,cAAc;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,aAAa;AACf,gBAAY,KAAK,aAAa,EAAE;AAAA,EAClC;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,gBAAY,KAAK,YAAY;AAC7B,eAAW,KAAK,SAAS;AACvB,kBAAY,KAAK,KAAK,CAAC,EAAE;AAAA,IAC3B;AACA,gBAAY,KAAK,EAAE;AAAA,EACrB;AAEA,MAAI,OAAO;AACT,gBAAY,KAAK,uBAAuB,OAAO,EAAE;AAAA,EACnD;AAEA,QAAM,aAAa,QAAQ,aAAa,IAAI,OAAO,QAAQ,aAAa,CAAC,IAAI;AAC7E,cAAY;AAAA,IACV,mBAAmB,UAAU;AAAA,IAC7B,iBAAiB,WAAW;AAAA,IAC5B,kBAAkB,SAAS;AAAA,EAC7B;AAEA,QAAM,SAAS,YAAY,KAAK,IAAI;AAEpC,UAAQ,IAAI,gCAAgC,KAAK,EAAE;AACnD,UAAQ,IAAI,WAAW,WAAW,EAAE;AAGpC,QAAM,SAAS,KAAK,SAAS,WAAW;AACxC,MAAI,QAAQ;AACV,YAAQ,IAAI,4BAA4B;AACxC,YAAQ,IAAI,MAAM;AAClB;AAAA,EACF;AAGA,QAAM,QAAQ,MAAM,UAAU,CAAC,MAAM,MAAM,GAAG;AAAA,IAC5C,OAAO;AAAA,IACP,KAAK,EAAE,GAAG,QAAQ,IAAI;AAAA,EACxB,CAAC;AAED,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,cAAQ,MAAM,2BAA2B,IAAI,OAAO,EAAE;AACtD,cAAQ,WAAW;AACnB,cAAQ;AAAA,IACV,CAAC;AACD,UAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,cAAQ,WAAW,QAAQ;AAC3B,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kantban-cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "description": "CLI for KantBan pipeline orchestration — bridges KantBan boards to local Claude Code sessions",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -26,12 +26,12 @@
26
26
  "README.md"
27
27
  ],
28
28
  "scripts": {
29
- "build": "tsc",
30
- "dev": "tsc --watch",
29
+ "build": "tsup",
30
+ "dev": "tsup --watch",
31
31
  "test": "vitest run",
32
32
  "typecheck": "tsc --noEmit",
33
33
  "postbuild": "chmod +x dist/index.js",
34
- "prepublishOnly": "tsc"
34
+ "prepublishOnly": "tsup"
35
35
  },
36
36
  "dependencies": {
37
37
  "js-yaml": "^4.1.1",
@@ -43,6 +43,7 @@
43
43
  "@types/js-yaml": "^4.0.9",
44
44
  "@types/node": "^22.0.0",
45
45
  "@types/ws": "^8.18.1",
46
+ "tsup": "^8.5.1",
46
47
  "typescript": "^5.8.0"
47
48
  },
48
49
  "engines": {
package/dist/client.d.ts DELETED
@@ -1,38 +0,0 @@
1
- export declare const REQUEST_TIMEOUT_MS = 30000;
2
- export declare const MAX_RETRIES = 2;
3
- export declare const RETRY_BASE_MS = 500;
4
- /** Returns true for statuses that are worth retrying (server errors + rate limit). */
5
- export declare function isRetryableStatus(status: number): boolean;
6
- /**
7
- * Wraps `fetch` with:
8
- * - Per-request AbortController timeout (REQUEST_TIMEOUT_MS)
9
- * - Exponential backoff with jitter on retryable failures
10
- * - Up to MAX_RETRIES retries (so MAX_RETRIES + 1 total attempts)
11
- *
12
- * @param _sleep — optional override for the backoff sleep (used in tests to avoid real delays)
13
- */
14
- export declare function fetchWithRetry(url: string, init: RequestInit, retries?: number, _sleep?: (ms: number) => Promise<void>): Promise<Response>;
15
- export declare class KantBanCLIClient {
16
- private apiUrl;
17
- private apiToken;
18
- constructor(apiUrl: string, apiToken: string);
19
- get baseUrl(): string;
20
- get token(): string;
21
- get<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T>;
22
- post<T>(path: string, body?: Record<string, unknown>): Promise<T>;
23
- claimTicket(projectId: string, ticketId: string): Promise<void>;
24
- getFingerprint(projectId: string, ticketId: string): Promise<{
25
- column_id: string | null;
26
- updated_at: string;
27
- comment_count: number;
28
- signal_count: number;
29
- field_value_count: number;
30
- }>;
31
- put<T>(path: string, body?: Record<string, unknown>): Promise<T>;
32
- patch<T>(path: string, body?: Record<string, unknown>): Promise<T>;
33
- delete<T = unknown>(path: string): Promise<T>;
34
- getBoardProject(boardId: string): Promise<{
35
- project_id: string;
36
- }>;
37
- }
38
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,EACjB,OAAO,SAAc,EACrB,MAAM,GAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CACe,GAClD,OAAO,CAAC,QAAQ,CAAC,CAgCnB;AAID,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;gBADR,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;IAG1B,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAEK,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAmBhG,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBjE,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;IAII,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBhE,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBlE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAe7C,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAGxE"}
package/dist/client.js DELETED
@@ -1,163 +0,0 @@
1
- // ── retry / timeout constants ─────────────────────────────────────────────
2
- export const REQUEST_TIMEOUT_MS = 30_000;
3
- export const MAX_RETRIES = 2;
4
- export const RETRY_BASE_MS = 500;
5
- /** Returns true for statuses that are worth retrying (server errors + rate limit). */
6
- export function isRetryableStatus(status) {
7
- return status >= 500 || status === 429;
8
- }
9
- /**
10
- * Wraps `fetch` with:
11
- * - Per-request AbortController timeout (REQUEST_TIMEOUT_MS)
12
- * - Exponential backoff with jitter on retryable failures
13
- * - Up to MAX_RETRIES retries (so MAX_RETRIES + 1 total attempts)
14
- *
15
- * @param _sleep — optional override for the backoff sleep (used in tests to avoid real delays)
16
- */
17
- export async function fetchWithRetry(url, init, retries = MAX_RETRIES, _sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
18
- let lastError;
19
- for (let attempt = 0; attempt <= retries; attempt++) {
20
- const controller = new AbortController();
21
- const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
22
- try {
23
- const res = await fetch(url, { ...init, signal: controller.signal });
24
- clearTimeout(timer);
25
- // Non-retryable: 2xx (ok) or any non-retryable error status
26
- if (res.ok || !isRetryableStatus(res.status)) {
27
- return res;
28
- }
29
- // Retryable status — treat as a transient failure
30
- lastError = new Error(`API error ${res.status}: ${await res.text()}`);
31
- }
32
- catch (err) {
33
- clearTimeout(timer);
34
- lastError = err;
35
- // Only retry on network/abort errors, not on logic errors
36
- }
37
- if (attempt < retries) {
38
- // Exponential backoff with up to 50% random jitter
39
- const delay = RETRY_BASE_MS * 2 ** attempt * (1 + Math.random() * 0.5);
40
- await _sleep(delay);
41
- }
42
- }
43
- throw lastError;
44
- }
45
- // ── client ────────────────────────────────────────────────────────────────
46
- export class KantBanCLIClient {
47
- apiUrl;
48
- apiToken;
49
- constructor(apiUrl, apiToken) {
50
- this.apiUrl = apiUrl;
51
- this.apiToken = apiToken;
52
- }
53
- get baseUrl() {
54
- return this.apiUrl;
55
- }
56
- get token() {
57
- return this.apiToken;
58
- }
59
- async get(path, params) {
60
- const url = new URL(path, this.apiUrl);
61
- if (params) {
62
- for (const [k, v] of Object.entries(params)) {
63
- if (v !== undefined)
64
- url.searchParams.set(k, String(v));
65
- }
66
- }
67
- const res = await fetchWithRetry(url.toString(), {
68
- headers: {
69
- 'Authorization': `Bearer ${this.apiToken}`,
70
- 'X-KantBan-Via': 'cli',
71
- },
72
- });
73
- if (!res.ok)
74
- throw new Error(`API error ${res.status}: ${await res.text()}`);
75
- const json = (await res.json());
76
- if (!json.success)
77
- throw new Error(`API responded with success: false`);
78
- return json.data;
79
- }
80
- async post(path, body) {
81
- const url = new URL(path, this.apiUrl);
82
- const headers = {
83
- 'Authorization': `Bearer ${this.apiToken}`,
84
- 'X-KantBan-Via': 'cli',
85
- };
86
- const init = { method: 'POST', headers };
87
- if (body) {
88
- headers['Content-Type'] = 'application/json';
89
- init.body = JSON.stringify(body);
90
- }
91
- const res = await fetchWithRetry(url.toString(), init);
92
- if (!res.ok)
93
- throw new Error(`API error ${res.status}: ${await res.text()}`);
94
- const json = (await res.json());
95
- if (!json.success)
96
- throw new Error(`API responded with success: false`);
97
- return json.data;
98
- }
99
- async claimTicket(projectId, ticketId) {
100
- await this.post(`/projects/${projectId}/tickets/${ticketId}/start`, {});
101
- }
102
- async getFingerprint(projectId, ticketId) {
103
- return this.get(`/projects/${projectId}/tickets/${ticketId}/fingerprint`);
104
- }
105
- async put(path, body) {
106
- const url = new URL(path, this.apiUrl);
107
- const headers = {
108
- 'Authorization': `Bearer ${this.apiToken}`,
109
- 'X-KantBan-Via': 'cli',
110
- };
111
- const init = { method: 'PUT', headers };
112
- if (body) {
113
- headers['Content-Type'] = 'application/json';
114
- init.body = JSON.stringify(body);
115
- }
116
- const res = await fetchWithRetry(url.toString(), init);
117
- if (!res.ok)
118
- throw new Error(`API error ${res.status}: ${await res.text()}`);
119
- const json = (await res.json());
120
- if (!json.success)
121
- throw new Error(`API responded with success: false`);
122
- return json.data;
123
- }
124
- async patch(path, body) {
125
- const url = new URL(path, this.apiUrl);
126
- const headers = {
127
- 'Authorization': `Bearer ${this.apiToken}`,
128
- 'X-KantBan-Via': 'cli',
129
- };
130
- const init = { method: 'PATCH', headers };
131
- if (body) {
132
- headers['Content-Type'] = 'application/json';
133
- init.body = JSON.stringify(body);
134
- }
135
- const res = await fetchWithRetry(url.toString(), init);
136
- if (!res.ok)
137
- throw new Error(`API error ${res.status}: ${await res.text()}`);
138
- const json = (await res.json());
139
- if (!json.success)
140
- throw new Error(`API responded with success: false`);
141
- return json.data;
142
- }
143
- async delete(path) {
144
- const url = new URL(path, this.apiUrl);
145
- const res = await fetchWithRetry(url.toString(), {
146
- method: 'DELETE',
147
- headers: {
148
- 'Authorization': `Bearer ${this.apiToken}`,
149
- 'X-KantBan-Via': 'cli',
150
- },
151
- });
152
- if (!res.ok)
153
- throw new Error(`API error ${res.status}: ${await res.text()}`);
154
- const json = (await res.json());
155
- if (!json.success)
156
- throw new Error(`API responded with success: false`);
157
- return json.data;
158
- }
159
- async getBoardProject(boardId) {
160
- return this.get(`/boards/${boardId}/project`);
161
- }
162
- }
163
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import type { KantBanCLIClient } from '../client.js';
2
- export declare function runContext(client: KantBanCLIClient, args: string[]): Promise<void>;
3
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BxF"}
@@ -1,27 +0,0 @@
1
- export async function runContext(client, args) {
2
- const [scopeType, scopeId] = args;
3
- if (!scopeType || !scopeId) {
4
- console.error('Usage: kantban context <board|column|ticket> <id>');
5
- process.exit(1);
6
- }
7
- const projectId = process.env['KANTBAN_PROJECT_ID'];
8
- if (!projectId) {
9
- console.error('Error: KANTBAN_PROJECT_ID environment variable required for context command');
10
- process.exit(1);
11
- }
12
- const params = {};
13
- if (scopeType === 'board')
14
- params['boardId'] = scopeId;
15
- else if (scopeType === 'column')
16
- params['columnId'] = scopeId;
17
- else if (scopeType === 'ticket')
18
- params['ticketId'] = scopeId;
19
- else {
20
- console.error(`Unknown scope type: ${scopeType}. Use board, column, or ticket.`);
21
- process.exit(1);
22
- }
23
- const data = await client.get(`/projects/${projectId}/pipeline-context`, params);
24
- // Output as structured JSON to stdout for piping
25
- console.log(JSON.stringify(data, null, 2));
26
- }
27
- //# sourceMappingURL=context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAwB,EAAE,IAAc;IACvE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACpD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,SAAS,KAAK,OAAO;QAAE,MAAM,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC;SAClD,IAAI,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;SACzD,IAAI,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;SACzD,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,uBAAuB,SAAS,iCAAiC,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,aAAa,SAAS,mBAAmB,EACzC,MAAM,CACP,CAAC;IAEF,iDAAiD;IACjD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC"}