@kb-labs/shared 1.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 (232) hide show
  1. package/.cursorrules +32 -0
  2. package/.github/workflows/ci.yml +13 -0
  3. package/.github/workflows/deploy.yml +28 -0
  4. package/.github/workflows/docker-build.yml +25 -0
  5. package/.github/workflows/drift-check.yml +10 -0
  6. package/.github/workflows/profiles-validate.yml +16 -0
  7. package/.github/workflows/release.yml +8 -0
  8. package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
  9. package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
  10. package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
  11. package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
  12. package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
  13. package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
  14. package/.kb/devkit/agents/release-manager/context.globs +7 -0
  15. package/.kb/devkit/agents/release-manager/prompt.md +27 -0
  16. package/.kb/devkit/agents/release-manager/runbook.md +17 -0
  17. package/.kb/devkit/agents/test-generator/context.globs +7 -0
  18. package/.kb/devkit/agents/test-generator/prompt.md +27 -0
  19. package/.kb/devkit/agents/test-generator/runbook.md +18 -0
  20. package/.vscode/settings.json +23 -0
  21. package/CHANGELOG.md +33 -0
  22. package/CONTRIBUTING.md +117 -0
  23. package/LICENSE +21 -0
  24. package/README.md +306 -0
  25. package/docs/DECLARATIVE-FLAGS-AND-ENV.md +622 -0
  26. package/docs/DOCUMENTATION.md +70 -0
  27. package/docs/adr/0000-template.md +52 -0
  28. package/docs/adr/0001-architecture-and-repository-layout.md +31 -0
  29. package/docs/adr/0002-plugins-and-extensibility.md +44 -0
  30. package/docs/adr/0003-package-and-module-boundaries.md +35 -0
  31. package/docs/adr/0004-versioning-and-release-policy.md +36 -0
  32. package/docs/adr/0005-reactive-loader-pattern.md +179 -0
  33. package/docs/adr/0006-declarative-flags-and-env-systems.md +376 -0
  34. package/eslint.config.js +27 -0
  35. package/kb-labs.config.json +5 -0
  36. package/package.json +88 -0
  37. package/package.json.bin +25 -0
  38. package/package.json.lib +30 -0
  39. package/packages/shared-cli-ui/CHANGELOG.md +20 -0
  40. package/packages/shared-cli-ui/README.md +342 -0
  41. package/packages/shared-cli-ui/docs/ARCHITECTURE.md +105 -0
  42. package/packages/shared-cli-ui/eslint.config.js +27 -0
  43. package/packages/shared-cli-ui/package.json +72 -0
  44. package/packages/shared-cli-ui/src/__tests__/artifacts-display.spec.ts +89 -0
  45. package/packages/shared-cli-ui/src/__tests__/format.spec.ts +44 -0
  46. package/packages/shared-cli-ui/src/__tests__/loader-json-mode.test.ts +119 -0
  47. package/packages/shared-cli-ui/src/artifacts-display.ts +266 -0
  48. package/packages/shared-cli-ui/src/cli-auto-discovery.ts +120 -0
  49. package/packages/shared-cli-ui/src/colors.ts +142 -0
  50. package/packages/shared-cli-ui/src/command-discovery.ts +72 -0
  51. package/packages/shared-cli-ui/src/command-output.ts +153 -0
  52. package/packages/shared-cli-ui/src/command-result.ts +267 -0
  53. package/packages/shared-cli-ui/src/command-runner.ts +310 -0
  54. package/packages/shared-cli-ui/src/command-suggestions.ts +204 -0
  55. package/packages/shared-cli-ui/src/debug/components/output.ts +141 -0
  56. package/packages/shared-cli-ui/src/debug/components/trace.ts +101 -0
  57. package/packages/shared-cli-ui/src/debug/components/tree.ts +88 -0
  58. package/packages/shared-cli-ui/src/debug/formatters/ai.ts +17 -0
  59. package/packages/shared-cli-ui/src/debug/formatters/human.ts +98 -0
  60. package/packages/shared-cli-ui/src/debug/formatters/timeline.ts +94 -0
  61. package/packages/shared-cli-ui/src/debug/index.ts +56 -0
  62. package/packages/shared-cli-ui/src/debug/types.ts +57 -0
  63. package/packages/shared-cli-ui/src/debug/utilities.ts +203 -0
  64. package/packages/shared-cli-ui/src/dynamic-command-discovery.ts +131 -0
  65. package/packages/shared-cli-ui/src/format.ts +412 -0
  66. package/packages/shared-cli-ui/src/index.ts +34 -0
  67. package/packages/shared-cli-ui/src/loader.ts +196 -0
  68. package/packages/shared-cli-ui/src/manifest-parser.ts +151 -0
  69. package/packages/shared-cli-ui/src/modern-format.ts +271 -0
  70. package/packages/shared-cli-ui/src/multi-cli-suggestions.ts +159 -0
  71. package/packages/shared-cli-ui/src/table.ts +134 -0
  72. package/packages/shared-cli-ui/src/timing-tracker.ts +68 -0
  73. package/packages/shared-cli-ui/src/utils/context.ts +12 -0
  74. package/packages/shared-cli-ui/src/utils/env.ts +164 -0
  75. package/packages/shared-cli-ui/src/utils/flags.ts +269 -0
  76. package/packages/shared-cli-ui/src/utils/path.ts +8 -0
  77. package/packages/shared-cli-ui/tsconfig.build.json +15 -0
  78. package/packages/shared-cli-ui/tsconfig.json +9 -0
  79. package/packages/shared-cli-ui/tsup.config.ts +11 -0
  80. package/packages/shared-cli-ui/vitest.config.ts +15 -0
  81. package/packages/shared-command-kit/CHANGELOG.md +20 -0
  82. package/packages/shared-command-kit/LICENSE +22 -0
  83. package/packages/shared-command-kit/README.md +1030 -0
  84. package/packages/shared-command-kit/docs/HIGH-LEVEL-API.md +89 -0
  85. package/packages/shared-command-kit/docs/LOW-LEVEL-API.md +105 -0
  86. package/packages/shared-command-kit/docs/MIGRATION-GUIDE.md +135 -0
  87. package/packages/shared-command-kit/eslint.config.js +27 -0
  88. package/packages/shared-command-kit/eslint.config.ts +14 -0
  89. package/packages/shared-command-kit/package.json +76 -0
  90. package/packages/shared-command-kit/prettierrc.json +5 -0
  91. package/packages/shared-command-kit/src/__tests__/define-command.spec.ts +294 -0
  92. package/packages/shared-command-kit/src/__tests__/define-route.test.ts +285 -0
  93. package/packages/shared-command-kit/src/__tests__/define-system-command.spec.ts +508 -0
  94. package/packages/shared-command-kit/src/__tests__/define-webhook.test.ts +156 -0
  95. package/packages/shared-command-kit/src/__tests__/define-websocket.test.ts +316 -0
  96. package/packages/shared-command-kit/src/__tests__/errors.spec.ts +45 -0
  97. package/packages/shared-command-kit/src/__tests__/flags.spec.ts +353 -0
  98. package/packages/shared-command-kit/src/__tests__/platform-api.test.ts +135 -0
  99. package/packages/shared-command-kit/src/__tests__/plugin-context-v3.snapshot.spec.ts +240 -0
  100. package/packages/shared-command-kit/src/__tests__/ws-types.test.ts +359 -0
  101. package/packages/shared-command-kit/src/analytics/index.ts +6 -0
  102. package/packages/shared-command-kit/src/analytics/with-analytics.ts +195 -0
  103. package/packages/shared-command-kit/src/define-action.ts +100 -0
  104. package/packages/shared-command-kit/src/define-command.ts +113 -0
  105. package/packages/shared-command-kit/src/define-route.ts +113 -0
  106. package/packages/shared-command-kit/src/define-system-command.ts +362 -0
  107. package/packages/shared-command-kit/src/define-webhook.ts +115 -0
  108. package/packages/shared-command-kit/src/define-websocket.ts +308 -0
  109. package/packages/shared-command-kit/src/errors/factory.ts +282 -0
  110. package/packages/shared-command-kit/src/errors/format-validation.ts +144 -0
  111. package/packages/shared-command-kit/src/errors/format.ts +92 -0
  112. package/packages/shared-command-kit/src/errors/index.ts +9 -0
  113. package/packages/shared-command-kit/src/errors/types.ts +32 -0
  114. package/packages/shared-command-kit/src/flags/define.ts +92 -0
  115. package/packages/shared-command-kit/src/flags/index.ts +9 -0
  116. package/packages/shared-command-kit/src/flags/types.ts +153 -0
  117. package/packages/shared-command-kit/src/flags/validate.ts +358 -0
  118. package/packages/shared-command-kit/src/helpers/context.ts +8 -0
  119. package/packages/shared-command-kit/src/helpers/flags.ts +84 -0
  120. package/packages/shared-command-kit/src/helpers/index.ts +42 -0
  121. package/packages/shared-command-kit/src/helpers/patterns.ts +464 -0
  122. package/packages/shared-command-kit/src/helpers/platform.ts +335 -0
  123. package/packages/shared-command-kit/src/helpers/use-analytics.ts +95 -0
  124. package/packages/shared-command-kit/src/helpers/use-cache.ts +97 -0
  125. package/packages/shared-command-kit/src/helpers/use-config.ts +99 -0
  126. package/packages/shared-command-kit/src/helpers/use-embeddings.ts +49 -0
  127. package/packages/shared-command-kit/src/helpers/use-llm.ts +316 -0
  128. package/packages/shared-command-kit/src/helpers/use-logger.ts +77 -0
  129. package/packages/shared-command-kit/src/helpers/use-platform.ts +111 -0
  130. package/packages/shared-command-kit/src/helpers/use-resource-broker.ts +106 -0
  131. package/packages/shared-command-kit/src/helpers/use-storage.ts +71 -0
  132. package/packages/shared-command-kit/src/helpers/use-vector-store.ts +49 -0
  133. package/packages/shared-command-kit/src/helpers/validation.ts +398 -0
  134. package/packages/shared-command-kit/src/index.ts +410 -0
  135. package/packages/shared-command-kit/src/jobs.ts +132 -0
  136. package/packages/shared-command-kit/src/lifecycle/define-handlers.ts +366 -0
  137. package/packages/shared-command-kit/src/lifecycle/index.ts +6 -0
  138. package/packages/shared-command-kit/src/manifest.ts +127 -0
  139. package/packages/shared-command-kit/src/rest/define-handler.ts +187 -0
  140. package/packages/shared-command-kit/src/rest/index.ts +11 -0
  141. package/packages/shared-command-kit/src/studio/index.ts +12 -0
  142. package/packages/shared-command-kit/src/validation/index.ts +6 -0
  143. package/packages/shared-command-kit/src/validation/schema-builders.ts +409 -0
  144. package/packages/shared-command-kit/src/ws-types.ts +106 -0
  145. package/packages/shared-command-kit/tsconfig.build.json +15 -0
  146. package/packages/shared-command-kit/tsconfig.json +9 -0
  147. package/packages/shared-command-kit/tsup.config.ts +30 -0
  148. package/packages/shared-command-kit/vitest.config.ts +4 -0
  149. package/packages/shared-http/package.json +67 -0
  150. package/packages/shared-http/src/__tests__/log-correlation.test.ts +81 -0
  151. package/packages/shared-http/src/__tests__/operation-metrics-tracker.test.ts +55 -0
  152. package/packages/shared-http/src/http-observability-collector.ts +363 -0
  153. package/packages/shared-http/src/index.ts +36 -0
  154. package/packages/shared-http/src/log-correlation.ts +89 -0
  155. package/packages/shared-http/src/operation-metrics-tracker.ts +107 -0
  156. package/packages/shared-http/src/register-openapi.ts +108 -0
  157. package/packages/shared-http/src/resolve-schema-ref.ts +75 -0
  158. package/packages/shared-http/src/schemas.ts +29 -0
  159. package/packages/shared-http/src/service-observability.ts +63 -0
  160. package/packages/shared-http/tsconfig.build.json +15 -0
  161. package/packages/shared-http/tsconfig.json +9 -0
  162. package/packages/shared-http/tsup.config.ts +23 -0
  163. package/packages/shared-http/vitest.config.ts +13 -0
  164. package/packages/shared-perm-presets/CHANGELOG.md +20 -0
  165. package/packages/shared-perm-presets/README.md +78 -0
  166. package/packages/shared-perm-presets/eslint.config.js +27 -0
  167. package/packages/shared-perm-presets/package.json +45 -0
  168. package/packages/shared-perm-presets/src/__tests__/combine.test.ts +403 -0
  169. package/packages/shared-perm-presets/src/__tests__/presets.test.ts +205 -0
  170. package/packages/shared-perm-presets/src/combine.ts +278 -0
  171. package/packages/shared-perm-presets/src/index.ts +18 -0
  172. package/packages/shared-perm-presets/src/presets/ci-environment.ts +34 -0
  173. package/packages/shared-perm-presets/src/presets/full-env.ts +16 -0
  174. package/packages/shared-perm-presets/src/presets/git-workflow.ts +40 -0
  175. package/packages/shared-perm-presets/src/presets/index.ts +8 -0
  176. package/packages/shared-perm-presets/src/presets/kb-platform.ts +30 -0
  177. package/packages/shared-perm-presets/src/presets/llm-access.ts +29 -0
  178. package/packages/shared-perm-presets/src/presets/minimal.ts +21 -0
  179. package/packages/shared-perm-presets/src/presets/npm-publish.ts +48 -0
  180. package/packages/shared-perm-presets/src/presets/vector-store.ts +40 -0
  181. package/packages/shared-perm-presets/src/types.ts +192 -0
  182. package/packages/shared-perm-presets/tsconfig.build.json +15 -0
  183. package/packages/shared-perm-presets/tsconfig.json +9 -0
  184. package/packages/shared-perm-presets/tsup.config.ts +8 -0
  185. package/packages/shared-perm-presets/vitest.config.ts +9 -0
  186. package/packages/shared-testing/CHANGELOG.md +20 -0
  187. package/packages/shared-testing/README.md +430 -0
  188. package/packages/shared-testing/package.json +51 -0
  189. package/packages/shared-testing/src/__tests__/create-test-context.test.ts +199 -0
  190. package/packages/shared-testing/src/__tests__/mock-cache.test.ts +174 -0
  191. package/packages/shared-testing/src/__tests__/mock-llm.test.ts +212 -0
  192. package/packages/shared-testing/src/__tests__/setup-platform.test.ts +90 -0
  193. package/packages/shared-testing/src/__tests__/test-command.test.ts +557 -0
  194. package/packages/shared-testing/src/create-test-context.ts +550 -0
  195. package/packages/shared-testing/src/index.ts +77 -0
  196. package/packages/shared-testing/src/mock-cache.ts +179 -0
  197. package/packages/shared-testing/src/mock-llm.ts +319 -0
  198. package/packages/shared-testing/src/mock-logger.ts +97 -0
  199. package/packages/shared-testing/src/mock-storage.ts +108 -0
  200. package/packages/shared-testing/src/setup-platform.ts +101 -0
  201. package/packages/shared-testing/src/test-command.ts +288 -0
  202. package/packages/shared-testing/tsconfig.build.json +15 -0
  203. package/packages/shared-testing/tsconfig.json +9 -0
  204. package/packages/shared-testing/tsup.config.ts +20 -0
  205. package/packages/shared-testing/vitest.config.ts +3 -0
  206. package/packages/shared-tool-kit/CHANGELOG.md +20 -0
  207. package/packages/shared-tool-kit/package.json +47 -0
  208. package/packages/shared-tool-kit/src/__tests__/factory.test.ts +103 -0
  209. package/packages/shared-tool-kit/src/__tests__/mock-tool.test.ts +95 -0
  210. package/packages/shared-tool-kit/src/factory.ts +126 -0
  211. package/packages/shared-tool-kit/src/index.ts +32 -0
  212. package/packages/shared-tool-kit/src/testing/index.ts +84 -0
  213. package/packages/shared-tool-kit/tsconfig.build.json +15 -0
  214. package/packages/shared-tool-kit/tsconfig.json +9 -0
  215. package/packages/shared-tool-kit/tsup.config.ts +21 -0
  216. package/pnpm-workspace.yaml +11070 -0
  217. package/prettierrc.json +1 -0
  218. package/scripts/devkit-sync.mjs +37 -0
  219. package/scripts/hooks/post-push +9 -0
  220. package/scripts/hooks/pre-commit +9 -0
  221. package/scripts/hooks/pre-push +9 -0
  222. package/tsconfig.base.json +9 -0
  223. package/tsconfig.build.json +15 -0
  224. package/tsconfig.json +9 -0
  225. package/tsconfig.paths.json +50 -0
  226. package/tsconfig.tools.json +18 -0
  227. package/tsup.config.bin.ts +34 -0
  228. package/tsup.config.cli.ts +41 -0
  229. package/tsup.config.dual.ts +46 -0
  230. package/tsup.config.ts +36 -0
  231. package/tsup.external.json +104 -0
  232. package/vitest.config.ts +48 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Command discovery utilities for CLI systems
3
+ */
4
+
5
+ export interface CommandInfo {
6
+ id: string;
7
+ group: string;
8
+ name: string;
9
+ description: string;
10
+ available: boolean;
11
+ }
12
+
13
+ /**
14
+ * Discover available commands from CLI manifest or registry
15
+ * This is a generic interface that can be implemented by different CLI systems
16
+ */
17
+ export interface CommandDiscovery {
18
+ /**
19
+ * Get all available commands
20
+ */
21
+ getAvailableCommands(): Promise<string[]>;
22
+
23
+ /**
24
+ * Get command info by ID
25
+ */
26
+ getCommandInfo(commandId: string): Promise<CommandInfo | null>;
27
+
28
+ /**
29
+ * Check if a command is available
30
+ */
31
+ isCommandAvailable(commandId: string): Promise<boolean>;
32
+ }
33
+
34
+ /**
35
+ * Simple command discovery that works with a predefined list
36
+ * Can be extended to work with actual CLI registries
37
+ */
38
+ export class StaticCommandDiscovery implements CommandDiscovery {
39
+ constructor(private commands: string[]) {}
40
+
41
+ async getAvailableCommands(): Promise<string[]> {
42
+ return [...this.commands];
43
+ }
44
+
45
+ async getCommandInfo(commandId: string): Promise<CommandInfo | null> {
46
+ if (!this.commands.includes(commandId)) {
47
+ return null;
48
+ }
49
+
50
+ const [group, name] = commandId.split(':');
51
+ return {
52
+ id: commandId,
53
+ group: group || 'unknown',
54
+ name: name || commandId,
55
+ description: `Execute ${commandId}`,
56
+ available: true
57
+ };
58
+ }
59
+
60
+ async isCommandAvailable(commandId: string): Promise<boolean> {
61
+ return this.commands.includes(commandId);
62
+ }
63
+ }
64
+
65
+
66
+
67
+ /**
68
+ * Create a command discovery instance from a command list
69
+ */
70
+ export function createCommandDiscovery(commands: string[]): CommandDiscovery {
71
+ return new StaticCommandDiscovery(commands);
72
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Command output formatting utilities
3
+ * Provides consistent formatting for CLI command results
4
+ */
5
+
6
+ import { box, keyValue } from './format';
7
+ import { safeColors } from './colors';
8
+
9
+ export interface CommandResult {
10
+ title: string;
11
+ summary: Record<string, string | number>;
12
+ timing?: number | Record<string, number>;
13
+ diagnostics?: string[];
14
+ warnings?: string[];
15
+ errors?: string[];
16
+ suggestions?: string[];
17
+ }
18
+
19
+ /**
20
+ * Format timing in milliseconds to human-readable string
21
+ */
22
+ export function formatTiming(ms: number): string {
23
+ if (ms < 1000) {
24
+ return `${ms}ms`;
25
+ } else if (ms < 60000) {
26
+ return `${(ms / 1000).toFixed(1)}s`;
27
+ } else {
28
+ const minutes = Math.floor(ms / 60000);
29
+ const seconds = ((ms % 60000) / 1000).toFixed(1);
30
+ return `${minutes}m ${seconds}s`;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Format timing breakdown as array of strings
36
+ */
37
+ export function formatTimingBreakdown(timings: Record<string, number>): string[] {
38
+ const lines: string[] = [];
39
+
40
+ // Sort timings by value (descending) for better readability
41
+ const sortedEntries = Object.entries(timings)
42
+ .filter(([key]) => key !== 'total')
43
+ .sort(([, a], [, b]) => b - a);
44
+
45
+ for (const [name, ms] of sortedEntries) {
46
+ const formattedName = name.charAt(0).toUpperCase() + name.slice(1);
47
+ lines.push(`${formattedName}: ${formatTiming(ms)}`);
48
+ }
49
+
50
+ // Always show total at the end
51
+ if (timings.total !== undefined) {
52
+ lines.push(`Total: ${formatTiming(timings.total)}`);
53
+ }
54
+
55
+ return lines;
56
+ }
57
+
58
+ /**
59
+ * Format complete command output with box, summary, timing, and additional info
60
+ */
61
+ export function formatCommandOutput(result: CommandResult): string {
62
+ const sections: string[] = [];
63
+
64
+ // Add summary section
65
+ const summaryLines = keyValue(result.summary);
66
+ sections.push(...summaryLines);
67
+
68
+ // Add timing section
69
+ if (result.timing !== undefined) {
70
+ sections.push('');
71
+
72
+ if (typeof result.timing === 'number') {
73
+ sections.push(`Time: ${formatTiming(result.timing)}`);
74
+ } else {
75
+ const timingLines = formatTimingBreakdown(result.timing);
76
+ sections.push(...timingLines);
77
+ }
78
+ }
79
+
80
+ // Add warnings section
81
+ if (result.warnings && result.warnings.length > 0) {
82
+ sections.push('');
83
+ sections.push(safeColors.warning('Warnings:'));
84
+ result.warnings.forEach(warning =>
85
+ sections.push(` ${safeColors.dim('•')} ${warning}`)
86
+ );
87
+ }
88
+
89
+ // Add errors section
90
+ if (result.errors && result.errors.length > 0) {
91
+ sections.push('');
92
+ sections.push(safeColors.error('Errors:'));
93
+ result.errors.forEach(error =>
94
+ sections.push(` ${safeColors.dim('•')} ${error}`)
95
+ );
96
+ }
97
+
98
+ // Add diagnostics section
99
+ if (result.diagnostics && result.diagnostics.length > 0) {
100
+ sections.push('');
101
+ sections.push(safeColors.info('Diagnostics:'));
102
+ result.diagnostics.forEach(diagnostic =>
103
+ sections.push(` ${safeColors.dim('•')} ${diagnostic}`)
104
+ );
105
+ }
106
+
107
+ // Add suggestions section
108
+ if (result.suggestions && result.suggestions.length > 0) {
109
+ sections.push('');
110
+ sections.push(safeColors.info('Suggestions:'));
111
+ result.suggestions.forEach(suggestion =>
112
+ sections.push(` ${safeColors.dim('•')} ${suggestion}`)
113
+ );
114
+ }
115
+
116
+ return box(result.title, sections);
117
+ }
118
+
119
+ /**
120
+ * Create a simple command result with just title, summary, and timing
121
+ */
122
+ export function createSimpleResult(
123
+ title: string,
124
+ summary: Record<string, string | number>,
125
+ timing?: number
126
+ ): CommandResult {
127
+ return {
128
+ title,
129
+ summary,
130
+ timing,
131
+ };
132
+ }
133
+
134
+ /**
135
+ * Create a detailed command result with all optional fields
136
+ */
137
+ export function createDetailedResult(
138
+ title: string,
139
+ summary: Record<string, string | number>,
140
+ options: {
141
+ timing?: number | Record<string, number>;
142
+ diagnostics?: string[];
143
+ warnings?: string[];
144
+ errors?: string[];
145
+ suggestions?: string[];
146
+ } = {}
147
+ ): CommandResult {
148
+ return {
149
+ title,
150
+ summary,
151
+ ...options,
152
+ };
153
+ }
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Command result formatting utilities
3
+ * Provides high and low-level APIs for formatting command output
4
+ */
5
+
6
+ import {
7
+ sideBorderBox,
8
+ metricsList,
9
+ bulletList,
10
+ type SectionContent,
11
+ } from './modern-format';
12
+
13
+ /**
14
+ * Command output with human and machine-readable formats
15
+ * Extends CommandResult contract from command-kit
16
+ */
17
+ export interface CommandOutput {
18
+ /** Whether command executed successfully - required by CommandResult contract */
19
+ ok: boolean;
20
+ /** Execution status */
21
+ status?: 'success' | 'error' | 'warning' | 'info' | 'failed' | 'cancelled' | 'skipped';
22
+ /** Human-readable output (side border format) */
23
+ human: string;
24
+ /** Machine-readable output (JSON) */
25
+ json: object;
26
+ /** Agent-specific output (optional, for --agent flag) */
27
+ agent?: object;
28
+ }
29
+
30
+ /**
31
+ * Parameters for formatting command results
32
+ */
33
+ export interface CommandResultParams {
34
+ title: string;
35
+ summary?: Record<string, string | number>;
36
+ details?: Array<{ section: string; items: string[] }>;
37
+ warnings?: string[];
38
+ errors?: string[];
39
+ timing?: number;
40
+ status: 'success' | 'error' | 'warning' | 'info';
41
+ /** Custom JSON data (optional) */
42
+ jsonData?: object;
43
+ }
44
+
45
+ /**
46
+ * Low-level: Format command result with full control
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const output = formatCommandResult({
51
+ * title: 'System Diagnostics',
52
+ * summary: { 'Total Checks': 4, 'OK': 3 },
53
+ * details: [
54
+ * { section: 'Environment', items: ['Node 20.11.0'] }
55
+ * ],
56
+ * warnings: ['Cache is old'],
57
+ * timing: 150,
58
+ * status: 'success',
59
+ * });
60
+ *
61
+ * console.log(output.human); // Pretty CLI output
62
+ * console.log(output.json); // JSON for --json flag
63
+ * ```
64
+ */
65
+ export function formatCommandResult(params: CommandResultParams): CommandOutput {
66
+ const {
67
+ title,
68
+ summary,
69
+ details = [],
70
+ warnings = [],
71
+ errors = [],
72
+ timing,
73
+ status,
74
+ jsonData,
75
+ } = params;
76
+
77
+ // Build sections for human output
78
+ const sections: SectionContent[] = [];
79
+
80
+ // Summary section
81
+ if (summary && Object.keys(summary).length > 0) {
82
+ sections.push({
83
+ header: 'Summary',
84
+ items: metricsList(summary),
85
+ });
86
+ }
87
+
88
+ // Details sections
89
+ for (const detail of details) {
90
+ sections.push({
91
+ header: detail.section,
92
+ items: detail.items,
93
+ });
94
+ }
95
+
96
+ // Warnings section
97
+ if (warnings.length > 0) {
98
+ sections.push({
99
+ header: '⚠ Warnings',
100
+ items: bulletList(warnings),
101
+ });
102
+ }
103
+
104
+ // Errors section
105
+ if (errors.length > 0) {
106
+ sections.push({
107
+ header: '✗ Errors',
108
+ items: bulletList(errors),
109
+ });
110
+ }
111
+
112
+ // Generate human-readable output
113
+ const human = sideBorderBox({
114
+ title,
115
+ sections,
116
+ status,
117
+ timing,
118
+ });
119
+
120
+ // Generate JSON output
121
+ const json: any = {
122
+ ok: status === 'success',
123
+ status,
124
+ ...(summary && { summary }),
125
+ ...(details.length > 0 && {
126
+ details: details.reduce((acc, d) => {
127
+ acc[d.section] = d.items;
128
+ return acc;
129
+ }, {} as Record<string, string[]>),
130
+ }),
131
+ ...(warnings.length > 0 && { warnings }),
132
+ ...(errors.length > 0 && { errors }),
133
+ ...(timing !== undefined && { timingMs: timing }),
134
+ ...(jsonData && { data: jsonData }),
135
+ };
136
+
137
+ return {
138
+ ok: status === 'success',
139
+ status,
140
+ human,
141
+ json
142
+ };
143
+ }
144
+
145
+ /**
146
+ * High-level: Quick success result
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * return successResult('Version Info', {
151
+ * summary: { 'CLI Version': '0.1.0' },
152
+ * timing: 5,
153
+ * });
154
+ * ```
155
+ */
156
+ export function successResult(
157
+ title: string,
158
+ data?: {
159
+ summary?: Record<string, string | number>;
160
+ details?: Array<{ section: string; items: string[] }>;
161
+ timing?: number;
162
+ json?: object;
163
+ }
164
+ ): CommandOutput {
165
+ return formatCommandResult({
166
+ title,
167
+ summary: data?.summary,
168
+ details: data?.details,
169
+ timing: data?.timing,
170
+ status: 'success',
171
+ jsonData: data?.json,
172
+ });
173
+ }
174
+
175
+ /**
176
+ * High-level: Quick error result
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * return errorResult('Command Failed', new Error('Something went wrong'), {
181
+ * timing: 100,
182
+ * suggestions: ['Try running with --debug flag'],
183
+ * });
184
+ * ```
185
+ */
186
+ export function errorResult(
187
+ title: string,
188
+ error: Error | string,
189
+ options?: {
190
+ timing?: number;
191
+ suggestions?: string[];
192
+ }
193
+ ): CommandOutput {
194
+ const errorMessage = error instanceof Error ? error.message : error;
195
+ const errorStack = error instanceof Error ? error.stack : undefined;
196
+
197
+ return formatCommandResult({
198
+ title,
199
+ errors: [errorMessage],
200
+ details: options?.suggestions
201
+ ? [{ section: 'Suggestions', items: bulletList(options.suggestions) }]
202
+ : [],
203
+ timing: options?.timing,
204
+ status: 'error',
205
+ jsonData: {
206
+ error: errorMessage,
207
+ ...(errorStack && { stack: errorStack }),
208
+ },
209
+ });
210
+ }
211
+
212
+ /**
213
+ * High-level: Quick warning result
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * return warningResult('Configuration Updated', ['Deprecated option used'], {
218
+ * summary: { 'Files Updated': 3 },
219
+ * timing: 50,
220
+ * });
221
+ * ```
222
+ */
223
+ export function warningResult(
224
+ title: string,
225
+ warnings: string[],
226
+ options?: {
227
+ summary?: Record<string, string | number>;
228
+ timing?: number;
229
+ }
230
+ ): CommandOutput {
231
+ return formatCommandResult({
232
+ title,
233
+ warnings,
234
+ summary: options?.summary,
235
+ timing: options?.timing,
236
+ status: 'warning',
237
+ });
238
+ }
239
+
240
+ /**
241
+ * High-level: Info result
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * return infoResult('Help Information', {
246
+ * details: [
247
+ * { section: 'Usage', items: ['kb command --flag'] }
248
+ * ],
249
+ * });
250
+ * ```
251
+ */
252
+ export function infoResult(
253
+ title: string,
254
+ data?: {
255
+ summary?: Record<string, string | number>;
256
+ details?: Array<{ section: string; items: string[] }>;
257
+ timing?: number;
258
+ }
259
+ ): CommandOutput {
260
+ return formatCommandResult({
261
+ title,
262
+ summary: data?.summary,
263
+ details: data?.details,
264
+ timing: data?.timing,
265
+ status: 'info',
266
+ });
267
+ }