k0ntext 3.3.1 → 3.5.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 (180) hide show
  1. package/README.md +225 -26
  2. package/dist/agents/cleanup-agent.d.ts.map +1 -1
  3. package/dist/agents/cleanup-agent.js +18 -6
  4. package/dist/agents/cleanup-agent.js.map +1 -1
  5. package/dist/agents/drift-agent.d.ts +7 -0
  6. package/dist/agents/drift-agent.d.ts.map +1 -1
  7. package/dist/agents/drift-agent.js +29 -8
  8. package/dist/agents/drift-agent.js.map +1 -1
  9. package/dist/cli/commands/cleanup.d.ts.map +1 -1
  10. package/dist/cli/commands/cleanup.js +8 -1
  11. package/dist/cli/commands/cleanup.js.map +1 -1
  12. package/dist/cli/commands/drift-detect.d.ts.map +1 -1
  13. package/dist/cli/commands/drift-detect.js +21 -1
  14. package/dist/cli/commands/drift-detect.js.map +1 -1
  15. package/dist/cli/commands/restore.d.ts +12 -0
  16. package/dist/cli/commands/restore.d.ts.map +1 -0
  17. package/dist/cli/commands/restore.js +261 -0
  18. package/dist/cli/commands/restore.js.map +1 -0
  19. package/dist/cli/commands/sync-templates.d.ts +15 -0
  20. package/dist/cli/commands/sync-templates.d.ts.map +1 -0
  21. package/dist/cli/commands/sync-templates.js +181 -0
  22. package/dist/cli/commands/sync-templates.js.map +1 -0
  23. package/dist/cli/commands/version-check.d.ts +12 -0
  24. package/dist/cli/commands/version-check.d.ts.map +1 -0
  25. package/dist/cli/commands/version-check.js +133 -0
  26. package/dist/cli/commands/version-check.js.map +1 -0
  27. package/dist/cli/generate.d.ts +5 -0
  28. package/dist/cli/generate.d.ts.map +1 -1
  29. package/dist/cli/generate.js +80 -16
  30. package/dist/cli/generate.js.map +1 -1
  31. package/dist/cli/index.js +145 -1
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/cli/repl/index.d.ts +1 -0
  34. package/dist/cli/repl/index.d.ts.map +1 -1
  35. package/dist/cli/repl/index.js +18 -6
  36. package/dist/cli/repl/index.js.map +1 -1
  37. package/dist/cli/utils/backup-manager.d.ts +94 -0
  38. package/dist/cli/utils/backup-manager.d.ts.map +1 -0
  39. package/dist/cli/utils/backup-manager.js +230 -0
  40. package/dist/cli/utils/backup-manager.js.map +1 -0
  41. package/dist/cli/utils/file-detector.d.ts +87 -0
  42. package/dist/cli/utils/file-detector.d.ts.map +1 -0
  43. package/dist/cli/utils/file-detector.js +131 -0
  44. package/dist/cli/utils/file-detector.js.map +1 -0
  45. package/dist/cli/utils/index.d.ts +9 -0
  46. package/dist/cli/utils/index.d.ts.map +1 -0
  47. package/dist/cli/utils/index.js +9 -0
  48. package/dist/cli/utils/index.js.map +1 -0
  49. package/dist/cli/utils/modification-prompt.d.ts +41 -0
  50. package/dist/cli/utils/modification-prompt.d.ts.map +1 -0
  51. package/dist/cli/utils/modification-prompt.js +84 -0
  52. package/dist/cli/utils/modification-prompt.js.map +1 -0
  53. package/dist/cli/version/checker.d.ts +47 -0
  54. package/dist/cli/version/checker.d.ts.map +1 -0
  55. package/dist/cli/version/checker.js +143 -0
  56. package/dist/cli/version/checker.js.map +1 -0
  57. package/dist/cli/version/comparator.d.ts +46 -0
  58. package/dist/cli/version/comparator.d.ts.map +1 -0
  59. package/dist/cli/version/comparator.js +99 -0
  60. package/dist/cli/version/comparator.js.map +1 -0
  61. package/dist/cli/version/index.d.ts +11 -0
  62. package/dist/cli/version/index.d.ts.map +1 -0
  63. package/dist/cli/version/index.js +11 -0
  64. package/dist/cli/version/index.js.map +1 -0
  65. package/dist/cli/version/parser.d.ts +38 -0
  66. package/dist/cli/version/parser.d.ts.map +1 -0
  67. package/dist/cli/version/parser.js +90 -0
  68. package/dist/cli/version/parser.js.map +1 -0
  69. package/dist/cli/version/prompt.d.ts +40 -0
  70. package/dist/cli/version/prompt.d.ts.map +1 -0
  71. package/dist/cli/version/prompt.js +162 -0
  72. package/dist/cli/version/prompt.js.map +1 -0
  73. package/dist/cli/version/types.d.ts +89 -0
  74. package/dist/cli/version/types.d.ts.map +1 -0
  75. package/dist/cli/version/types.js +7 -0
  76. package/dist/cli/version/types.js.map +1 -0
  77. package/dist/db/client.d.ts +64 -2
  78. package/dist/db/client.d.ts.map +1 -1
  79. package/dist/db/client.js +148 -2
  80. package/dist/db/client.js.map +1 -1
  81. package/dist/db/schema.d.ts +41 -2
  82. package/dist/db/schema.d.ts.map +1 -1
  83. package/dist/db/schema.js +77 -2
  84. package/dist/db/schema.js.map +1 -1
  85. package/dist/mcp.js +2 -2
  86. package/dist/mcp.js.map +1 -1
  87. package/dist/template-engine/data-transformer.d.ts +17 -0
  88. package/dist/template-engine/data-transformer.d.ts.map +1 -0
  89. package/dist/template-engine/data-transformer.js +343 -0
  90. package/dist/template-engine/data-transformer.js.map +1 -0
  91. package/dist/template-engine/engine.d.ts +74 -0
  92. package/dist/template-engine/engine.d.ts.map +1 -0
  93. package/dist/template-engine/engine.js +183 -0
  94. package/dist/template-engine/engine.js.map +1 -0
  95. package/dist/template-engine/helpers.d.ts +81 -0
  96. package/dist/template-engine/helpers.d.ts.map +1 -0
  97. package/dist/template-engine/helpers.js +153 -0
  98. package/dist/template-engine/helpers.js.map +1 -0
  99. package/dist/template-engine/index.d.ts +10 -0
  100. package/dist/template-engine/index.d.ts.map +1 -0
  101. package/dist/template-engine/index.js +10 -0
  102. package/dist/template-engine/index.js.map +1 -0
  103. package/dist/template-engine/types.d.ts +147 -0
  104. package/dist/template-engine/types.d.ts.map +1 -0
  105. package/dist/template-engine/types.js +7 -0
  106. package/dist/template-engine/types.js.map +1 -0
  107. package/dist/template-sync/comparator.d.ts +138 -0
  108. package/dist/template-sync/comparator.d.ts.map +1 -0
  109. package/dist/template-sync/comparator.js +353 -0
  110. package/dist/template-sync/comparator.js.map +1 -0
  111. package/dist/template-sync/conflict-resolver.d.ts +112 -0
  112. package/dist/template-sync/conflict-resolver.d.ts.map +1 -0
  113. package/dist/template-sync/conflict-resolver.js +328 -0
  114. package/dist/template-sync/conflict-resolver.js.map +1 -0
  115. package/dist/template-sync/engine.d.ts +93 -0
  116. package/dist/template-sync/engine.d.ts.map +1 -0
  117. package/dist/template-sync/engine.js +350 -0
  118. package/dist/template-sync/engine.js.map +1 -0
  119. package/dist/template-sync/hasher.d.ts +67 -0
  120. package/dist/template-sync/hasher.d.ts.map +1 -0
  121. package/dist/template-sync/hasher.js +94 -0
  122. package/dist/template-sync/hasher.js.map +1 -0
  123. package/dist/template-sync/index.d.ts +20 -0
  124. package/dist/template-sync/index.d.ts.map +1 -0
  125. package/dist/template-sync/index.js +14 -0
  126. package/dist/template-sync/index.js.map +1 -0
  127. package/dist/template-sync/manifest.d.ts +131 -0
  128. package/dist/template-sync/manifest.d.ts.map +1 -0
  129. package/dist/template-sync/manifest.js +309 -0
  130. package/dist/template-sync/manifest.js.map +1 -0
  131. package/dist/template-sync/merger.d.ts +125 -0
  132. package/dist/template-sync/merger.d.ts.map +1 -0
  133. package/dist/template-sync/merger.js +371 -0
  134. package/dist/template-sync/merger.js.map +1 -0
  135. package/dist/template-sync/scanner.d.ts +106 -0
  136. package/dist/template-sync/scanner.d.ts.map +1 -0
  137. package/dist/template-sync/scanner.js +196 -0
  138. package/dist/template-sync/scanner.js.map +1 -0
  139. package/dist/template-sync/types.d.ts +199 -0
  140. package/dist/template-sync/types.d.ts.map +1 -0
  141. package/dist/template-sync/types.js +30 -0
  142. package/dist/template-sync/types.js.map +1 -0
  143. package/package.json +2 -1
  144. package/src/agents/cleanup-agent.ts +21 -6
  145. package/src/agents/drift-agent.ts +31 -8
  146. package/src/cli/commands/cleanup.ts +9 -1
  147. package/src/cli/commands/drift-detect.ts +24 -1
  148. package/src/cli/commands/restore.ts +318 -0
  149. package/src/cli/commands/sync-templates.ts +210 -0
  150. package/src/cli/commands/version-check.ts +158 -0
  151. package/src/cli/generate.ts +99 -17
  152. package/src/cli/index.ts +167 -1
  153. package/src/cli/repl/index.ts +16 -6
  154. package/src/cli/utils/backup-manager.ts +275 -0
  155. package/src/cli/utils/file-detector.ts +181 -0
  156. package/src/cli/utils/index.ts +9 -0
  157. package/src/cli/utils/modification-prompt.ts +112 -0
  158. package/src/cli/version/checker.ts +172 -0
  159. package/src/cli/version/comparator.ts +106 -0
  160. package/src/cli/version/index.ts +11 -0
  161. package/src/cli/version/parser.ts +101 -0
  162. package/src/cli/version/prompt.ts +208 -0
  163. package/src/cli/version/types.ts +95 -0
  164. package/src/db/client.ts +220 -3
  165. package/src/db/schema.ts +109 -2
  166. package/src/mcp.ts +2 -2
  167. package/src/template-engine/data-transformer.ts +367 -0
  168. package/src/template-engine/engine.ts +213 -0
  169. package/src/template-engine/helpers.ts +163 -0
  170. package/src/template-engine/index.ts +10 -0
  171. package/src/template-engine/types.ts +158 -0
  172. package/src/template-sync/comparator.ts +452 -0
  173. package/src/template-sync/conflict-resolver.ts +401 -0
  174. package/src/template-sync/engine.ts +417 -0
  175. package/src/template-sync/hasher.ts +104 -0
  176. package/src/template-sync/index.ts +60 -0
  177. package/src/template-sync/manifest.ts +358 -0
  178. package/src/template-sync/merger.ts +454 -0
  179. package/src/template-sync/scanner.ts +254 -0
  180. package/src/template-sync/types.ts +247 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Version Checker
3
+ *
4
+ * Checks context files for outdated versions.
5
+ * Integrates with database for efficient caching.
6
+ */
7
+
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+ import type { DatabaseClient } from '../../db/client.js';
11
+ import { parseVersion, hasVersionMarker } from './parser.js';
12
+ import { needsUpdate, getUpdateType } from './comparator.js';
13
+ import type {
14
+ CheckOptions,
15
+ FileVersionStatus,
16
+ VersionCheckResult,
17
+ OutdatedFile
18
+ } from './types.js';
19
+
20
+ /**
21
+ * Tool to file path mappings
22
+ */
23
+ const TOOL_FILES: Record<string, string[]> = {
24
+ claude: ['AI_CONTEXT.md', 'CLAUDE.md', '.claude/AI_CONTEXT.md'],
25
+ copilot: ['.github/copilot-instructions.md'],
26
+ cline: ['.clinerules'],
27
+ antigravity: ['.agent/README.md'],
28
+ windsurf: ['.windsurf/rules.md'],
29
+ aider: ['.aider.conf.yml'],
30
+ continue: ['.continue/config.json'],
31
+ cursor: ['.cursorrules'],
32
+ gemini: ['.gemini/config.md']
33
+ };
34
+
35
+ /**
36
+ * Check a single file for version status
37
+ *
38
+ * @param filePath - Full path to the file
39
+ * @param tool - Tool name
40
+ * @param currentVersion - Current k0ntext version
41
+ * @param db - Database client (optional, for modification detection)
42
+ * @returns File version status
43
+ */
44
+ export async function checkSingleFile(
45
+ filePath: string,
46
+ tool: string,
47
+ currentVersion: string,
48
+ db?: DatabaseClient
49
+ ): Promise<FileVersionStatus> {
50
+ // Check if file exists
51
+ let exists = false;
52
+ let content = '';
53
+ try {
54
+ content = await fs.readFile(filePath, 'utf-8');
55
+ exists = true;
56
+ } catch {
57
+ // File doesn't exist
58
+ }
59
+
60
+ // Check for version marker
61
+ const hasMarker = hasVersionMarker(content);
62
+ const fileVersion = parseVersion(content);
63
+
64
+ // Determine if outdated
65
+ const isOutdated = fileVersion ? needsUpdate(fileVersion, currentVersion) : false;
66
+ const updateType = fileVersion ? getUpdateType(fileVersion, currentVersion) : 'none';
67
+
68
+ // Check if user modified (from database)
69
+ let userModified = false;
70
+ if (db && exists) {
71
+ const tracked = db.getGeneratedFileInfo(tool, filePath);
72
+ if (tracked?.userModified) {
73
+ userModified = true;
74
+ }
75
+ }
76
+
77
+ return {
78
+ tool,
79
+ filePath,
80
+ exists,
81
+ fileVersion,
82
+ hasMarker,
83
+ isOutdated,
84
+ updateType,
85
+ userModified
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Check all context files for version status
91
+ *
92
+ * @param options - Check options
93
+ * @param db - Database client (optional)
94
+ * @returns Version check result
95
+ */
96
+ export async function checkContextFiles(
97
+ options: CheckOptions,
98
+ db?: DatabaseClient
99
+ ): Promise<VersionCheckResult> {
100
+ const { projectRoot, currentVersion, tools: toolsToCheck } = options;
101
+
102
+ const tools = toolsToCheck || Object.keys(TOOL_FILES);
103
+ const results: VersionCheckResult = {
104
+ currentVersion,
105
+ checked: 0,
106
+ outdated: [],
107
+ upToDate: [],
108
+ noVersion: []
109
+ };
110
+
111
+ for (const tool of tools) {
112
+ const files = TOOL_FILES[tool] || [];
113
+ const toolName = tool;
114
+
115
+ for (const relativePath of files) {
116
+ const fullPath = path.join(projectRoot, relativePath);
117
+
118
+ const status = await checkSingleFile(fullPath, toolName, currentVersion, db);
119
+ results.checked++;
120
+
121
+ if (!status.exists) {
122
+ continue; // Skip non-existent files
123
+ }
124
+
125
+ if (status.isOutdated) {
126
+ results.outdated.push({
127
+ tool: status.tool,
128
+ filePath: status.filePath,
129
+ fileVersion: status.fileVersion || 'unknown',
130
+ currentVersion,
131
+ updateType: status.updateType,
132
+ userModified: status.userModified
133
+ });
134
+ } else if (status.hasMarker) {
135
+ results.upToDate.push(status);
136
+ } else {
137
+ results.noVersion.push(status);
138
+ }
139
+ }
140
+ }
141
+
142
+ return results;
143
+ }
144
+
145
+ /**
146
+ * Get all context file paths for a tool
147
+ *
148
+ * @param tool - Tool name
149
+ * @returns Array of file paths
150
+ */
151
+ export function getToolFiles(tool: string): string[] {
152
+ return TOOL_FILES[tool] || [];
153
+ }
154
+
155
+ /**
156
+ * Check if a tool is supported
157
+ *
158
+ * @param tool - Tool name
159
+ * @returns True if supported
160
+ */
161
+ export function isSupportedTool(tool: string): boolean {
162
+ return tool in TOOL_FILES;
163
+ }
164
+
165
+ /**
166
+ * Get all supported tools
167
+ *
168
+ * @returns Array of tool names
169
+ */
170
+ export function getSupportedTools(): string[] {
171
+ return Object.keys(TOOL_FILES);
172
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Version Comparator
3
+ *
4
+ * Semantic version comparison for detecting outdated files.
5
+ * Reuses logic from UpdateChecker for consistency.
6
+ */
7
+
8
+ import type { UpdateType } from './types.js';
9
+
10
+ /**
11
+ * Parse semantic version string into components
12
+ *
13
+ * @param version - Version string (e.g., "3.3.1")
14
+ * @returns Object with major, minor, patch components
15
+ */
16
+ function parseSemver(version: string): { major: number; minor: number; patch: number } {
17
+ const parts = version.split('.').map(Number);
18
+
19
+ return {
20
+ major: parts[0] || 0,
21
+ minor: parts[1] || 0,
22
+ patch: parts[2] || 0
23
+ };
24
+ }
25
+
26
+ /**
27
+ * Compare two version strings
28
+ *
29
+ * @param a - First version string
30
+ * @param b - Second version string
31
+ * @returns Negative if a < b, positive if a > b, zero if equal
32
+ */
33
+ export function compareVersions(a: string, b: string): number {
34
+ const [cMajor, cMinor, cPatch] = a.split('.').map(Number);
35
+ const [lMajor, lMinor, lPatch] = b.split('.').map(Number);
36
+
37
+ if (lMajor !== cMajor) return lMajor - cMajor;
38
+ if (lMinor !== cMinor) return lMinor - cMinor;
39
+ return lPatch - cPatch;
40
+ }
41
+
42
+ /**
43
+ * Check if a file version needs updating
44
+ *
45
+ * @param fileVersion - Version from the file
46
+ * @param currentVersion - Current k0ntext version
47
+ * @returns True if file is outdated
48
+ */
49
+ export function needsUpdate(fileVersion: string, currentVersion: string): boolean {
50
+ if (fileVersion === currentVersion) return false;
51
+ return compareVersions(fileVersion, currentVersion) > 0;
52
+ }
53
+
54
+ /**
55
+ * Get the type of update needed
56
+ *
57
+ * @param fileVersion - Version from the file
58
+ * @param currentVersion - Current k0ntext version
59
+ * @returns Type of update: 'major', 'minor', 'patch', or 'none'
60
+ */
61
+ export function getUpdateType(fileVersion: string, currentVersion: string): UpdateType {
62
+ if (fileVersion === currentVersion) return 'none';
63
+
64
+ const [cMajor, cMinor, cPatch] = fileVersion.split('.').map(Number);
65
+ const [lMajor, lMinor, lPatch] = currentVersion.split('.').map(Number);
66
+
67
+ if (lMajor > cMajor) return 'major';
68
+ if (lMinor > cMinor) return 'minor';
69
+ if (lPatch > cPatch) return 'patch';
70
+
71
+ return 'none';
72
+ }
73
+
74
+ /**
75
+ * Format update type as a human-readable string
76
+ *
77
+ * @param type - Update type
78
+ * @returns Formatted string (e.g., "Major (3.0.0 → 3.1.0)")
79
+ */
80
+ export function formatUpdateType(type: UpdateType, from: string, to: string): string {
81
+ const emoji = {
82
+ major: '🚨',
83
+ minor: '✨',
84
+ patch: '🔧',
85
+ none: '✓'
86
+ }[type] || '→';
87
+
88
+ const label = {
89
+ major: 'Major',
90
+ minor: 'Minor',
91
+ patch: 'Patch',
92
+ none: 'Current'
93
+ }[type];
94
+
95
+ return `${emoji} ${label} (${from} → ${to})`;
96
+ }
97
+
98
+ /**
99
+ * Validate a version string format
100
+ *
101
+ * @param version - Version string to validate
102
+ * @returns True if valid semver format
103
+ */
104
+ export function isValidVersion(version: string): boolean {
105
+ return /^\d+\.\d+\.\d+/.test(version);
106
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Version Detection Module
3
+ *
4
+ * Exports all version detection functionality.
5
+ */
6
+
7
+ export * from './types.js';
8
+ export * from './parser.js';
9
+ export * from './comparator.js';
10
+ export * from './checker.js';
11
+ export * from './prompt.js';
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Version Parser
3
+ *
4
+ * Parses version strings from generated context files.
5
+ * Supports multiple version marker formats used by k0ntext.
6
+ */
7
+
8
+ /**
9
+ * Version marker patterns found in generated files
10
+ */
11
+ const VERSION_PATTERNS = [
12
+ // Format: *Generated by k0ntext v3.3.1*
13
+ /\*Generated by k0ntext v(\d+\.\d+\.\d+[^*)]*)\*/,
14
+ // Format: > **Version:** 3.3.1
15
+ /\*\*Version:\*\*\s*(\d+\.\d+\.\d+[^,\s]*)/,
16
+ // Format: > Version: 3.3.1
17
+ /Version:\s*(\d+\.\d+\.\d+[^,\s]*)/,
18
+ // Format: "generator_version": "3.3.1"
19
+ /"generator_version":\s*"(\d+\.\d+\.\d+[^"]*)"/,
20
+ // Format: <!-- Version: 3.3.1 -->
21
+ /<!--\s*Version:\s*(\d+\.\d+\.\d+[^-\s]*)/,
22
+ ] as const;
23
+
24
+ /**
25
+ * Parse version from file content
26
+ *
27
+ * @param content - File content to search for version
28
+ * @returns Version string if found, null otherwise
29
+ */
30
+ export function parseVersion(content: string): string | null {
31
+ if (!content || typeof content !== 'string') {
32
+ return null;
33
+ }
34
+
35
+ for (const pattern of VERSION_PATTERNS) {
36
+ const match = content.match(pattern);
37
+ if (match && match[1]) {
38
+ return match[1].trim();
39
+ }
40
+ }
41
+
42
+ return null;
43
+ }
44
+
45
+ /**
46
+ * Check if content has any version marker
47
+ *
48
+ * @param content - File content to check
49
+ * @returns True if any version pattern is found
50
+ */
51
+ export function hasVersionMarker(content: string): boolean {
52
+ if (!content || typeof content !== 'string') {
53
+ return false;
54
+ }
55
+
56
+ return VERSION_PATTERNS.some(pattern => pattern.test(content));
57
+ }
58
+
59
+ /**
60
+ * Extract version from first N lines of a file
61
+ * Useful for quick checks without reading entire file
62
+ *
63
+ * @param content - File content (or first N lines)
64
+ * @param lines - Number of lines to check (default: 50)
65
+ * @returns Version string if found, null otherwise
66
+ */
67
+ export function parseVersionFromHeader(content: string, lines = 50): string | null {
68
+ if (!content || typeof content !== 'string') {
69
+ return null;
70
+ }
71
+
72
+ // Only check first N lines
73
+ const linesToCheck = content.split('\n').slice(0, lines).join('\n');
74
+ return parseVersion(linesToCheck);
75
+ }
76
+
77
+ /**
78
+ * Get all version markers found in content
79
+ * Useful for debugging or validation
80
+ *
81
+ * @param content - File content to search
82
+ * @returns Array of found version strings
83
+ */
84
+ export function findAllVersions(content: string): string[] {
85
+ if (!content || typeof content !== 'string') {
86
+ return [];
87
+ }
88
+
89
+ const versions: string[] = [];
90
+
91
+ for (const pattern of VERSION_PATTERNS) {
92
+ const matches = content.matchAll(new RegExp(pattern, 'g'));
93
+ for (const match of matches) {
94
+ if (match[1]) {
95
+ versions.push(match[1].trim());
96
+ }
97
+ }
98
+ }
99
+
100
+ return [...new Set(versions)]; // Deduplicate
101
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Version Prompt
3
+ *
4
+ * Interactive prompts for version checking and regeneration.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import { confirm, select, checkbox } from '@inquirer/prompts';
9
+ import type {
10
+ VersionCheckResult,
11
+ RegenerationPromptResult,
12
+ RegenerationChoice
13
+ } from './types.js';
14
+ import { formatUpdateType } from './comparator.js';
15
+
16
+ /**
17
+ * Show a formatted summary of version check results
18
+ *
19
+ * @param result - Version check result
20
+ */
21
+ export function showVersionSummary(result: VersionCheckResult): void {
22
+ console.log('');
23
+ console.log(chalk.bold('Context File Version Check'));
24
+ console.log(chalk.dim('─'.repeat(50)));
25
+
26
+ if (result.outdated.length === 0 && result.noVersion.length === 0) {
27
+ console.log(chalk.green('✓ All context files are up to date!'));
28
+ console.log(chalk.dim(`Current version: ${result.currentVersion}`));
29
+ return;
30
+ }
31
+
32
+ // Show outdated files
33
+ if (result.outdated.length > 0) {
34
+ console.log('');
35
+ console.log(chalk.yellow(`⚠ ${result.outdated.length} file(s) need updates:`));
36
+ console.log('');
37
+
38
+ // Table header
39
+ console.log(
40
+ chalk.dim('Tool'.padEnd(12)) +
41
+ chalk.dim('File'.padEnd(30)) +
42
+ chalk.dim('Version')
43
+ );
44
+ console.log(chalk.dim('─'.repeat(54)));
45
+
46
+ for (const file of result.outdated) {
47
+ const toolCol = chalk.cyan(file.tool.padEnd(12));
48
+ const fileCol = file.filePath.padEnd(30);
49
+ const versionCol = formatUpdateType(
50
+ file.updateType,
51
+ file.fileVersion,
52
+ file.currentVersion
53
+ );
54
+
55
+ console.log(toolCol + fileCol + versionCol);
56
+
57
+ if (file.userModified) {
58
+ console.log(
59
+ chalk.dim(' '.repeat(12)) +
60
+ chalk.yellow('⚠ Has custom modifications')
61
+ );
62
+ }
63
+ }
64
+ }
65
+
66
+ // Show files without version markers
67
+ if (result.noVersion.length > 0) {
68
+ console.log('');
69
+ console.log(chalk.dim(`ℹ ${result.noVersion.length} file(s) without version markers:`));
70
+ for (const file of result.noVersion) {
71
+ console.log(chalk.dim(` ${file.filePath}`));
72
+ }
73
+ }
74
+
75
+ console.log('');
76
+ }
77
+
78
+ /**
79
+ * Prompt user for regeneration choice
80
+ *
81
+ * @param outdated - List of outdated files
82
+ * @returns User's regeneration choice
83
+ */
84
+ export async function promptRegeneration(
85
+ outdated: NonNullable<VersionCheckResult['outdated']>
86
+ ): Promise<RegenerationPromptResult> {
87
+ if (outdated.length === 0) {
88
+ return {
89
+ choice: 'skip',
90
+ includeModified: false
91
+ };
92
+ }
93
+
94
+ const hasModified = outdated.some(f => f.userModified);
95
+
96
+ // First prompt: what to update
97
+ const choice = await select<RegenerationChoice>({
98
+ message: 'Some context files are outdated. What would you like to do?',
99
+ choices: [
100
+ {
101
+ name: 'Update all files',
102
+ value: 'all',
103
+ description: 'Regenerate all outdated files'
104
+ },
105
+ {
106
+ name: 'Select specific files',
107
+ value: 'select',
108
+ description: 'Choose which files to update'
109
+ },
110
+ {
111
+ name: 'Skip for now',
112
+ value: 'skip',
113
+ description: 'Continue without updating'
114
+ }
115
+ ]
116
+ });
117
+
118
+ if (choice === 'skip') {
119
+ return {
120
+ choice: 'skip',
121
+ includeModified: false
122
+ };
123
+ }
124
+
125
+ // If there are modified files, ask about them
126
+ let includeModified = false;
127
+ if (hasModified) {
128
+ includeModified = await confirm({
129
+ message: chalk.yellow('⚠ Some files have your custom modifications. Include them?'),
130
+ default: false
131
+ });
132
+
133
+ if (!includeModified) {
134
+ console.log(chalk.dim('ℹ Modified files will be skipped.'));
135
+ }
136
+ }
137
+
138
+ // If user wants to select specific files
139
+ if (choice === 'select') {
140
+ const choices = outdated.map(f => {
141
+ const label = `${f.tool} (${f.fileVersion} → ${f.currentVersion})`;
142
+ const disabled = f.userModified && !includeModified
143
+ ? 'Has custom modifications'
144
+ : undefined;
145
+
146
+ return {
147
+ name: label,
148
+ value: `${f.tool}:${f.filePath}`,
149
+ disabled
150
+ };
151
+ });
152
+
153
+ const selected = await checkbox({
154
+ message: 'Select files to update:',
155
+ choices
156
+ });
157
+
158
+ // Extract tool names from selections
159
+ const selectedTools = selected.map(s => (s as string).split(':')[0]);
160
+
161
+ return {
162
+ choice: 'select',
163
+ selectedTools,
164
+ includeModified
165
+ };
166
+ }
167
+
168
+ return {
169
+ choice,
170
+ includeModified
171
+ };
172
+ }
173
+
174
+ /**
175
+ * Show a simple prompt to update outdated files
176
+ *
177
+ * @param result - Version check result
178
+ * @returns True if user wants to update
179
+ */
180
+ export async function promptToUpdate(result: VersionCheckResult): Promise<boolean> {
181
+ if (result.outdated.length === 0) {
182
+ return false;
183
+ }
184
+
185
+ const answer = await confirm({
186
+ message: `Update ${result.outdated.length} outdated context file(s)?`,
187
+ default: true
188
+ });
189
+
190
+ return answer;
191
+ }
192
+
193
+ /**
194
+ * Format a single file status for display
195
+ *
196
+ * @param status - File version status
197
+ * @returns Formatted string
198
+ */
199
+ export function formatFileStatus(status: {
200
+ tool: string;
201
+ filePath: string;
202
+ fileVersion: string | null;
203
+ currentVersion: string;
204
+ updateType?: string;
205
+ }): string {
206
+ const version = status.fileVersion || 'unknown';
207
+ return `${status.tool}: ${version} → ${status.currentVersion}`;
208
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Version Detection Types
3
+ *
4
+ * Type definitions for version detection and checking system.
5
+ */
6
+
7
+ /**
8
+ * Update type classification
9
+ */
10
+ export type UpdateType = 'major' | 'minor' | 'patch' | 'none';
11
+
12
+ /**
13
+ * Single file version status
14
+ */
15
+ export interface FileVersionStatus {
16
+ /** Tool name (claude, copilot, etc.) */
17
+ tool: string;
18
+ /** Full path to the file */
19
+ filePath: string;
20
+ /** Whether the file exists on disk */
21
+ exists: boolean;
22
+ /** Version string found in the file (if any) */
23
+ fileVersion: string | null;
24
+ /** Whether the file has a version marker */
25
+ hasMarker: boolean;
26
+ /** Whether the file is outdated compared to current version */
27
+ isOutdated: boolean;
28
+ /** Type of update needed (if outdated) */
29
+ updateType: UpdateType;
30
+ /** Whether the file has been modified by the user */
31
+ userModified: boolean;
32
+ /** Last time the file was checked */
33
+ lastChecked?: string;
34
+ }
35
+
36
+ /**
37
+ * Outdated file summary for prompting
38
+ */
39
+ export interface OutdatedFile {
40
+ tool: string;
41
+ filePath: string;
42
+ fileVersion: string;
43
+ currentVersion: string;
44
+ updateType: UpdateType;
45
+ userModified: boolean;
46
+ }
47
+
48
+ /**
49
+ * Version check result
50
+ */
51
+ export interface VersionCheckResult {
52
+ /** Current k0ntext package version */
53
+ currentVersion: string;
54
+ /** Total files checked */
55
+ checked: number;
56
+ /** List of outdated files */
57
+ outdated: OutdatedFile[];
58
+ /** List of up-to-date files */
59
+ upToDate: FileVersionStatus[];
60
+ /** List of files with no version marker */
61
+ noVersion: FileVersionStatus[];
62
+ }
63
+
64
+ /**
65
+ * Version check options
66
+ */
67
+ export interface CheckOptions {
68
+ /** Project root directory */
69
+ projectRoot: string;
70
+ /** Current k0ntext version */
71
+ currentVersion: string;
72
+ /** Specific tools to check (empty = all) */
73
+ tools?: string[];
74
+ /** Force re-check even if recently checked */
75
+ force?: boolean;
76
+ /** Whether to check file modifications */
77
+ checkModifications?: boolean;
78
+ }
79
+
80
+ /**
81
+ * Regeneration choice from user prompt
82
+ */
83
+ export type RegenerationChoice = 'all' | 'outdated' | 'select' | 'skip';
84
+
85
+ /**
86
+ * Prompt result for regeneration
87
+ */
88
+ export interface RegenerationPromptResult {
89
+ /** User's choice */
90
+ choice: RegenerationChoice;
91
+ /** Selected tools if choice is 'select' */
92
+ selectedTools?: string[];
93
+ /** Whether to include modified files */
94
+ includeModified: boolean;
95
+ }