prjct-cli 0.20.0 → 0.21.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 (236) hide show
  1. package/CHANGELOG.md +24 -6
  2. package/CLAUDE.md +56 -15
  3. package/README.md +5 -6
  4. package/bin/prjct +59 -42
  5. package/bin/prjct.ts +60 -0
  6. package/core/__tests__/agentic/memory-system.test.ts +18 -3
  7. package/core/__tests__/agentic/plan-mode.test.ts +55 -26
  8. package/core/__tests__/agentic/prompt-builder.test.ts +6 -6
  9. package/core/__tests__/utils/project-commands.test.ts +72 -0
  10. package/core/agentic/agent-router.ts +3 -12
  11. package/core/agentic/command-executor.ts +372 -3
  12. package/core/agentic/context-builder.ts +7 -27
  13. package/core/agentic/ground-truth.ts +604 -5
  14. package/core/agentic/index.ts +180 -0
  15. package/core/agentic/loop-detector.ts +418 -4
  16. package/core/agentic/memory-system.ts +857 -3
  17. package/core/agentic/plan-mode.ts +491 -4
  18. package/core/agentic/prompt-builder.ts +44 -65
  19. package/core/agentic/services.ts +13 -5
  20. package/core/agentic/skill-loader.ts +112 -0
  21. package/core/agentic/smart-context.ts +37 -122
  22. package/core/agentic/template-loader.ts +79 -122
  23. package/core/agentic/tool-registry.ts +5 -11
  24. package/core/agents/index.ts +1 -1
  25. package/core/agents/performance.ts +4 -2
  26. package/core/bus/bus.ts +262 -0
  27. package/core/bus/index.ts +3 -313
  28. package/core/commands/analysis.ts +5 -5
  29. package/core/commands/analytics.ts +11 -11
  30. package/core/commands/base.ts +33 -209
  31. package/core/commands/cleanup.ts +148 -0
  32. package/core/commands/command-data.ts +346 -0
  33. package/core/commands/commands.ts +216 -0
  34. package/core/commands/design.ts +83 -0
  35. package/core/commands/index.ts +13 -207
  36. package/core/commands/maintenance.ts +52 -473
  37. package/core/commands/planning.ts +3 -3
  38. package/core/commands/register.ts +104 -0
  39. package/core/commands/registry.ts +441 -0
  40. package/core/commands/setup.ts +25 -9
  41. package/core/commands/shipping.ts +48 -11
  42. package/core/commands/snapshots.ts +299 -0
  43. package/core/commands/workflow.ts +2 -2
  44. package/core/constants/index.ts +254 -4
  45. package/core/domain/agent-loader.ts +5 -6
  46. package/core/domain/task-stack.ts +555 -4
  47. package/core/errors.ts +127 -1
  48. package/core/events/events.ts +87 -0
  49. package/core/events/index.ts +4 -138
  50. package/core/index.ts +15 -23
  51. package/core/infrastructure/agent-detector.ts +126 -201
  52. package/core/infrastructure/author-detector.ts +99 -171
  53. package/core/infrastructure/command-installer.ts +476 -4
  54. package/core/infrastructure/config-manager.ts +41 -37
  55. package/core/infrastructure/path-manager.ts +59 -9
  56. package/core/infrastructure/permission-manager.ts +286 -0
  57. package/core/integrations/notion/client.ts +323 -0
  58. package/core/integrations/notion/index.ts +43 -0
  59. package/core/integrations/notion/setup.ts +230 -0
  60. package/core/integrations/notion/sync.ts +311 -0
  61. package/core/integrations/notion/templates.ts +234 -0
  62. package/core/outcomes/analyzer.ts +7 -41
  63. package/core/outcomes/index.ts +1 -1
  64. package/core/outcomes/recorder.ts +1 -1
  65. package/core/plugin/builtin/notion.ts +178 -0
  66. package/core/{plugins → plugin/builtin}/webhook.ts +6 -22
  67. package/core/plugin/loader.ts +5 -5
  68. package/core/plugin/registry.ts +2 -2
  69. package/core/schemas/ideas.ts +85 -54
  70. package/core/schemas/index.ts +14 -33
  71. package/core/schemas/permissions.ts +177 -0
  72. package/core/schemas/project.ts +39 -12
  73. package/core/schemas/roadmap.ts +94 -59
  74. package/core/schemas/schemas.ts +39 -0
  75. package/core/schemas/shipped.ts +87 -60
  76. package/core/schemas/state.ts +110 -70
  77. package/core/server/index.ts +21 -0
  78. package/core/server/routes.ts +165 -0
  79. package/core/server/server.ts +136 -0
  80. package/core/server/sse.ts +135 -0
  81. package/core/services/agent-service.ts +170 -0
  82. package/core/services/breakdown-service.ts +126 -0
  83. package/core/services/index.ts +21 -0
  84. package/core/services/memory-service.ts +108 -0
  85. package/core/services/project-service.ts +146 -0
  86. package/core/services/skill-service.ts +253 -0
  87. package/core/session/compaction.ts +257 -0
  88. package/core/session/index.ts +20 -8
  89. package/core/{infrastructure/session-manager/migration.ts → session/log-migration.ts} +9 -9
  90. package/core/{infrastructure/session-manager/session-manager.ts → session/session-log-manager.ts} +27 -26
  91. package/core/session/{session-manager.ts → task-session-manager.ts} +7 -4
  92. package/core/session/utils.ts +1 -1
  93. package/core/storage/ideas-storage.ts +10 -26
  94. package/core/storage/index.ts +14 -162
  95. package/core/storage/queue-storage.ts +13 -11
  96. package/core/storage/shipped-storage.ts +4 -17
  97. package/core/storage/state-storage.ts +35 -43
  98. package/core/storage/storage-manager.ts +42 -52
  99. package/core/storage/storage.ts +160 -0
  100. package/core/sync/auth-config.ts +1 -8
  101. package/core/sync/index.ts +17 -10
  102. package/core/sync/oauth-handler.ts +1 -6
  103. package/core/sync/sync-client.ts +6 -34
  104. package/core/sync/sync-manager.ts +11 -40
  105. package/core/types/agentic.ts +577 -0
  106. package/core/types/agents.ts +145 -0
  107. package/core/types/bus.ts +82 -0
  108. package/core/types/commands.ts +366 -0
  109. package/core/types/config.ts +70 -0
  110. package/core/types/core.ts +96 -0
  111. package/core/types/domain.ts +71 -0
  112. package/core/types/events.ts +42 -0
  113. package/core/types/fs.ts +56 -0
  114. package/core/types/index.ts +396 -500
  115. package/core/types/infrastructure.ts +196 -0
  116. package/core/types/integrations.ts +57 -0
  117. package/core/{agentic/memory-system/types.ts → types/memory.ts} +33 -8
  118. package/core/{outcomes/types.ts → types/outcomes.ts} +53 -8
  119. package/core/types/plugin.ts +25 -0
  120. package/core/types/server.ts +54 -0
  121. package/core/types/services.ts +65 -0
  122. package/core/types/session.ts +135 -0
  123. package/core/types/storage.ts +148 -0
  124. package/core/types/sync.ts +121 -0
  125. package/core/types/task.ts +72 -0
  126. package/core/types/template.ts +24 -0
  127. package/core/types/utils.ts +90 -0
  128. package/core/utils/cache.ts +195 -0
  129. package/core/utils/collection-filters.ts +245 -0
  130. package/core/utils/date-helper.ts +1 -5
  131. package/core/utils/file-helper.ts +20 -10
  132. package/core/utils/jsonl-helper.ts +5 -8
  133. package/core/utils/markdown-builder.ts +277 -0
  134. package/core/utils/project-commands.ts +132 -0
  135. package/core/utils/runtime.ts +119 -0
  136. package/dist/bin/prjct.mjs +12568 -0
  137. package/package.json +13 -8
  138. package/scripts/build.js +106 -0
  139. package/scripts/postinstall.js +50 -8
  140. package/templates/agentic/subagent-generation.md +1 -1
  141. package/templates/commands/init.md +43 -0
  142. package/templates/commands/notion-setup.md +191 -0
  143. package/templates/commands/serve.md +118 -0
  144. package/templates/commands/ship.md +13 -2
  145. package/templates/commands/skill.md +110 -0
  146. package/templates/commands/sync.md +1 -1
  147. package/templates/commands/test.md +23 -4
  148. package/templates/mcp-config.json +28 -0
  149. package/templates/permissions/default.jsonc +60 -0
  150. package/templates/permissions/permissive.jsonc +49 -0
  151. package/templates/permissions/strict.jsonc +62 -0
  152. package/templates/skills/code-review.md +47 -0
  153. package/templates/skills/debug.md +61 -0
  154. package/templates/skills/refactor.md +47 -0
  155. package/templates/subagents/domain/devops.md +1 -1
  156. package/templates/subagents/domain/testing.md +6 -10
  157. package/templates/subagents/workflow/prjct-shipper.md +16 -7
  158. package/templates/tools/bash.txt +22 -0
  159. package/templates/tools/edit.txt +18 -0
  160. package/templates/tools/glob.txt +19 -0
  161. package/templates/tools/grep.txt +21 -0
  162. package/templates/tools/read.txt +14 -0
  163. package/templates/tools/task.txt +20 -0
  164. package/templates/tools/webfetch.txt +16 -0
  165. package/templates/tools/websearch.txt +18 -0
  166. package/templates/tools/write.txt +17 -0
  167. package/core/agentic/command-executor/command-executor.ts +0 -312
  168. package/core/agentic/command-executor/index.ts +0 -16
  169. package/core/agentic/command-executor/status-signal.ts +0 -38
  170. package/core/agentic/command-executor/types.ts +0 -79
  171. package/core/agentic/ground-truth/index.ts +0 -76
  172. package/core/agentic/ground-truth/types.ts +0 -33
  173. package/core/agentic/ground-truth/utils.ts +0 -48
  174. package/core/agentic/ground-truth/verifiers/analyze.ts +0 -54
  175. package/core/agentic/ground-truth/verifiers/done.ts +0 -75
  176. package/core/agentic/ground-truth/verifiers/feature.ts +0 -70
  177. package/core/agentic/ground-truth/verifiers/index.ts +0 -37
  178. package/core/agentic/ground-truth/verifiers/init.ts +0 -52
  179. package/core/agentic/ground-truth/verifiers/now.ts +0 -57
  180. package/core/agentic/ground-truth/verifiers/ship.ts +0 -85
  181. package/core/agentic/ground-truth/verifiers/spec.ts +0 -45
  182. package/core/agentic/ground-truth/verifiers/sync.ts +0 -47
  183. package/core/agentic/ground-truth/verifiers.ts +0 -6
  184. package/core/agentic/loop-detector/error-analysis.ts +0 -97
  185. package/core/agentic/loop-detector/hallucination.ts +0 -71
  186. package/core/agentic/loop-detector/index.ts +0 -41
  187. package/core/agentic/loop-detector/loop-detector.ts +0 -222
  188. package/core/agentic/loop-detector/types.ts +0 -66
  189. package/core/agentic/memory-system/history.ts +0 -53
  190. package/core/agentic/memory-system/index.ts +0 -192
  191. package/core/agentic/memory-system/patterns.ts +0 -156
  192. package/core/agentic/memory-system/semantic-memories.ts +0 -278
  193. package/core/agentic/memory-system/session.ts +0 -21
  194. package/core/agentic/plan-mode/approval.ts +0 -57
  195. package/core/agentic/plan-mode/constants.ts +0 -44
  196. package/core/agentic/plan-mode/index.ts +0 -28
  197. package/core/agentic/plan-mode/plan-mode.ts +0 -407
  198. package/core/agentic/plan-mode/types.ts +0 -193
  199. package/core/agents/types.ts +0 -126
  200. package/core/command-registry/categories.ts +0 -23
  201. package/core/command-registry/commands.ts +0 -15
  202. package/core/command-registry/core-commands.ts +0 -344
  203. package/core/command-registry/index.ts +0 -158
  204. package/core/command-registry/optional-commands.ts +0 -163
  205. package/core/command-registry/setup-commands.ts +0 -83
  206. package/core/command-registry/types.ts +0 -59
  207. package/core/command-registry.ts +0 -9
  208. package/core/commands/types.ts +0 -185
  209. package/core/commands.ts +0 -11
  210. package/core/constants/formats.ts +0 -187
  211. package/core/context-sync.ts +0 -18
  212. package/core/data/index.ts +0 -27
  213. package/core/data/md-base-manager.ts +0 -203
  214. package/core/data/md-ideas-manager.ts +0 -155
  215. package/core/data/md-queue-manager.ts +0 -180
  216. package/core/data/md-shipped-manager.ts +0 -90
  217. package/core/data/md-state-manager.ts +0 -137
  218. package/core/domain/task-stack/index.ts +0 -19
  219. package/core/domain/task-stack/parser.ts +0 -86
  220. package/core/domain/task-stack/storage.ts +0 -123
  221. package/core/domain/task-stack/task-stack.ts +0 -340
  222. package/core/domain/task-stack/types.ts +0 -51
  223. package/core/infrastructure/command-installer/command-installer.ts +0 -327
  224. package/core/infrastructure/command-installer/global-config.ts +0 -136
  225. package/core/infrastructure/command-installer/index.ts +0 -25
  226. package/core/infrastructure/command-installer/types.ts +0 -41
  227. package/core/infrastructure/session-manager/index.ts +0 -23
  228. package/core/infrastructure/session-manager/types.ts +0 -45
  229. package/core/infrastructure/session-manager.ts +0 -8
  230. package/core/serializers/ideas-serializer.ts +0 -187
  231. package/core/serializers/index.ts +0 -36
  232. package/core/serializers/queue-serializer.ts +0 -210
  233. package/core/serializers/shipped-serializer.ts +0 -108
  234. package/core/serializers/state-serializer.ts +0 -136
  235. package/core/session/types.ts +0 -29
  236. /package/core/infrastructure/{agents/claude-agent.ts → claude-agent.ts} +0 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Storage Types
3
+ * Types for data persistence layer.
4
+ */
5
+
6
+ // =============================================================================
7
+ // Core Storage Interface
8
+ // =============================================================================
9
+
10
+ /**
11
+ * Generic storage interface for granular data access
12
+ */
13
+ export interface Storage {
14
+ write<T>(path: string[], data: T): Promise<void>
15
+ read<T>(path: string[]): Promise<T | null>
16
+ list(prefix: string[]): Promise<string[][]>
17
+ delete(path: string[]): Promise<void>
18
+ exists(path: string[]): Promise<boolean>
19
+ }
20
+
21
+ // =============================================================================
22
+ // Shipped Storage Types
23
+ // =============================================================================
24
+
25
+ /**
26
+ * Shipped feature record (simple version used by shipped-storage.ts)
27
+ */
28
+ export interface ShippedFeature {
29
+ id: string
30
+ name: string
31
+ shippedAt: string
32
+ version: string
33
+ description?: string
34
+ tasks?: string[]
35
+ duration?: string
36
+ type?: 'feature' | 'fix' | 'improvement' | 'refactor'
37
+ agent?: string
38
+ changes?: ShipChange[]
39
+ codeSnippets?: string[]
40
+ commit?: CommitInfo
41
+ codeMetrics?: CodeMetrics
42
+ qualityMetrics?: QualityMetrics
43
+ quantitativeImpact?: string
44
+ tasksCompleted?: number
45
+ featureId?: string
46
+ }
47
+
48
+ export interface ShipChange {
49
+ description: string
50
+ type: 'added' | 'changed' | 'fixed' | 'removed'
51
+ }
52
+
53
+ export interface CommitInfo {
54
+ hash: string
55
+ message: string
56
+ branch: string
57
+ }
58
+
59
+ export interface CodeMetrics {
60
+ filesChanged: number
61
+ linesAdded: number
62
+ linesRemoved: number
63
+ commits: number
64
+ }
65
+
66
+ export interface QualityMetrics {
67
+ lintStatus: 'pass' | 'warning' | 'fail' | 'skipped'
68
+ lintDetails?: string
69
+ testStatus: 'pass' | 'warning' | 'fail' | 'skipped'
70
+ testDetails?: string
71
+ }
72
+
73
+ export interface Duration {
74
+ hours: number
75
+ minutes: number
76
+ totalMinutes: number
77
+ }
78
+
79
+ /**
80
+ * Shipped items collection
81
+ */
82
+ export interface ShippedJson {
83
+ shipped: ShippedFeature[]
84
+ lastUpdated: string
85
+ }
86
+
87
+ // =============================================================================
88
+ // Ideas Storage Types
89
+ // =============================================================================
90
+
91
+ export type IdeaStatus = 'pending' | 'converted' | 'completed' | 'archived'
92
+ export type IdeaPriority = 'low' | 'medium' | 'high'
93
+
94
+ /**
95
+ * Idea record
96
+ */
97
+ export interface Idea {
98
+ id: string
99
+ text: string
100
+ status: IdeaStatus
101
+ priority: IdeaPriority
102
+ tags: string[]
103
+ addedAt: string
104
+ convertedTo?: string
105
+ details?: string
106
+ painPoints?: string[]
107
+ solutions?: string[]
108
+ filesAffected?: string[]
109
+ impactEffort?: ImpactEffort
110
+ stack?: TechStack
111
+ modules?: IdeaModule[]
112
+ roles?: IdeaRole[]
113
+ risks?: string[]
114
+ risksCount?: number
115
+ createdAt?: string
116
+ }
117
+
118
+ export interface ImpactEffort {
119
+ impact: 'high' | 'medium' | 'low'
120
+ effort: 'high' | 'medium' | 'low'
121
+ }
122
+
123
+ export interface TechStack {
124
+ frontend?: string
125
+ backend?: string
126
+ payments?: string
127
+ ai?: string
128
+ deploy?: string
129
+ other?: string[]
130
+ }
131
+
132
+ export interface IdeaModule {
133
+ name: string
134
+ description: string
135
+ }
136
+
137
+ export interface IdeaRole {
138
+ name: string
139
+ description: string
140
+ }
141
+
142
+ /**
143
+ * Ideas collection
144
+ */
145
+ export interface IdeasJson {
146
+ ideas: Idea[]
147
+ lastUpdated: string
148
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Sync Types
3
+ * Types for sync and cloud modules.
4
+ */
5
+
6
+ // =============================================================================
7
+ // OAuth Types
8
+ // =============================================================================
9
+
10
+ /**
11
+ * Result of an authentication attempt
12
+ */
13
+ export interface AuthResult {
14
+ success: boolean
15
+ email?: string
16
+ error?: string
17
+ }
18
+
19
+ /**
20
+ * Authentication configuration stored in ~/.prjct-cli/config/auth.json
21
+ */
22
+ export interface AuthConfig {
23
+ apiKey: string | null
24
+ apiUrl: string
25
+ userId: string | null
26
+ email: string | null
27
+ lastAuth: string | null
28
+ }
29
+
30
+ // =============================================================================
31
+ // Sync Manager Types
32
+ // =============================================================================
33
+
34
+ /**
35
+ * Result of a full sync operation (push + pull)
36
+ */
37
+ export interface SyncManagerResult {
38
+ success: boolean
39
+ skipped: boolean
40
+ reason?: 'no_auth' | 'no_pending' | 'error'
41
+ pushed?: {
42
+ count: number
43
+ syncedAt: string
44
+ }
45
+ pulled?: {
46
+ count: number
47
+ syncedAt: string
48
+ }
49
+ error?: string
50
+ }
51
+
52
+ /**
53
+ * Result of pushing events to the server
54
+ */
55
+ export interface PushResult {
56
+ success: boolean
57
+ skipped: boolean
58
+ reason?: 'no_auth' | 'no_pending' | 'error'
59
+ count?: number
60
+ syncedAt?: string
61
+ error?: string
62
+ }
63
+
64
+ /**
65
+ * Result of pulling events from the server
66
+ */
67
+ export interface PullResult {
68
+ success: boolean
69
+ skipped: boolean
70
+ reason?: 'no_auth' | 'error'
71
+ count?: number
72
+ applied?: number
73
+ syncedAt?: string
74
+ error?: string
75
+ }
76
+
77
+ // =============================================================================
78
+ // Sync Client Types
79
+ // =============================================================================
80
+
81
+ /**
82
+ * Result of batch push to API
83
+ */
84
+ export interface SyncBatchResult {
85
+ success: boolean
86
+ processed: number
87
+ errors: Array<{ index: number; error: string }>
88
+ syncedAt: string
89
+ }
90
+
91
+ /**
92
+ * Result of pull from API
93
+ */
94
+ export interface SyncPullResult {
95
+ events: Array<{
96
+ type: string
97
+ path: string[]
98
+ data: unknown
99
+ timestamp: string
100
+ }>
101
+ syncedAt: string
102
+ }
103
+
104
+ /**
105
+ * Project sync status from API
106
+ */
107
+ export interface SyncStatus {
108
+ projectId: string
109
+ lastSync: string | null
110
+ pendingCount: number
111
+ hasConflicts: boolean
112
+ }
113
+
114
+ /**
115
+ * Error from sync client
116
+ */
117
+ export interface SyncClientError {
118
+ code: 'AUTH_REQUIRED' | 'NETWORK_ERROR' | 'API_ERROR' | 'UNKNOWN'
119
+ message: string
120
+ status?: number
121
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Task Types
3
+ * Types for task tracking and analysis.
4
+ */
5
+
6
+ export interface Task {
7
+ id: string
8
+ description: string
9
+ status: 'pending' | 'in_progress' | 'completed' | 'blocked'
10
+ createdAt: string
11
+ completedAt?: string
12
+ duration?: string
13
+ metadata?: TaskMetadata
14
+ }
15
+
16
+ export interface TaskMetadata {
17
+ domain?: string
18
+ complexity?: 'low' | 'medium' | 'high'
19
+ agent?: string
20
+ tags?: string[]
21
+ }
22
+
23
+ /**
24
+ * Result of analyzing a task to determine routing and complexity.
25
+ */
26
+ export interface TaskAnalysis {
27
+ /** Primary domain detected (e.g., 'frontend', 'backend', 'devops') */
28
+ primaryDomain: string
29
+ /** Confidence score (0-1) */
30
+ confidence: number
31
+ /** Semantic analysis of task description */
32
+ semantic: SemanticAnalysis
33
+ /** Historical analysis from past similar tasks */
34
+ historical: HistoricalAnalysis
35
+ /** Complexity level */
36
+ complexity: 'low' | 'medium' | 'high'
37
+ /** Project-specific data used in analysis */
38
+ projectData: ProjectAnalysisData
39
+ /** Keywords that matched domain patterns */
40
+ matchedKeywords: string[]
41
+ /** Human-readable reason for domain assignment */
42
+ reason: string
43
+ /** Alternative domains considered */
44
+ alternatives: string[]
45
+ }
46
+
47
+ export interface SemanticAnalysis {
48
+ /** Detected intent */
49
+ intent: string
50
+ /** Key entities in the task */
51
+ entities: string[]
52
+ /** Sentiment score */
53
+ sentiment: number
54
+ }
55
+
56
+ export interface HistoricalAnalysis {
57
+ /** Similar past tasks count */
58
+ similarTasksCount: number
59
+ /** Average duration of similar tasks */
60
+ avgDuration: string | null
61
+ /** Success rate of similar tasks */
62
+ successRate: number
63
+ }
64
+
65
+ export interface ProjectAnalysisData {
66
+ /** Available agents */
67
+ availableAgents: string[]
68
+ /** Stack technologies */
69
+ stack: string[]
70
+ /** Recent activity domains */
71
+ recentDomains: string[]
72
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Template Types
3
+ * Types for command templates.
4
+ */
5
+
6
+ export interface Template {
7
+ name: string
8
+ content: string
9
+ frontmatter: TemplateFrontmatter
10
+ }
11
+
12
+ export interface TemplateFrontmatter {
13
+ name: string
14
+ description?: string
15
+ category?: string
16
+ allowedTools?: string[]
17
+ validation?: ValidationRule[]
18
+ }
19
+
20
+ export interface ValidationRule {
21
+ type: string
22
+ field?: string
23
+ message?: string
24
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Utility Types
3
+ * Common utility types and file system types.
4
+ */
5
+
6
+ // Re-export file system types
7
+ export {
8
+ NodeError,
9
+ isNotFoundError,
10
+ isPermissionError,
11
+ isDirNotEmptyError,
12
+ isFileExistsError,
13
+ isNodeError,
14
+ } from './fs'
15
+
16
+ export type AsyncFunction<T = unknown> = (...args: unknown[]) => Promise<T>
17
+
18
+ export type MaybePromise<T> = T | Promise<T>
19
+
20
+ export interface FileInfo {
21
+ path: string
22
+ content: string
23
+ mtime?: Date
24
+ size?: number
25
+ }
26
+
27
+ export interface LogLevel {
28
+ debug: 0
29
+ info: 1
30
+ warn: 2
31
+ error: 3
32
+ }
33
+
34
+ // =============================================================================
35
+ // Date Helper Types
36
+ // =============================================================================
37
+
38
+ export interface DateComponents {
39
+ year: string
40
+ month: string
41
+ day: string
42
+ }
43
+
44
+ // =============================================================================
45
+ // Cache Types
46
+ // =============================================================================
47
+
48
+ export interface CacheEntry<T> {
49
+ data: T
50
+ timestamp: number
51
+ }
52
+
53
+ export interface CacheOptions {
54
+ /** TTL in milliseconds (default: 5000) */
55
+ ttl?: number
56
+ /** Max entries before eviction (default: 50) */
57
+ maxSize?: number
58
+ }
59
+
60
+ export interface CacheStats {
61
+ size: number
62
+ maxSize: number
63
+ ttl: number
64
+ }
65
+
66
+ // =============================================================================
67
+ // Project Commands Types
68
+ // =============================================================================
69
+
70
+ type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'
71
+ type DetectedStack = 'js' | 'python' | 'go' | 'rust' | 'dotnet' | 'java' | 'unknown'
72
+
73
+ interface DetectedCommand {
74
+ command: string
75
+ tool: string
76
+ }
77
+
78
+ export interface DetectedProjectCommands {
79
+ stack: DetectedStack
80
+ packageManager?: PackageManager
81
+ lint?: DetectedCommand
82
+ typecheck?: DetectedCommand
83
+ test?: DetectedCommand
84
+ }
85
+
86
+ // =============================================================================
87
+ // Runtime Types
88
+ // =============================================================================
89
+
90
+ export type Runtime = 'bun' | 'node'
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Cache Utilities - Shared caching primitives for storage layers
3
+ *
4
+ * Provides two cache implementations:
5
+ * - TTLCache: Time-based cache with LRU eviction (for StorageManager)
6
+ * - LazyCache: Single-project lazy loading cache (for memory system)
7
+ */
8
+
9
+ import type { CacheEntry, CacheOptions, CacheStats } from '../types'
10
+
11
+ /**
12
+ * TTL Cache with LRU eviction
13
+ *
14
+ * Used by StorageManager for project-keyed caching.
15
+ * Automatically evicts expired entries and oldest entries when over capacity.
16
+ */
17
+ export class TTLCache<T> {
18
+ private cache = new Map<string, CacheEntry<T>>()
19
+ private readonly ttl: number
20
+ private readonly maxSize: number
21
+
22
+ constructor(options: CacheOptions = {}) {
23
+ this.ttl = options.ttl ?? 5000
24
+ this.maxSize = options.maxSize ?? 50
25
+ }
26
+
27
+ /**
28
+ * Check if entry exists and is not expired
29
+ */
30
+ isValid(key: string): boolean {
31
+ const entry = this.cache.get(key)
32
+ if (!entry) return false
33
+ return Date.now() - entry.timestamp < this.ttl
34
+ }
35
+
36
+ /**
37
+ * Get entry if valid, otherwise null
38
+ */
39
+ get(key: string): T | null {
40
+ const entry = this.cache.get(key)
41
+
42
+ if (!entry) return null
43
+
44
+ if (!this.isValid(key)) {
45
+ this.cache.delete(key)
46
+ return null
47
+ }
48
+
49
+ return entry.data
50
+ }
51
+
52
+ /**
53
+ * Set entry with current timestamp
54
+ */
55
+ set(key: string, data: T): void {
56
+ this.cache.set(key, { data, timestamp: Date.now() })
57
+ this.evictOldEntries()
58
+ }
59
+
60
+ /**
61
+ * Delete entry
62
+ */
63
+ delete(key: string): void {
64
+ this.cache.delete(key)
65
+ }
66
+
67
+ /**
68
+ * Clear all entries
69
+ */
70
+ clear(): void {
71
+ this.cache.clear()
72
+ }
73
+
74
+ /**
75
+ * Check if key exists (may be expired)
76
+ */
77
+ has(key: string): boolean {
78
+ return this.cache.has(key)
79
+ }
80
+
81
+ /**
82
+ * Get number of entries (including expired)
83
+ */
84
+ get size(): number {
85
+ return this.cache.size
86
+ }
87
+
88
+ /**
89
+ * Evict oldest entries if over max size
90
+ */
91
+ private evictOldEntries(): void {
92
+ if (this.cache.size <= this.maxSize) return
93
+
94
+ const entries = Array.from(this.cache.entries()).sort(
95
+ (a, b) => a[1].timestamp - b[1].timestamp
96
+ )
97
+
98
+ const toRemove = entries.slice(0, this.cache.size - this.maxSize)
99
+ for (const [key] of toRemove) {
100
+ this.cache.delete(key)
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Get cache statistics
106
+ */
107
+ stats(): CacheStats {
108
+ return {
109
+ size: this.cache.size,
110
+ maxSize: this.maxSize,
111
+ ttl: this.ttl,
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Remove all expired entries
117
+ */
118
+ prune(): number {
119
+ let removed = 0
120
+ for (const key of this.cache.keys()) {
121
+ if (!this.isValid(key)) {
122
+ this.cache.delete(key)
123
+ removed++
124
+ }
125
+ }
126
+ return removed
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Single-project lazy cache
132
+ *
133
+ * Used by CachedStore for memory system (one project at a time).
134
+ * Simpler than TTLCache - just tracks if data is loaded for current project.
135
+ */
136
+ export class LazyCache<T> {
137
+ private data: T | null = null
138
+ private loaded = false
139
+ private projectId: string | null = null
140
+
141
+ /**
142
+ * Check if loaded for a specific project
143
+ */
144
+ isLoaded(projectId?: string): boolean {
145
+ if (projectId) {
146
+ return this.loaded && this.projectId === projectId
147
+ }
148
+ return this.loaded
149
+ }
150
+
151
+ /**
152
+ * Get cached data (may be null if not loaded)
153
+ */
154
+ get(): T | null {
155
+ return this.data
156
+ }
157
+
158
+ /**
159
+ * Set data for a project
160
+ */
161
+ set(projectId: string, data: T): void {
162
+ this.data = data
163
+ this.loaded = true
164
+ this.projectId = projectId
165
+ }
166
+
167
+ /**
168
+ * Reset cache
169
+ */
170
+ reset(): void {
171
+ this.data = null
172
+ this.loaded = false
173
+ this.projectId = null
174
+ }
175
+
176
+ /**
177
+ * Get current project ID
178
+ */
179
+ getProjectId(): string | null {
180
+ return this.projectId
181
+ }
182
+
183
+ /**
184
+ * Check if cache is empty
185
+ */
186
+ isEmpty(): boolean {
187
+ return !this.loaded || this.data === null
188
+ }
189
+ }
190
+
191
+ // Default export for CommonJS compatibility
192
+ export default {
193
+ TTLCache,
194
+ LazyCache,
195
+ }