tachibot-mcp 2.0.2

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 (214) hide show
  1. package/.env.example +260 -0
  2. package/CHANGELOG.md +54 -0
  3. package/CODE_OF_CONDUCT.md +56 -0
  4. package/CONTRIBUTING.md +54 -0
  5. package/Dockerfile +36 -0
  6. package/LICENSE +644 -0
  7. package/README.md +201 -0
  8. package/SECURITY.md +95 -0
  9. package/dist/personality/komaai-expressions.js +12 -0
  10. package/dist/profiles/balanced.json +33 -0
  11. package/dist/profiles/code_focus.json +33 -0
  12. package/dist/profiles/full.json +33 -0
  13. package/dist/profiles/minimal.json +33 -0
  14. package/dist/profiles/research_power.json +33 -0
  15. package/dist/scripts/build-profiles.js +46 -0
  16. package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
  17. package/dist/src/application/services/focus/FocusTool.service.js +109 -0
  18. package/dist/src/application/services/focus/ModeRegistry.js +46 -0
  19. package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
  20. package/dist/src/application/services/focus/modes/status.mode.js +50 -0
  21. package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
  22. package/dist/src/collaborative-orchestrator.js +391 -0
  23. package/dist/src/config/model-constants.js +188 -0
  24. package/dist/src/config/model-defaults.js +57 -0
  25. package/dist/src/config/model-preferences.js +382 -0
  26. package/dist/src/config/timeout-config.js +130 -0
  27. package/dist/src/config.js +173 -0
  28. package/dist/src/domain/interfaces/IFocusMode.js +5 -0
  29. package/dist/src/domain/interfaces/IProvider.js +6 -0
  30. package/dist/src/domain/interfaces/ITool.js +5 -0
  31. package/dist/src/focus-deep.js +245 -0
  32. package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
  33. package/dist/src/mcp-client.js +90 -0
  34. package/dist/src/memory/index.js +17 -0
  35. package/dist/src/memory/memory-config.js +135 -0
  36. package/dist/src/memory/memory-interface.js +174 -0
  37. package/dist/src/memory/memory-manager.js +383 -0
  38. package/dist/src/memory/providers/devlog-provider.js +385 -0
  39. package/dist/src/memory/providers/hybrid-provider.js +399 -0
  40. package/dist/src/memory/providers/local-provider.js +388 -0
  41. package/dist/src/memory/providers/mem0-provider.js +337 -0
  42. package/dist/src/modes/architect.js +477 -0
  43. package/dist/src/modes/auditor.js +362 -0
  44. package/dist/src/modes/challenger.js +841 -0
  45. package/dist/src/modes/code-reviewer.js +382 -0
  46. package/dist/src/modes/commit-guardian.js +424 -0
  47. package/dist/src/modes/documentation-writer.js +572 -0
  48. package/dist/src/modes/scout.js +587 -0
  49. package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
  50. package/dist/src/modes/shared/helpers/index.js +17 -0
  51. package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
  52. package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
  53. package/dist/src/modes/test-architect.js +767 -0
  54. package/dist/src/modes/verifier.js +378 -0
  55. package/dist/src/monitoring/performance-monitor.js +435 -0
  56. package/dist/src/optimization/batch-executor.js +121 -0
  57. package/dist/src/optimization/context-pruner.js +196 -0
  58. package/dist/src/optimization/cost-monitor.js +338 -0
  59. package/dist/src/optimization/index.js +65 -0
  60. package/dist/src/optimization/model-router.js +264 -0
  61. package/dist/src/optimization/result-cache.js +114 -0
  62. package/dist/src/optimization/token-optimizer.js +257 -0
  63. package/dist/src/optimization/token-tracker.js +118 -0
  64. package/dist/src/orchestrator-instructions.js +128 -0
  65. package/dist/src/orchestrator-lite.js +139 -0
  66. package/dist/src/orchestrator.js +191 -0
  67. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
  68. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
  69. package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
  70. package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
  71. package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
  72. package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
  73. package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
  74. package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
  75. package/dist/src/profiles/balanced.js +37 -0
  76. package/dist/src/profiles/code_focus.js +37 -0
  77. package/dist/src/profiles/debug_intensive.js +59 -0
  78. package/dist/src/profiles/full.js +37 -0
  79. package/dist/src/profiles/minimal.js +37 -0
  80. package/dist/src/profiles/research_code.js +59 -0
  81. package/dist/src/profiles/research_power.js +37 -0
  82. package/dist/src/profiles/types.js +5 -0
  83. package/dist/src/profiles/workflow_builder.js +53 -0
  84. package/dist/src/prompt-engineer-lite.js +78 -0
  85. package/dist/src/prompt-engineer.js +399 -0
  86. package/dist/src/reasoning-chain.js +508 -0
  87. package/dist/src/sequential-thinking.js +291 -0
  88. package/dist/src/server-diagnostic.js +74 -0
  89. package/dist/src/server-raw.js +158 -0
  90. package/dist/src/server-simple.js +58 -0
  91. package/dist/src/server.js +514 -0
  92. package/dist/src/session/session-logger.js +617 -0
  93. package/dist/src/session/session-manager.js +571 -0
  94. package/dist/src/session/session-tools.js +400 -0
  95. package/dist/src/tools/advanced-modes.js +200 -0
  96. package/dist/src/tools/claude-integration.js +356 -0
  97. package/dist/src/tools/consolidated/ai-router.js +174 -0
  98. package/dist/src/tools/consolidated/ai-tool.js +48 -0
  99. package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
  100. package/dist/src/tools/consolidated/environment-detector.js +80 -0
  101. package/dist/src/tools/consolidated/index.js +50 -0
  102. package/dist/src/tools/consolidated/search-tool.js +110 -0
  103. package/dist/src/tools/consolidated/workflow-tool.js +238 -0
  104. package/dist/src/tools/gemini-tools.js +329 -0
  105. package/dist/src/tools/grok-enhanced.js +376 -0
  106. package/dist/src/tools/grok-tools.js +299 -0
  107. package/dist/src/tools/lmstudio-tools.js +223 -0
  108. package/dist/src/tools/openai-tools.js +498 -0
  109. package/dist/src/tools/openrouter-tools.js +317 -0
  110. package/dist/src/tools/optimized-wrapper.js +204 -0
  111. package/dist/src/tools/perplexity-tools.js +294 -0
  112. package/dist/src/tools/pingpong-tool.js +343 -0
  113. package/dist/src/tools/qwen-wrapper.js +74 -0
  114. package/dist/src/tools/tool-router.js +444 -0
  115. package/dist/src/tools/unified-ai-provider.js +260 -0
  116. package/dist/src/tools/workflow-runner.js +425 -0
  117. package/dist/src/tools/workflow-validator-tool.js +107 -0
  118. package/dist/src/types.js +23 -0
  119. package/dist/src/utils/input-validator.js +130 -0
  120. package/dist/src/utils/model-router.js +91 -0
  121. package/dist/src/utils/progress-stream.js +255 -0
  122. package/dist/src/utils/provider-router.js +88 -0
  123. package/dist/src/utils/smart-api-client.js +146 -0
  124. package/dist/src/utils/table-builder.js +218 -0
  125. package/dist/src/utils/timestamp-formatter.js +134 -0
  126. package/dist/src/utils/tool-compressor.js +257 -0
  127. package/dist/src/utils/tool-config.js +201 -0
  128. package/dist/src/validators/dependency-graph-validator.js +147 -0
  129. package/dist/src/validators/interpolation-validator.js +222 -0
  130. package/dist/src/validators/output-usage-validator.js +151 -0
  131. package/dist/src/validators/syntax-validator.js +102 -0
  132. package/dist/src/validators/tool-registry-validator.js +123 -0
  133. package/dist/src/validators/tool-types.js +97 -0
  134. package/dist/src/validators/types.js +8 -0
  135. package/dist/src/validators/workflow-validator.js +134 -0
  136. package/dist/src/visualizer-lite.js +42 -0
  137. package/dist/src/visualizer.js +179 -0
  138. package/dist/src/workflows/circuit-breaker.js +199 -0
  139. package/dist/src/workflows/custom-workflows.js +451 -0
  140. package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
  141. package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
  142. package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
  143. package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
  144. package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
  145. package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
  146. package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
  147. package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
  148. package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
  149. package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
  150. package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
  151. package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
  152. package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
  153. package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
  154. package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
  155. package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
  156. package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
  157. package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
  158. package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
  159. package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
  160. package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
  161. package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
  162. package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
  163. package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
  164. package/dist/src/workflows/fallback-strategies.js +373 -0
  165. package/dist/src/workflows/message-queue.js +455 -0
  166. package/dist/src/workflows/model-router.js +189 -0
  167. package/dist/src/workflows/orchestrator-examples.js +174 -0
  168. package/dist/src/workflows/orchestrator-integration.js +200 -0
  169. package/dist/src/workflows/self-healing.js +524 -0
  170. package/dist/src/workflows/tool-mapper.js +407 -0
  171. package/dist/src/workflows/tool-orchestrator.js +796 -0
  172. package/dist/src/workflows/workflow-engine.js +573 -0
  173. package/dist/src/workflows/workflow-parser.js +283 -0
  174. package/dist/src/workflows/workflow-types.js +95 -0
  175. package/dist/src/workflows.js +568 -0
  176. package/dist/test-workflow-file-output.js +93 -0
  177. package/docs/API_KEYS.md +570 -0
  178. package/docs/CLAUDE_CODE_SETUP.md +181 -0
  179. package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
  180. package/docs/CONFIGURATION.md +745 -0
  181. package/docs/FOCUS_MODES.md +240 -0
  182. package/docs/INSTALLATION_BOTH.md +145 -0
  183. package/docs/TERMS.md +352 -0
  184. package/docs/TOOLS_REFERENCE.md +1622 -0
  185. package/docs/TOOL_PARAMETERS.md +496 -0
  186. package/docs/TOOL_PROFILES.md +236 -0
  187. package/docs/WORKFLOWS.md +987 -0
  188. package/docs/WORKFLOW_OUTPUT.md +198 -0
  189. package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
  190. package/docs/workflows/design-brainstorm.md +335 -0
  191. package/package.json +97 -0
  192. package/profiles/balanced.json +37 -0
  193. package/profiles/code_focus.json +37 -0
  194. package/profiles/debug_intensive.json +34 -0
  195. package/profiles/full.json +37 -0
  196. package/profiles/minimal.json +37 -0
  197. package/profiles/research_power.json +37 -0
  198. package/profiles/workflow_builder.json +37 -0
  199. package/smithery.yaml +66 -0
  200. package/start.sh +8 -0
  201. package/tools.config.json +81 -0
  202. package/tsconfig.json +18 -0
  203. package/workflows/accessibility-code-audit.yaml +92 -0
  204. package/workflows/code-architecture-review.yaml +202 -0
  205. package/workflows/code-review.yaml +142 -0
  206. package/workflows/core/iterative-problem-solver.yaml +283 -0
  207. package/workflows/creative-brainstorm-yaml.yaml +215 -0
  208. package/workflows/pingpong.yaml +141 -0
  209. package/workflows/system/README.md +412 -0
  210. package/workflows/system/challenger.yaml +175 -0
  211. package/workflows/system/scout.yaml +164 -0
  212. package/workflows/system/verifier.yaml +133 -0
  213. package/workflows/ultra-creative-brainstorm.yaml +318 -0
  214. package/workflows/ux-research-flow.yaml +92 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * SmartAPIClient - Adaptive timeout and retry system for external API calls
3
+ *
4
+ * Features:
5
+ * - Fixed timeouts with priority-based adjustment (interactive vs batch)
6
+ * - Exponential backoff with full jitter
7
+ * - Proper resource cleanup with AbortController
8
+ * - NO metrics collection - privacy-first design
9
+ */
10
+ export class SmartAPIClient {
11
+ constructor() {
12
+ // Default configuration
13
+ this.defaults = {
14
+ maxRetries: 3,
15
+ baseTimeoutMs: 30000, // 30 seconds
16
+ maxTimeoutMs: 120000, // 2 minutes
17
+ backoffBase: 2,
18
+ enableJitter: true
19
+ };
20
+ // Priority-specific timeout multipliers
21
+ this.priorityMultipliers = {
22
+ interactive: {
23
+ base: 0.5, // 50% of base timeout
24
+ max: 0.5 // 50% of max timeout
25
+ },
26
+ batch: {
27
+ base: 1.0, // 100% of base timeout
28
+ max: 1.0 // 100% of max timeout
29
+ }
30
+ };
31
+ // Singleton pattern
32
+ }
33
+ static getInstance() {
34
+ if (!SmartAPIClient.instance) {
35
+ SmartAPIClient.instance = new SmartAPIClient();
36
+ }
37
+ return SmartAPIClient.instance;
38
+ }
39
+ /**
40
+ * Call API with timeout and retry logic
41
+ */
42
+ async callWithRetries(apiCall, config) {
43
+ const fullConfig = { ...this.defaults, ...config };
44
+ const startTime = Date.now();
45
+ let lastError;
46
+ let attempt = 0;
47
+ while (attempt < fullConfig.maxRetries) {
48
+ const controller = new AbortController();
49
+ const timeoutMs = this.calculateTimeout(fullConfig.priority, fullConfig.baseTimeoutMs, fullConfig.maxTimeoutMs);
50
+ const timeoutId = setTimeout(() => {
51
+ controller.abort();
52
+ }, timeoutMs);
53
+ try {
54
+ const attemptStart = Date.now();
55
+ // Execute API call
56
+ const result = await Promise.race([
57
+ apiCall(),
58
+ this.createTimeoutPromise(timeoutMs, fullConfig.provider)
59
+ ]);
60
+ clearTimeout(timeoutId);
61
+ const latency = Date.now() - attemptStart;
62
+ console.log(`[SmartAPIClient] Success: ${fullConfig.provider} ` +
63
+ `(attempt ${attempt + 1}, ${latency}ms, timeout=${timeoutMs}ms)`);
64
+ return result;
65
+ }
66
+ catch (error) {
67
+ clearTimeout(timeoutId);
68
+ lastError = error;
69
+ console.error(`[SmartAPIClient] Attempt ${attempt + 1} failed for ${fullConfig.provider}: ${error.message}`);
70
+ // Check if we should retry
71
+ if (!this.shouldRetry(error, attempt, fullConfig.maxRetries)) {
72
+ break;
73
+ }
74
+ // Wait before retry with exponential backoff + jitter
75
+ await this.backoffWithJitter(attempt, fullConfig.backoffBase, fullConfig.enableJitter);
76
+ attempt++;
77
+ }
78
+ finally {
79
+ // Ensure cleanup
80
+ if (!controller.signal.aborted) {
81
+ controller.abort();
82
+ }
83
+ }
84
+ }
85
+ const totalTime = Date.now() - startTime;
86
+ throw new Error(`[SmartAPIClient] All retries exhausted for ${fullConfig.provider} ` +
87
+ `(${attempt} attempts in ${totalTime}ms): ${lastError?.message || 'Unknown error'}`);
88
+ }
89
+ /**
90
+ * Calculate timeout based on priority
91
+ */
92
+ calculateTimeout(priority, baseTimeout, maxTimeout) {
93
+ const finalTimeout = Math.min(baseTimeout * this.priorityMultipliers[priority].base, maxTimeout * this.priorityMultipliers[priority].max);
94
+ return finalTimeout;
95
+ }
96
+ /**
97
+ * Exponential backoff with full jitter
98
+ */
99
+ async backoffWithJitter(attempt, base, enableJitter) {
100
+ const exponentialDelay = Math.pow(base, attempt) * 1000;
101
+ const cappedDelay = Math.min(exponentialDelay, 10000); // Cap at 10 seconds
102
+ const finalDelay = enableJitter
103
+ ? Math.random() * cappedDelay // Full jitter: random(0, cappedDelay)
104
+ : cappedDelay;
105
+ console.log(`[SmartAPIClient] Backing off for ${Math.round(finalDelay)}ms ` +
106
+ `(attempt ${attempt + 1}, ${enableJitter ? 'with' : 'without'} jitter)`);
107
+ await new Promise(resolve => setTimeout(resolve, finalDelay));
108
+ }
109
+ /**
110
+ * Determine if we should retry based on error type and attempt count
111
+ */
112
+ shouldRetry(error, attempt, maxRetries) {
113
+ if (attempt >= maxRetries - 1) {
114
+ return false;
115
+ }
116
+ // Retry on timeout, network errors, 5xx errors
117
+ const retryablePatterns = [
118
+ 'timeout',
119
+ 'ETIMEDOUT',
120
+ 'ECONNRESET',
121
+ 'ENOTFOUND',
122
+ 'ECONNREFUSED',
123
+ '500',
124
+ '502',
125
+ '503',
126
+ '504'
127
+ ];
128
+ const errorMessage = error?.message?.toLowerCase() || '';
129
+ const isRetryable = retryablePatterns.some(pattern => errorMessage.includes(pattern.toLowerCase()));
130
+ console.log(`[SmartAPIClient] Error "${errorMessage.slice(0, 50)}..." is ` +
131
+ `${isRetryable ? 'retryable' : 'not retryable'}`);
132
+ return isRetryable;
133
+ }
134
+ /**
135
+ * Create a timeout promise for Promise.race
136
+ */
137
+ createTimeoutPromise(timeoutMs, provider) {
138
+ return new Promise((_, reject) => {
139
+ setTimeout(() => {
140
+ reject(new Error(`Timeout after ${timeoutMs}ms for ${provider}`));
141
+ }, timeoutMs);
142
+ });
143
+ }
144
+ }
145
+ // Export singleton instance
146
+ export const smartAPIClient = SmartAPIClient.getInstance();
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Beautiful Unicode box-drawing table builder using cli-table3
3
+ * Provides a fluent API for creating readable, professional tables
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const table = new TableBuilder()
8
+ * .withHeaders(['Status', 'Model', 'Conclusion'])
9
+ * .withAlignments(['center', 'left', 'center'])
10
+ * .addRow(['✅', 'grok-4', '✓ true'])
11
+ * .build();
12
+ * ```
13
+ */
14
+ import Table from 'cli-table3';
15
+ /**
16
+ * Predefined table styles
17
+ */
18
+ export const TableStyles = {
19
+ /**
20
+ * Beautiful Unicode box-drawing characters
21
+ * Uses double lines for outer border, single lines for inner
22
+ */
23
+ unicode: {
24
+ chars: {
25
+ 'top': '═',
26
+ 'top-mid': '╤',
27
+ 'top-left': '╔',
28
+ 'top-right': '╗',
29
+ 'bottom': '═',
30
+ 'bottom-mid': '╧',
31
+ 'bottom-left': '╚',
32
+ 'bottom-right': '╝',
33
+ 'left': '║',
34
+ 'left-mid': '╟',
35
+ 'mid': '─',
36
+ 'mid-mid': '┼',
37
+ 'right': '║',
38
+ 'right-mid': '╢',
39
+ 'middle': '│'
40
+ },
41
+ style: {
42
+ head: [], // No color styling for headers
43
+ border: [] // No color styling for borders
44
+ }
45
+ },
46
+ /**
47
+ * Compact Unicode style with single lines
48
+ */
49
+ compact: {
50
+ chars: {
51
+ 'top': '─',
52
+ 'top-mid': '┬',
53
+ 'top-left': '┌',
54
+ 'top-right': '┐',
55
+ 'bottom': '─',
56
+ 'bottom-mid': '┴',
57
+ 'bottom-left': '└',
58
+ 'bottom-right': '┘',
59
+ 'left': '│',
60
+ 'left-mid': '├',
61
+ 'mid': '─',
62
+ 'mid-mid': '┼',
63
+ 'right': '│',
64
+ 'right-mid': '┤',
65
+ 'middle': '│'
66
+ },
67
+ style: {
68
+ head: [],
69
+ border: []
70
+ }
71
+ },
72
+ /**
73
+ * ASCII-only style for maximum compatibility
74
+ */
75
+ ascii: {
76
+ chars: {
77
+ 'top': '-',
78
+ 'top-mid': '+',
79
+ 'top-left': '+',
80
+ 'top-right': '+',
81
+ 'bottom': '-',
82
+ 'bottom-mid': '+',
83
+ 'bottom-left': '+',
84
+ 'bottom-right': '+',
85
+ 'left': '|',
86
+ 'left-mid': '+',
87
+ 'mid': '-',
88
+ 'mid-mid': '+',
89
+ 'right': '|',
90
+ 'right-mid': '+',
91
+ 'middle': '|'
92
+ },
93
+ style: {
94
+ head: [],
95
+ border: []
96
+ }
97
+ }
98
+ };
99
+ /**
100
+ * Fluent API table builder with beautiful Unicode box-drawing
101
+ */
102
+ export class TableBuilder {
103
+ constructor() {
104
+ this.headers = [];
105
+ this.alignments = [];
106
+ this.rows = [];
107
+ this.style = TableStyles.unicode;
108
+ }
109
+ /**
110
+ * Set table headers
111
+ */
112
+ withHeaders(headers) {
113
+ this.headers = headers;
114
+ return this;
115
+ }
116
+ /**
117
+ * Set column alignments
118
+ * @param alignments - Array of 'left', 'center', or 'right'
119
+ */
120
+ withAlignments(alignments) {
121
+ this.alignments = alignments;
122
+ return this;
123
+ }
124
+ /**
125
+ * Set explicit column widths
126
+ * @param widths - Array of column widths in characters
127
+ */
128
+ withColumnWidths(widths) {
129
+ this.colWidths = widths;
130
+ return this;
131
+ }
132
+ /**
133
+ * Use a predefined style
134
+ * @param styleName - 'unicode', 'compact', or 'ascii'
135
+ */
136
+ withStyle(styleName) {
137
+ this.style = TableStyles[styleName];
138
+ return this;
139
+ }
140
+ /**
141
+ * Use custom box-drawing characters
142
+ * @param chars - Custom character set
143
+ */
144
+ withCustomChars(chars) {
145
+ this.style = {
146
+ ...this.style,
147
+ chars: { ...this.style.chars, ...chars }
148
+ };
149
+ return this;
150
+ }
151
+ /**
152
+ * Add a single row to the table
153
+ * @param row - Array of cell values
154
+ */
155
+ addRow(row) {
156
+ this.rows.push(row);
157
+ return this;
158
+ }
159
+ /**
160
+ * Add multiple rows at once
161
+ * @param rows - Array of row arrays
162
+ */
163
+ addRows(rows) {
164
+ this.rows.push(...rows);
165
+ return this;
166
+ }
167
+ /**
168
+ * Build and return the formatted table string
169
+ * @returns Formatted table with newline prefix for spacing
170
+ */
171
+ build() {
172
+ const options = {
173
+ head: this.headers.length > 0 ? this.headers : undefined,
174
+ colAligns: this.alignments.length > 0 ? this.alignments : undefined,
175
+ ...this.style
176
+ };
177
+ // Only add colWidths if explicitly set
178
+ if (this.colWidths && this.colWidths.length > 0) {
179
+ options.colWidths = this.colWidths;
180
+ }
181
+ const table = new Table(options);
182
+ if (this.rows.length > 0) {
183
+ table.push(...this.rows);
184
+ }
185
+ // Add newline prefix for better spacing in output
186
+ return '\n' + table.toString();
187
+ }
188
+ /**
189
+ * Build and return without the leading newline
190
+ * @returns Formatted table without prefix spacing
191
+ */
192
+ buildRaw() {
193
+ return this.build().trimStart();
194
+ }
195
+ }
196
+ /**
197
+ * Quick helper function for simple tables
198
+ * @param headers - Column headers
199
+ * @param rows - Table rows
200
+ * @param alignments - Optional column alignments
201
+ * @returns Formatted table string
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * const table = quickTable(
206
+ * ['Name', 'Age'],
207
+ * [['Alice', 30], ['Bob', 25]],
208
+ * ['left', 'right']
209
+ * );
210
+ * ```
211
+ */
212
+ export function quickTable(headers, rows, alignments) {
213
+ const builder = new TableBuilder().withHeaders(headers).addRows(rows);
214
+ if (alignments) {
215
+ builder.withAlignments(alignments);
216
+ }
217
+ return builder.build();
218
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Timestamp Formatter - Human-readable timestamps for workflow/session output
3
+ * Format: YYYY-MM-DD-DayName-HH-MM-shortid
4
+ * Example: 2025-11-23-Sunday-22-44-a1b2c3d4
5
+ */
6
+ import { randomUUID } from 'crypto';
7
+ /**
8
+ * Day names for human readability
9
+ */
10
+ const DAY_NAMES = [
11
+ 'Sunday',
12
+ 'Monday',
13
+ 'Tuesday',
14
+ 'Wednesday',
15
+ 'Thursday',
16
+ 'Friday',
17
+ 'Saturday'
18
+ ];
19
+ /**
20
+ * Format a date as human-readable timestamp
21
+ * @param date - Date to format (defaults to now)
22
+ * @param includeShortId - Whether to include short UUID (default: true)
23
+ * @returns Formatted timestamp string
24
+ *
25
+ * @example
26
+ * formatTimestamp() // "2025-11-23-Sunday-22-44-a1b2c3d4"
27
+ * formatTimestamp(new Date(), false) // "2025-11-23-Sunday-22-44"
28
+ */
29
+ export function formatTimestamp(date = new Date(), includeShortId = true) {
30
+ const year = date.getFullYear();
31
+ const month = String(date.getMonth() + 1).padStart(2, '0');
32
+ const day = String(date.getDate()).padStart(2, '0');
33
+ const dayName = DAY_NAMES[date.getDay()];
34
+ const hours = String(date.getHours()).padStart(2, '0');
35
+ const minutes = String(date.getMinutes()).padStart(2, '0');
36
+ const parts = [year, month, day, dayName, hours, minutes];
37
+ if (includeShortId) {
38
+ const shortId = randomUUID().split('-')[0];
39
+ parts.push(shortId);
40
+ }
41
+ return parts.join('-');
42
+ }
43
+ /**
44
+ * Parse a human-readable timestamp back to Date
45
+ * @param timestamp - Formatted timestamp string
46
+ * @returns Date object or null if invalid
47
+ *
48
+ * @example
49
+ * parseTimestamp("2025-11-23-Sunday-22-44-a1b2c3d4") // Date object
50
+ */
51
+ export function parseTimestamp(timestamp) {
52
+ try {
53
+ // Format: YYYY-MM-DD-DayName-HH-MM-shortid
54
+ const parts = timestamp.split('-');
55
+ if (parts.length < 6) {
56
+ return null;
57
+ }
58
+ const [year, month, day, _dayName, hours, minutes] = parts;
59
+ const date = new Date(parseInt(year), parseInt(month) - 1, // JS months are 0-indexed
60
+ parseInt(day), parseInt(hours), parseInt(minutes), 0, 0);
61
+ if (isNaN(date.getTime())) {
62
+ return null;
63
+ }
64
+ return date;
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Generate a workflow ID with human-readable timestamp
72
+ * @param workflowName - Optional workflow name to include
73
+ * @returns Workflow ID string
74
+ *
75
+ * @example
76
+ * generateWorkflowId() // "2025-11-23-Sunday-22-44-a1b2c3d4"
77
+ * generateWorkflowId("pingpong") // "2025-11-23-Sunday-22-44-a1b2c3d4"
78
+ */
79
+ export function generateWorkflowId(workflowName) {
80
+ // Don't include workflow name in the folder name - it's already in the parent path
81
+ // workflow-output/{workflowName}/{timestamp}/
82
+ return formatTimestamp();
83
+ }
84
+ /**
85
+ * Generate a session ID with human-readable timestamp
86
+ * @param mode - Session mode (e.g., "advanced-pingpong", "workflow-test")
87
+ * @returns Session ID string
88
+ *
89
+ * @example
90
+ * generateSessionId("advanced-pingpong") // "session-2025-11-23-Sunday-22-44-advanced-pingpong"
91
+ */
92
+ export function generateSessionId(mode) {
93
+ const timestamp = formatTimestamp(new Date(), false); // No short ID in session names
94
+ return `session-${timestamp}-${mode}`;
95
+ }
96
+ /**
97
+ * Check if a timestamp is from today
98
+ */
99
+ export function isToday(timestamp) {
100
+ const parsed = parseTimestamp(timestamp);
101
+ if (!parsed)
102
+ return false;
103
+ const today = new Date();
104
+ return (parsed.getFullYear() === today.getFullYear() &&
105
+ parsed.getMonth() === today.getMonth() &&
106
+ parsed.getDate() === today.getDate());
107
+ }
108
+ /**
109
+ * Get a human-readable relative time string
110
+ * @example "2 hours ago", "just now", "yesterday"
111
+ */
112
+ export function getRelativeTime(timestamp) {
113
+ const parsed = parseTimestamp(timestamp);
114
+ if (!parsed)
115
+ return 'unknown';
116
+ const now = new Date();
117
+ const diffMs = now.getTime() - parsed.getTime();
118
+ const diffMins = Math.floor(diffMs / (1000 * 60));
119
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
120
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
121
+ if (diffMins < 1)
122
+ return 'just now';
123
+ if (diffMins < 60)
124
+ return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`;
125
+ if (diffHours < 24)
126
+ return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
127
+ if (diffDays === 1)
128
+ return 'yesterday';
129
+ if (diffDays < 7)
130
+ return `${diffDays} days ago`;
131
+ if (diffDays < 30)
132
+ return `${Math.floor(diffDays / 7)} week${Math.floor(diffDays / 7) > 1 ? 's' : ''} ago`;
133
+ return parsed.toLocaleDateString();
134
+ }