@lssm/module.ai-chat 1.41.1 → 1.42.1

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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/ai-chat.feature.d.ts +12 -0
  4. package/dist/ai-chat.feature.d.ts.map +1 -0
  5. package/dist/ai-chat.feature.js +95 -1
  6. package/dist/ai-chat.feature.js.map +1 -0
  7. package/dist/ai-chat.operations.d.ts +243 -0
  8. package/dist/ai-chat.operations.d.ts.map +1 -0
  9. package/dist/ai-chat.operations.js +174 -0
  10. package/dist/ai-chat.operations.js.map +1 -0
  11. package/dist/context/context-builder.d.ts +57 -0
  12. package/dist/context/context-builder.d.ts.map +1 -0
  13. package/dist/context/context-builder.js +148 -2
  14. package/dist/context/context-builder.js.map +1 -0
  15. package/dist/context/file-operations.d.ts +100 -0
  16. package/dist/context/file-operations.d.ts.map +1 -0
  17. package/dist/context/file-operations.js +175 -1
  18. package/dist/context/file-operations.js.map +1 -0
  19. package/dist/context/index.d.ts +4 -0
  20. package/dist/context/index.js +5 -1
  21. package/dist/context/workspace-context.d.ts +117 -0
  22. package/dist/context/workspace-context.d.ts.map +1 -0
  23. package/dist/context/workspace-context.js +124 -2
  24. package/dist/context/workspace-context.js.map +1 -0
  25. package/dist/core/chat-service.d.ts +73 -0
  26. package/dist/core/chat-service.d.ts.map +1 -0
  27. package/dist/core/chat-service.js +215 -2
  28. package/dist/core/chat-service.js.map +1 -0
  29. package/dist/core/conversation-store.d.ts +74 -0
  30. package/dist/core/conversation-store.d.ts.map +1 -0
  31. package/dist/core/conversation-store.js +109 -1
  32. package/dist/core/conversation-store.js.map +1 -0
  33. package/dist/core/index.d.ts +4 -0
  34. package/dist/core/index.js +4 -1
  35. package/dist/core/message-types.d.ts +150 -0
  36. package/dist/core/message-types.d.ts.map +1 -0
  37. package/dist/events.d.ts +115 -0
  38. package/dist/events.d.ts.map +1 -0
  39. package/dist/events.js +100 -0
  40. package/dist/events.js.map +1 -0
  41. package/dist/index.d.ts +21 -0
  42. package/dist/index.js +23 -1
  43. package/dist/libs/schema/dist/EnumType.js +2 -0
  44. package/dist/libs/schema/dist/FieldType.js +50 -0
  45. package/dist/libs/schema/dist/FieldType.js.map +1 -0
  46. package/dist/libs/schema/dist/ScalarTypeEnum.js +237 -0
  47. package/dist/libs/schema/dist/ScalarTypeEnum.js.map +1 -0
  48. package/dist/libs/schema/dist/SchemaModel.js +40 -0
  49. package/dist/libs/schema/dist/SchemaModel.js.map +1 -0
  50. package/dist/libs/schema/dist/entity/defineEntity.js +1 -0
  51. package/dist/libs/schema/dist/entity/index.js +2 -0
  52. package/dist/libs/schema/dist/entity/types.js +1 -0
  53. package/dist/libs/schema/dist/index.js +6 -0
  54. package/dist/presentation/components/ChatContainer.d.ts +21 -0
  55. package/dist/presentation/components/ChatContainer.d.ts.map +1 -0
  56. package/dist/presentation/components/ChatContainer.js +63 -1
  57. package/dist/presentation/components/ChatContainer.js.map +1 -0
  58. package/dist/presentation/components/ChatInput.d.ts +35 -0
  59. package/dist/presentation/components/ChatInput.d.ts.map +1 -0
  60. package/dist/presentation/components/ChatInput.js +149 -1
  61. package/dist/presentation/components/ChatInput.js.map +1 -0
  62. package/dist/presentation/components/ChatMessage.d.ts +24 -0
  63. package/dist/presentation/components/ChatMessage.d.ts.map +1 -0
  64. package/dist/presentation/components/ChatMessage.js +136 -1
  65. package/dist/presentation/components/ChatMessage.js.map +1 -0
  66. package/dist/presentation/components/CodePreview.d.ts +40 -0
  67. package/dist/presentation/components/CodePreview.d.ts.map +1 -0
  68. package/dist/presentation/components/CodePreview.js +127 -2
  69. package/dist/presentation/components/CodePreview.js.map +1 -0
  70. package/dist/presentation/components/ContextIndicator.d.ts +26 -0
  71. package/dist/presentation/components/ContextIndicator.d.ts.map +1 -0
  72. package/dist/presentation/components/ContextIndicator.js +97 -1
  73. package/dist/presentation/components/ContextIndicator.js.map +1 -0
  74. package/dist/presentation/components/ModelPicker.d.ts +39 -0
  75. package/dist/presentation/components/ModelPicker.d.ts.map +1 -0
  76. package/dist/presentation/components/ModelPicker.js +202 -1
  77. package/dist/presentation/components/ModelPicker.js.map +1 -0
  78. package/dist/presentation/components/index.d.ts +7 -0
  79. package/dist/presentation/components/index.js +8 -1
  80. package/dist/presentation/hooks/index.d.ts +3 -0
  81. package/dist/presentation/hooks/index.js +4 -1
  82. package/dist/presentation/hooks/useChat.d.ts +67 -0
  83. package/dist/presentation/hooks/useChat.d.ts.map +1 -0
  84. package/dist/presentation/hooks/useChat.js +172 -1
  85. package/dist/presentation/hooks/useChat.js.map +1 -0
  86. package/dist/presentation/hooks/useProviders.d.ts +38 -0
  87. package/dist/presentation/hooks/useProviders.d.ts.map +1 -0
  88. package/dist/presentation/hooks/useProviders.js +41 -1
  89. package/dist/presentation/hooks/useProviders.js.map +1 -0
  90. package/dist/presentation/index.d.ts +11 -0
  91. package/dist/presentation/index.js +12 -1
  92. package/dist/providers/chat-utilities.d.ts +15 -0
  93. package/dist/providers/chat-utilities.d.ts.map +1 -0
  94. package/dist/providers/chat-utilities.js +17 -1
  95. package/dist/providers/chat-utilities.js.map +1 -0
  96. package/dist/providers/index.d.ts +3 -0
  97. package/dist/providers/index.js +4 -1
  98. package/dist/schema.d.ts +222 -0
  99. package/dist/schema.d.ts.map +1 -0
  100. package/dist/schema.js +102 -0
  101. package/dist/schema.js.map +1 -0
  102. package/package.json +29 -22
@@ -1,2 +1,148 @@
1
- function e(e){return Math.ceil(e.length/4)}function t(e,t){if(!t)return .5;let n=t.toLowerCase(),r=0;return e.name.toLowerCase().includes(n)&&(r+=.4),e.description?.toLowerCase().includes(n)&&(r+=.3),e.tags?.some(e=>e.toLowerCase().includes(n))&&(r+=.2),Math.min(r,1)}function n(e,t){if(!t)return .5;let n=t.toLowerCase(),r=0;return e.path.toLowerCase().includes(n)&&(r+=.5),e.name.toLowerCase().includes(n)&&(r+=.3),e.isSpec&&(r+=.2),Math.min(r,1)}var r=class{context;constructor(e){this.context=e}build(r={}){let i=r.maxTokens??4e3,a=[],o=0;if(r.includeSpecs?.length)for(let t of r.includeSpecs){let n=this.context.getSpecs().find(e=>e.name===t);if(n){let t={type:`spec`,path:n.path,summary:`${n.type}: ${n.name}${n.description?` - ${n.description}`:``}`,relevance:1};a.push(t),o+=e(t.summary??``)}}if(r.includeFiles?.length)for(let t of r.includeFiles){let n=this.context.getFiles().find(e=>e.path===t);if(n){let t={type:`file`,path:n.path,summary:`File: ${n.relativePath}`,relevance:1};a.push(t),o+=e(t.summary??``)}}if(r.query){let n=this.context.getSpecs().map(e=>({spec:e,score:t(e,r.query)})).filter(({score:e})=>e>.2).sort((e,t)=>t.score-e.score);for(let{spec:t,score:r}of n){if(o>=i)break;if(a.some(e=>e.path===t.path))continue;let n={type:`spec`,path:t.path,summary:`${t.type}: ${t.name}${t.description?` - ${t.description}`:``}`,relevance:r};a.push(n),o+=e(n.summary??``)}}if(r.query){let t=this.context.getFiles().map(e=>({file:e,score:n(e,r.query)})).filter(({score:e})=>e>.2).sort((e,t)=>t.score-e.score);for(let{file:n,score:r}of t){if(o>=i)break;if(a.some(e=>e.path===n.path))continue;let t={type:`file`,path:n.path,summary:`File: ${n.relativePath}`,relevance:r};a.push(t),o+=e(t.summary??``)}}let s=this.buildSummary(a);return{entries:a,summary:s,totalTokensEstimate:o+e(s)}}buildSummary(e){if(e.length===0)return this.context.getContextSummary();let t=[],n=this.context.getSummary();t.push(`Workspace: ${n.name}`),t.push(``);let r=e.filter(e=>e.type===`spec`);if(r.length>0){t.push(`### Relevant Specs`);for(let e of r)t.push(`- ${e.summary}`);t.push(``)}let i=e.filter(e=>e.type===`file`);if(i.length>0){t.push(`### Relevant Files`);for(let e of i)t.push(`- ${e.summary}`)}return t.join(`
2
- `)}};function i(e){return new r(e)}export{r as ContextBuilder,i as createContextBuilder};
1
+ //#region src/context/context-builder.ts
2
+ /**
3
+ * Estimates token count from string (rough approximation)
4
+ */
5
+ function estimateTokens(text) {
6
+ return Math.ceil(text.length / 4);
7
+ }
8
+ /**
9
+ * Calculate relevance score for a spec
10
+ */
11
+ function scoreSpec(spec, query) {
12
+ if (!query) return .5;
13
+ const lowerQuery = query.toLowerCase();
14
+ let score = 0;
15
+ if (spec.name.toLowerCase().includes(lowerQuery)) score += .4;
16
+ if (spec.description?.toLowerCase().includes(lowerQuery)) score += .3;
17
+ if (spec.tags?.some((t) => t.toLowerCase().includes(lowerQuery))) score += .2;
18
+ return Math.min(score, 1);
19
+ }
20
+ /**
21
+ * Calculate relevance score for a file
22
+ */
23
+ function scoreFile(file, query) {
24
+ if (!query) return .5;
25
+ const lowerQuery = query.toLowerCase();
26
+ let score = 0;
27
+ if (file.path.toLowerCase().includes(lowerQuery)) score += .5;
28
+ if (file.name.toLowerCase().includes(lowerQuery)) score += .3;
29
+ if (file.isSpec) score += .2;
30
+ return Math.min(score, 1);
31
+ }
32
+ /**
33
+ * Context builder for creating rich LLM context
34
+ */
35
+ var ContextBuilder = class {
36
+ context;
37
+ constructor(context) {
38
+ this.context = context;
39
+ }
40
+ /**
41
+ * Build context for a chat message
42
+ */
43
+ build(options = {}) {
44
+ const maxTokens = options.maxTokens ?? 4e3;
45
+ const entries = [];
46
+ let totalTokens = 0;
47
+ if (options.includeSpecs?.length) for (const specName of options.includeSpecs) {
48
+ const spec = this.context.getSpecs().find((s) => s.name === specName);
49
+ if (spec) {
50
+ const entry = {
51
+ type: "spec",
52
+ path: spec.path,
53
+ summary: `${spec.type}: ${spec.name}${spec.description ? ` - ${spec.description}` : ""}`,
54
+ relevance: 1
55
+ };
56
+ entries.push(entry);
57
+ totalTokens += estimateTokens(entry.summary ?? "");
58
+ }
59
+ }
60
+ if (options.includeFiles?.length) for (const filePath of options.includeFiles) {
61
+ const file = this.context.getFiles().find((f) => f.path === filePath);
62
+ if (file) {
63
+ const entry = {
64
+ type: "file",
65
+ path: file.path,
66
+ summary: `File: ${file.relativePath}`,
67
+ relevance: 1
68
+ };
69
+ entries.push(entry);
70
+ totalTokens += estimateTokens(entry.summary ?? "");
71
+ }
72
+ }
73
+ if (options.query) {
74
+ const scoredSpecs = this.context.getSpecs().map((spec) => ({
75
+ spec,
76
+ score: scoreSpec(spec, options.query)
77
+ })).filter(({ score }) => score > .2).sort((a, b) => b.score - a.score);
78
+ for (const { spec, score } of scoredSpecs) {
79
+ if (totalTokens >= maxTokens) break;
80
+ if (entries.some((e) => e.path === spec.path)) continue;
81
+ const entry = {
82
+ type: "spec",
83
+ path: spec.path,
84
+ summary: `${spec.type}: ${spec.name}${spec.description ? ` - ${spec.description}` : ""}`,
85
+ relevance: score
86
+ };
87
+ entries.push(entry);
88
+ totalTokens += estimateTokens(entry.summary ?? "");
89
+ }
90
+ }
91
+ if (options.query) {
92
+ const scoredFiles = this.context.getFiles().map((file) => ({
93
+ file,
94
+ score: scoreFile(file, options.query)
95
+ })).filter(({ score }) => score > .2).sort((a, b) => b.score - a.score);
96
+ for (const { file, score } of scoredFiles) {
97
+ if (totalTokens >= maxTokens) break;
98
+ if (entries.some((e) => e.path === file.path)) continue;
99
+ const entry = {
100
+ type: "file",
101
+ path: file.path,
102
+ summary: `File: ${file.relativePath}`,
103
+ relevance: score
104
+ };
105
+ entries.push(entry);
106
+ totalTokens += estimateTokens(entry.summary ?? "");
107
+ }
108
+ }
109
+ const summary = this.buildSummary(entries);
110
+ return {
111
+ entries,
112
+ summary,
113
+ totalTokensEstimate: totalTokens + estimateTokens(summary)
114
+ };
115
+ }
116
+ /**
117
+ * Build a text summary of the context entries
118
+ */
119
+ buildSummary(entries) {
120
+ if (entries.length === 0) return this.context.getContextSummary();
121
+ const parts = [];
122
+ const workspaceSummary = this.context.getSummary();
123
+ parts.push(`Workspace: ${workspaceSummary.name}`);
124
+ parts.push("");
125
+ const specs = entries.filter((e) => e.type === "spec");
126
+ if (specs.length > 0) {
127
+ parts.push("### Relevant Specs");
128
+ for (const entry of specs) parts.push(`- ${entry.summary}`);
129
+ parts.push("");
130
+ }
131
+ const files = entries.filter((e) => e.type === "file");
132
+ if (files.length > 0) {
133
+ parts.push("### Relevant Files");
134
+ for (const entry of files) parts.push(`- ${entry.summary}`);
135
+ }
136
+ return parts.join("\n");
137
+ }
138
+ };
139
+ /**
140
+ * Create a context builder
141
+ */
142
+ function createContextBuilder(context) {
143
+ return new ContextBuilder(context);
144
+ }
145
+
146
+ //#endregion
147
+ export { ContextBuilder, createContextBuilder };
148
+ //# sourceMappingURL=context-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-builder.js","names":["entries: ContextEntry[]","entry: ContextEntry","parts: string[]"],"sources":["../../src/context/context-builder.ts"],"sourcesContent":["/**\n * Context builder for LLM prompts\n *\n * Builds rich context from workspace information for AI assistance.\n */\nimport type { WorkspaceContext, SpecInfo, FileInfo } from './workspace-context';\n\n/**\n * Context entry for a file or spec\n */\nexport interface ContextEntry {\n type: 'spec' | 'file' | 'reference';\n path: string;\n content?: string;\n summary?: string;\n relevance: number; // 0-1 score\n}\n\n/**\n * Built context for LLM\n */\nexport interface BuiltContext {\n entries: ContextEntry[];\n summary: string;\n totalTokensEstimate: number;\n}\n\n/**\n * Options for building context\n */\nexport interface ContextBuilderOptions {\n /** Maximum estimated tokens for context */\n maxTokens?: number;\n /** Query to use for relevance scoring */\n query?: string;\n /** Specific files to include */\n includeFiles?: string[];\n /** Specific specs to include */\n includeSpecs?: string[];\n}\n\n/**\n * Estimates token count from string (rough approximation)\n */\nfunction estimateTokens(text: string): number {\n // Rough estimate: ~4 characters per token\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Calculate relevance score for a spec\n */\nfunction scoreSpec(spec: SpecInfo, query?: string): number {\n if (!query) return 0.5;\n\n const lowerQuery = query.toLowerCase();\n let score = 0;\n\n // Name match\n if (spec.name.toLowerCase().includes(lowerQuery)) {\n score += 0.4;\n }\n\n // Description match\n if (spec.description?.toLowerCase().includes(lowerQuery)) {\n score += 0.3;\n }\n\n // Tag match\n if (spec.tags?.some((t) => t.toLowerCase().includes(lowerQuery))) {\n score += 0.2;\n }\n\n return Math.min(score, 1);\n}\n\n/**\n * Calculate relevance score for a file\n */\nfunction scoreFile(file: FileInfo, query?: string): number {\n if (!query) return 0.5;\n\n const lowerQuery = query.toLowerCase();\n let score = 0;\n\n // Path match\n if (file.path.toLowerCase().includes(lowerQuery)) {\n score += 0.5;\n }\n\n // Name match\n if (file.name.toLowerCase().includes(lowerQuery)) {\n score += 0.3;\n }\n\n // Spec file bonus\n if (file.isSpec) {\n score += 0.2;\n }\n\n return Math.min(score, 1);\n}\n\n/**\n * Context builder for creating rich LLM context\n */\nexport class ContextBuilder {\n private readonly context: WorkspaceContext;\n\n constructor(context: WorkspaceContext) {\n this.context = context;\n }\n\n /**\n * Build context for a chat message\n */\n build(options: ContextBuilderOptions = {}): BuiltContext {\n const maxTokens = options.maxTokens ?? 4000;\n const entries: ContextEntry[] = [];\n let totalTokens = 0;\n\n // Add explicitly included specs\n if (options.includeSpecs?.length) {\n for (const specName of options.includeSpecs) {\n const spec = this.context.getSpecs().find((s) => s.name === specName);\n if (spec) {\n const entry: ContextEntry = {\n type: 'spec',\n path: spec.path,\n summary: `${spec.type}: ${spec.name}${spec.description ? ` - ${spec.description}` : ''}`,\n relevance: 1,\n };\n entries.push(entry);\n totalTokens += estimateTokens(entry.summary ?? '');\n }\n }\n }\n\n // Add explicitly included files\n if (options.includeFiles?.length) {\n for (const filePath of options.includeFiles) {\n const file = this.context.getFiles().find((f) => f.path === filePath);\n if (file) {\n const entry: ContextEntry = {\n type: 'file',\n path: file.path,\n summary: `File: ${file.relativePath}`,\n relevance: 1,\n };\n entries.push(entry);\n totalTokens += estimateTokens(entry.summary ?? '');\n }\n }\n }\n\n // Add relevant specs based on query\n if (options.query) {\n const scoredSpecs = this.context\n .getSpecs()\n .map((spec) => ({ spec, score: scoreSpec(spec, options.query) }))\n .filter(({ score }) => score > 0.2)\n .sort((a, b) => b.score - a.score);\n\n for (const { spec, score } of scoredSpecs) {\n if (totalTokens >= maxTokens) break;\n if (entries.some((e) => e.path === spec.path)) continue;\n\n const entry: ContextEntry = {\n type: 'spec',\n path: spec.path,\n summary: `${spec.type}: ${spec.name}${spec.description ? ` - ${spec.description}` : ''}`,\n relevance: score,\n };\n entries.push(entry);\n totalTokens += estimateTokens(entry.summary ?? '');\n }\n }\n\n // Add relevant files based on query\n if (options.query) {\n const scoredFiles = this.context\n .getFiles()\n .map((file) => ({ file, score: scoreFile(file, options.query) }))\n .filter(({ score }) => score > 0.2)\n .sort((a, b) => b.score - a.score);\n\n for (const { file, score } of scoredFiles) {\n if (totalTokens >= maxTokens) break;\n if (entries.some((e) => e.path === file.path)) continue;\n\n const entry: ContextEntry = {\n type: 'file',\n path: file.path,\n summary: `File: ${file.relativePath}`,\n relevance: score,\n };\n entries.push(entry);\n totalTokens += estimateTokens(entry.summary ?? '');\n }\n }\n\n // Build summary\n const summary = this.buildSummary(entries);\n\n return {\n entries,\n summary,\n totalTokensEstimate: totalTokens + estimateTokens(summary),\n };\n }\n\n /**\n * Build a text summary of the context entries\n */\n private buildSummary(entries: ContextEntry[]): string {\n if (entries.length === 0) {\n return this.context.getContextSummary();\n }\n\n const parts: string[] = [];\n\n // Workspace info\n const workspaceSummary = this.context.getSummary();\n parts.push(`Workspace: ${workspaceSummary.name}`);\n parts.push('');\n\n // Relevant specs\n const specs = entries.filter((e) => e.type === 'spec');\n if (specs.length > 0) {\n parts.push('### Relevant Specs');\n for (const entry of specs) {\n parts.push(`- ${entry.summary}`);\n }\n parts.push('');\n }\n\n // Relevant files\n const files = entries.filter((e) => e.type === 'file');\n if (files.length > 0) {\n parts.push('### Relevant Files');\n for (const entry of files) {\n parts.push(`- ${entry.summary}`);\n }\n }\n\n return parts.join('\\n');\n }\n}\n\n/**\n * Create a context builder\n */\nexport function createContextBuilder(\n context: WorkspaceContext\n): ContextBuilder {\n return new ContextBuilder(context);\n}\n"],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ //#region src/context/file-operations.d.ts
2
+ /**
3
+ * File operations for workspace context
4
+ *
5
+ * Provides read/write operations for files in the workspace.
6
+ */
7
+ /**
8
+ * Result of a file read operation
9
+ */
10
+ interface FileReadResult {
11
+ success: boolean;
12
+ path: string;
13
+ content?: string;
14
+ error?: string;
15
+ }
16
+ /**
17
+ * Result of a file write operation
18
+ */
19
+ interface FileWriteResult {
20
+ success: boolean;
21
+ path: string;
22
+ error?: string;
23
+ }
24
+ /**
25
+ * File operation to perform
26
+ */
27
+ interface FileOperation {
28
+ type: 'read' | 'write' | 'create' | 'delete';
29
+ path: string;
30
+ content?: string;
31
+ }
32
+ /**
33
+ * Result of a file operation
34
+ */
35
+ interface FileOperationResult {
36
+ operation: FileOperation;
37
+ success: boolean;
38
+ content?: string;
39
+ error?: string;
40
+ }
41
+ /**
42
+ * Interface for file system operations
43
+ */
44
+ interface FileSystem {
45
+ /**
46
+ * Read a file's contents
47
+ */
48
+ readFile(path: string): Promise<string>;
49
+ /**
50
+ * Write content to a file
51
+ */
52
+ writeFile(path: string, content: string): Promise<void>;
53
+ /**
54
+ * Check if a file exists
55
+ */
56
+ exists(path: string): Promise<boolean>;
57
+ /**
58
+ * Delete a file
59
+ */
60
+ deleteFile(path: string): Promise<void>;
61
+ /**
62
+ * List files in a directory
63
+ */
64
+ listFiles(directory: string, options?: {
65
+ recursive?: boolean;
66
+ pattern?: string;
67
+ }): Promise<string[]>;
68
+ }
69
+ /**
70
+ * File operations executor
71
+ */
72
+ declare class FileOperations {
73
+ private readonly fs;
74
+ private readonly workspacePath;
75
+ private readonly allowWrites;
76
+ constructor(fs: FileSystem, workspacePath: string, allowWrites?: boolean);
77
+ /**
78
+ * Read a file
79
+ */
80
+ read(relativePath: string): Promise<FileReadResult>;
81
+ /**
82
+ * Write to a file
83
+ */
84
+ write(relativePath: string, content: string): Promise<FileWriteResult>;
85
+ /**
86
+ * Execute multiple file operations
87
+ */
88
+ execute(operations: FileOperation[]): Promise<FileOperationResult[]>;
89
+ /**
90
+ * Resolve a relative path to an absolute path
91
+ */
92
+ private resolvePath;
93
+ }
94
+ /**
95
+ * Create a file operations instance with Node.js fs
96
+ */
97
+ declare function createNodeFileOperations(workspacePath: string, allowWrites?: boolean): FileOperations;
98
+ //#endregion
99
+ export { FileOperation, FileOperationResult, FileOperations, FileReadResult, FileSystem, FileWriteResult, createNodeFileOperations };
100
+ //# sourceMappingURL=file-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-operations.d.ts","names":[],"sources":["../../src/context/file-operations.ts"],"sourcesContent":[],"mappings":";;AASA;AAUA;AASA;AASA;AAUA;;;AAcwB,UApDP,cAAA,CAoDO;EAKI,OAAA,EAAA,OAAA;EAQvB,IAAA,EAAA,MAAA;EAAO,OAAA,CAAA,EAAA,MAAA;EAMC,KAAA,CAAA,EAAA,MAAA;;;;;AA4ByC,UAzFrC,eAAA,CAyFqC;EA0B1B,OAAA,EAAA,OAAA;EAA0B,IAAA,EAAA,MAAA;EAAR,KAAA,CAAA,EAAA,MAAA;;AAyF9C;;;UAnMiB,aAAA;;;;;;;;UASA,mBAAA;aACJ;;;;;;;;UASI,UAAA;;;;0BAIS;;;;4CAKkB;;;;wBAKpB;;;;4BAKI;;;;;;;MAQvB;;;;;cAMQ,cAAA;;;;kBAEY;;;;8BAQW,QAAQ;;;;gDAkBU,QAAQ;;;;sBA0BlC,kBAAkB,QAAQ;;;;;;;;;iBAyFtC,wBAAA,gDAGb"}
@@ -1 +1,175 @@
1
- var e=class{constructor(e,t,n=!1){this.fs=e,this.workspacePath=t,this.allowWrites=n}async read(e){let t=this.resolvePath(e);try{return{success:!0,path:e,content:await this.fs.readFile(t)}}catch(t){return{success:!1,path:e,error:t instanceof Error?t.message:String(t)}}}async write(e,t){if(!this.allowWrites)return{success:!1,path:e,error:`File writes are not enabled`};let n=this.resolvePath(e);try{return await this.fs.writeFile(n,t),{success:!0,path:e}}catch(t){return{success:!1,path:e,error:t instanceof Error?t.message:String(t)}}}async execute(e){let t=[];for(let n of e){let e;switch(n.type){case`read`:{let t=await this.read(n.path);e={operation:n,success:t.success,content:t.content,error:t.error};break}case`write`:case`create`:if(!n.content)e={operation:n,success:!1,error:`Content is required for write operations`};else{let t=await this.write(n.path,n.content);e={operation:n,success:t.success,error:t.error}}break;case`delete`:if(!this.allowWrites)e={operation:n,success:!1,error:`File writes are not enabled`};else try{await this.fs.deleteFile(this.resolvePath(n.path)),e={operation:n,success:!0}}catch(t){e={operation:n,success:!1,error:t instanceof Error?t.message:String(t)}}break;default:e={operation:n,success:!1,error:`Unknown operation type: ${n.type}`}}t.push(e)}return t}resolvePath(e){let t=e.replace(/\.\./g,``).replace(/^\//,``);return`${this.workspacePath}/${t}`}};function t(t,n=!1){return new e({async readFile(e){let{readFile:t}=await import(`node:fs/promises`);return t(e,`utf-8`)},async writeFile(e,t){let{writeFile:n,mkdir:r}=await import(`node:fs/promises`),{dirname:i}=await import(`node:path`);await r(i(e),{recursive:!0}),await n(e,t,`utf-8`)},async exists(e){let{access:t}=await import(`node:fs/promises`);try{return await t(e),!0}catch{return!1}},async deleteFile(e){let{unlink:t}=await import(`node:fs/promises`);await t(e)},async listFiles(e,t){let{readdir:n}=await import(`node:fs/promises`),{join:r}=await import(`node:path`),i=[],a=await n(e,{withFileTypes:!0});for(let n of a){let a=r(e,n.name);if(n.isDirectory()&&t?.recursive){let e=await this.listFiles(a,t);i.push(...e)}else n.isFile()&&(!t?.pattern||n.name.match(new RegExp(t.pattern)))&&i.push(a)}return i}},t,n)}export{e as FileOperations,t as createNodeFileOperations};
1
+ //#region src/context/file-operations.ts
2
+ /**
3
+ * File operations executor
4
+ */
5
+ var FileOperations = class {
6
+ constructor(fs, workspacePath, allowWrites = false) {
7
+ this.fs = fs;
8
+ this.workspacePath = workspacePath;
9
+ this.allowWrites = allowWrites;
10
+ }
11
+ /**
12
+ * Read a file
13
+ */
14
+ async read(relativePath) {
15
+ const fullPath = this.resolvePath(relativePath);
16
+ try {
17
+ return {
18
+ success: true,
19
+ path: relativePath,
20
+ content: await this.fs.readFile(fullPath)
21
+ };
22
+ } catch (error) {
23
+ return {
24
+ success: false,
25
+ path: relativePath,
26
+ error: error instanceof Error ? error.message : String(error)
27
+ };
28
+ }
29
+ }
30
+ /**
31
+ * Write to a file
32
+ */
33
+ async write(relativePath, content) {
34
+ if (!this.allowWrites) return {
35
+ success: false,
36
+ path: relativePath,
37
+ error: "File writes are not enabled"
38
+ };
39
+ const fullPath = this.resolvePath(relativePath);
40
+ try {
41
+ await this.fs.writeFile(fullPath, content);
42
+ return {
43
+ success: true,
44
+ path: relativePath
45
+ };
46
+ } catch (error) {
47
+ return {
48
+ success: false,
49
+ path: relativePath,
50
+ error: error instanceof Error ? error.message : String(error)
51
+ };
52
+ }
53
+ }
54
+ /**
55
+ * Execute multiple file operations
56
+ */
57
+ async execute(operations) {
58
+ const results = [];
59
+ for (const operation of operations) {
60
+ let result;
61
+ switch (operation.type) {
62
+ case "read": {
63
+ const readResult = await this.read(operation.path);
64
+ result = {
65
+ operation,
66
+ success: readResult.success,
67
+ content: readResult.content,
68
+ error: readResult.error
69
+ };
70
+ break;
71
+ }
72
+ case "write":
73
+ case "create":
74
+ if (!operation.content) result = {
75
+ operation,
76
+ success: false,
77
+ error: "Content is required for write operations"
78
+ };
79
+ else {
80
+ const writeResult = await this.write(operation.path, operation.content);
81
+ result = {
82
+ operation,
83
+ success: writeResult.success,
84
+ error: writeResult.error
85
+ };
86
+ }
87
+ break;
88
+ case "delete":
89
+ if (!this.allowWrites) result = {
90
+ operation,
91
+ success: false,
92
+ error: "File writes are not enabled"
93
+ };
94
+ else try {
95
+ await this.fs.deleteFile(this.resolvePath(operation.path));
96
+ result = {
97
+ operation,
98
+ success: true
99
+ };
100
+ } catch (error) {
101
+ result = {
102
+ operation,
103
+ success: false,
104
+ error: error instanceof Error ? error.message : String(error)
105
+ };
106
+ }
107
+ break;
108
+ default: result = {
109
+ operation,
110
+ success: false,
111
+ error: `Unknown operation type: ${operation.type}`
112
+ };
113
+ }
114
+ results.push(result);
115
+ }
116
+ return results;
117
+ }
118
+ /**
119
+ * Resolve a relative path to an absolute path
120
+ */
121
+ resolvePath(relativePath) {
122
+ const normalized = relativePath.replace(/\.\./g, "").replace(/^\//, "");
123
+ return `${this.workspacePath}/${normalized}`;
124
+ }
125
+ };
126
+ /**
127
+ * Create a file operations instance with Node.js fs
128
+ */
129
+ function createNodeFileOperations(workspacePath, allowWrites = false) {
130
+ return new FileOperations({
131
+ async readFile(path) {
132
+ const { readFile } = await import("node:fs/promises");
133
+ return readFile(path, "utf-8");
134
+ },
135
+ async writeFile(path, content) {
136
+ const { writeFile, mkdir } = await import("node:fs/promises");
137
+ const { dirname } = await import("node:path");
138
+ await mkdir(dirname(path), { recursive: true });
139
+ await writeFile(path, content, "utf-8");
140
+ },
141
+ async exists(path) {
142
+ const { access } = await import("node:fs/promises");
143
+ try {
144
+ await access(path);
145
+ return true;
146
+ } catch {
147
+ return false;
148
+ }
149
+ },
150
+ async deleteFile(path) {
151
+ const { unlink } = await import("node:fs/promises");
152
+ await unlink(path);
153
+ },
154
+ async listFiles(directory, options) {
155
+ const { readdir } = await import("node:fs/promises");
156
+ const { join } = await import("node:path");
157
+ const files = [];
158
+ const entries = await readdir(directory, { withFileTypes: true });
159
+ for (const entry of entries) {
160
+ const fullPath = join(directory, entry.name);
161
+ if (entry.isDirectory() && options?.recursive) {
162
+ const subFiles = await this.listFiles(fullPath, options);
163
+ files.push(...subFiles);
164
+ } else if (entry.isFile()) {
165
+ if (!options?.pattern || entry.name.match(new RegExp(options.pattern))) files.push(fullPath);
166
+ }
167
+ }
168
+ return files;
169
+ }
170
+ }, workspacePath, allowWrites);
171
+ }
172
+
173
+ //#endregion
174
+ export { FileOperations, createNodeFileOperations };
175
+ //# sourceMappingURL=file-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-operations.js","names":["fs: FileSystem","workspacePath: string","results: FileOperationResult[]","result: FileOperationResult","files: string[]"],"sources":["../../src/context/file-operations.ts"],"sourcesContent":["/**\n * File operations for workspace context\n *\n * Provides read/write operations for files in the workspace.\n */\n\n/**\n * Result of a file read operation\n */\nexport interface FileReadResult {\n success: boolean;\n path: string;\n content?: string;\n error?: string;\n}\n\n/**\n * Result of a file write operation\n */\nexport interface FileWriteResult {\n success: boolean;\n path: string;\n error?: string;\n}\n\n/**\n * File operation to perform\n */\nexport interface FileOperation {\n type: 'read' | 'write' | 'create' | 'delete';\n path: string;\n content?: string;\n}\n\n/**\n * Result of a file operation\n */\nexport interface FileOperationResult {\n operation: FileOperation;\n success: boolean;\n content?: string;\n error?: string;\n}\n\n/**\n * Interface for file system operations\n */\nexport interface FileSystem {\n /**\n * Read a file's contents\n */\n readFile(path: string): Promise<string>;\n\n /**\n * Write content to a file\n */\n writeFile(path: string, content: string): Promise<void>;\n\n /**\n * Check if a file exists\n */\n exists(path: string): Promise<boolean>;\n\n /**\n * Delete a file\n */\n deleteFile(path: string): Promise<void>;\n\n /**\n * List files in a directory\n */\n listFiles(\n directory: string,\n options?: { recursive?: boolean; pattern?: string }\n ): Promise<string[]>;\n}\n\n/**\n * File operations executor\n */\nexport class FileOperations {\n constructor(\n private readonly fs: FileSystem,\n private readonly workspacePath: string,\n private readonly allowWrites = false\n ) {}\n\n /**\n * Read a file\n */\n async read(relativePath: string): Promise<FileReadResult> {\n const fullPath = this.resolvePath(relativePath);\n\n try {\n const content = await this.fs.readFile(fullPath);\n return { success: true, path: relativePath, content };\n } catch (error) {\n return {\n success: false,\n path: relativePath,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Write to a file\n */\n async write(relativePath: string, content: string): Promise<FileWriteResult> {\n if (!this.allowWrites) {\n return {\n success: false,\n path: relativePath,\n error: 'File writes are not enabled',\n };\n }\n\n const fullPath = this.resolvePath(relativePath);\n\n try {\n await this.fs.writeFile(fullPath, content);\n return { success: true, path: relativePath };\n } catch (error) {\n return {\n success: false,\n path: relativePath,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Execute multiple file operations\n */\n async execute(operations: FileOperation[]): Promise<FileOperationResult[]> {\n const results: FileOperationResult[] = [];\n\n for (const operation of operations) {\n let result: FileOperationResult;\n\n switch (operation.type) {\n case 'read': {\n const readResult = await this.read(operation.path);\n result = {\n operation,\n success: readResult.success,\n content: readResult.content,\n error: readResult.error,\n };\n break;\n }\n\n case 'write':\n case 'create': {\n if (!operation.content) {\n result = {\n operation,\n success: false,\n error: 'Content is required for write operations',\n };\n } else {\n const writeResult = await this.write(\n operation.path,\n operation.content\n );\n result = {\n operation,\n success: writeResult.success,\n error: writeResult.error,\n };\n }\n break;\n }\n\n case 'delete': {\n if (!this.allowWrites) {\n result = {\n operation,\n success: false,\n error: 'File writes are not enabled',\n };\n } else {\n try {\n await this.fs.deleteFile(this.resolvePath(operation.path));\n result = { operation, success: true };\n } catch (error) {\n result = {\n operation,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n break;\n }\n\n default:\n result = {\n operation,\n success: false,\n error: `Unknown operation type: ${(operation as FileOperation).type}`,\n };\n }\n\n results.push(result);\n }\n\n return results;\n }\n\n /**\n * Resolve a relative path to an absolute path\n */\n private resolvePath(relativePath: string): string {\n // Prevent path traversal\n const normalized = relativePath.replace(/\\.\\./g, '').replace(/^\\//, '');\n return `${this.workspacePath}/${normalized}`;\n }\n}\n\n/**\n * Create a file operations instance with Node.js fs\n */\nexport function createNodeFileOperations(\n workspacePath: string,\n allowWrites = false\n): FileOperations {\n // Dynamic import to avoid issues in browser environments\n const fs: FileSystem = {\n async readFile(path: string): Promise<string> {\n const { readFile } = await import('node:fs/promises');\n return readFile(path, 'utf-8');\n },\n async writeFile(path: string, content: string): Promise<void> {\n const { writeFile, mkdir } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, 'utf-8');\n },\n async exists(path: string): Promise<boolean> {\n const { access } = await import('node:fs/promises');\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n },\n async deleteFile(path: string): Promise<void> {\n const { unlink } = await import('node:fs/promises');\n await unlink(path);\n },\n async listFiles(\n directory: string,\n options?: { recursive?: boolean; pattern?: string }\n ): Promise<string[]> {\n const { readdir } = await import('node:fs/promises');\n const { join } = await import('node:path');\n\n const files: string[] = [];\n const entries = await readdir(directory, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(directory, entry.name);\n if (entry.isDirectory() && options?.recursive) {\n const subFiles = await this.listFiles(fullPath, options);\n files.push(...subFiles);\n } else if (entry.isFile()) {\n if (\n !options?.pattern ||\n entry.name.match(new RegExp(options.pattern))\n ) {\n files.push(fullPath);\n }\n }\n }\n\n return files;\n },\n };\n\n return new FileOperations(fs, workspacePath, allowWrites);\n}\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { FileInfo, SpecInfo, WorkspaceContext, WorkspaceContextConfig, WorkspaceSummary, createWorkspaceContext } from "./workspace-context.js";
2
+ import { BuiltContext, ContextBuilder, ContextBuilderOptions, ContextEntry, createContextBuilder } from "./context-builder.js";
3
+ import { FileOperation, FileOperationResult, FileOperations, FileReadResult, FileSystem, FileWriteResult, createNodeFileOperations } from "./file-operations.js";
4
+ export { BuiltContext, ContextBuilder, ContextBuilderOptions, ContextEntry, FileInfo, FileOperation, FileOperationResult, FileOperations, FileReadResult, FileSystem, FileWriteResult, SpecInfo, WorkspaceContext, WorkspaceContextConfig, WorkspaceSummary, createContextBuilder, createNodeFileOperations, createWorkspaceContext };
@@ -1 +1,5 @@
1
- import{WorkspaceContext as e,createWorkspaceContext as t}from"./workspace-context.js";import{ContextBuilder as n,createContextBuilder as r}from"./context-builder.js";import{FileOperations as i,createNodeFileOperations as a}from"./file-operations.js";export{n as ContextBuilder,i as FileOperations,e as WorkspaceContext,r as createContextBuilder,a as createNodeFileOperations,t as createWorkspaceContext};
1
+ import { WorkspaceContext, createWorkspaceContext } from "./workspace-context.js";
2
+ import { ContextBuilder, createContextBuilder } from "./context-builder.js";
3
+ import { FileOperations, createNodeFileOperations } from "./file-operations.js";
4
+
5
+ export { ContextBuilder, FileOperations, WorkspaceContext, createContextBuilder, createNodeFileOperations, createWorkspaceContext };
@@ -0,0 +1,117 @@
1
+ //#region src/context/workspace-context.d.ts
2
+ /**
3
+ * Workspace context management
4
+ *
5
+ * Provides access to specs, files, and codebase information
6
+ * for context-aware AI chat assistance.
7
+ */
8
+ /**
9
+ * Spec information for context
10
+ */
11
+ interface SpecInfo {
12
+ name: string;
13
+ version: number;
14
+ type: 'command' | 'query' | 'event' | 'presentation';
15
+ path: string;
16
+ description?: string;
17
+ tags?: string[];
18
+ }
19
+ /**
20
+ * File information for context
21
+ */
22
+ interface FileInfo {
23
+ path: string;
24
+ relativePath: string;
25
+ name: string;
26
+ extension: string;
27
+ size: number;
28
+ isSpec: boolean;
29
+ }
30
+ /**
31
+ * Workspace summary for context
32
+ */
33
+ interface WorkspaceSummary {
34
+ name: string;
35
+ path: string;
36
+ specs: {
37
+ total: number;
38
+ commands: number;
39
+ queries: number;
40
+ events: number;
41
+ presentations: number;
42
+ };
43
+ files: {
44
+ total: number;
45
+ typescript: number;
46
+ specFiles: number;
47
+ };
48
+ }
49
+ /**
50
+ * Configuration for workspace context
51
+ */
52
+ interface WorkspaceContextConfig {
53
+ /** Root path of the workspace */
54
+ workspacePath: string;
55
+ /** File patterns to include */
56
+ includePatterns?: string[];
57
+ /** File patterns to exclude */
58
+ excludePatterns?: string[];
59
+ /** Maximum file size to read (bytes) */
60
+ maxFileSize?: number;
61
+ /** Whether to enable file writes */
62
+ allowWrites?: boolean;
63
+ }
64
+ /**
65
+ * Workspace context for AI chat
66
+ */
67
+ declare class WorkspaceContext {
68
+ readonly workspacePath: string;
69
+ readonly allowWrites: boolean;
70
+ private specs;
71
+ private files;
72
+ private initialized;
73
+ constructor(config: WorkspaceContextConfig);
74
+ /**
75
+ * Initialize the workspace context by scanning files
76
+ */
77
+ initialize(): Promise<void>;
78
+ /**
79
+ * Get all discovered specs
80
+ */
81
+ getSpecs(): SpecInfo[];
82
+ /**
83
+ * Get all discovered files
84
+ */
85
+ getFiles(): FileInfo[];
86
+ /**
87
+ * Add specs to the context
88
+ */
89
+ addSpecs(specs: SpecInfo[]): void;
90
+ /**
91
+ * Add files to the context
92
+ */
93
+ addFiles(files: FileInfo[]): void;
94
+ /**
95
+ * Get a summary of the workspace for context
96
+ */
97
+ getSummary(): WorkspaceSummary;
98
+ /**
99
+ * Get a context summary for LLM prompts
100
+ */
101
+ getContextSummary(): string;
102
+ /**
103
+ * Find specs matching a query
104
+ */
105
+ findSpecs(query: string): SpecInfo[];
106
+ /**
107
+ * Find files matching a query
108
+ */
109
+ findFiles(query: string): FileInfo[];
110
+ }
111
+ /**
112
+ * Create a workspace context from a path
113
+ */
114
+ declare function createWorkspaceContext(path: string, options?: Partial<WorkspaceContextConfig>): Promise<WorkspaceContext>;
115
+ //#endregion
116
+ export { FileInfo, SpecInfo, WorkspaceContext, WorkspaceContextConfig, WorkspaceSummary, createWorkspaceContext };
117
+ //# sourceMappingURL=workspace-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-context.d.ts","names":[],"sources":["../../src/context/workspace-context.ts"],"sourcesContent":[],"mappings":";;AAUA;AAYA;AAYA;AAoBA;AAgBA;;;;AAkCc,UA9FG,QAAA,CA8FH;EAOI,IAAA,EAAA,MAAA;EAOA,OAAA,EAAA,MAAA;EAOF,IAAA,EAAA,SAAA,GAAA,OAAA,GAAA,OAAA,GAAA,cAAA;EA8DY,IAAA,EAAA,MAAA;EAaA,WAAA,CAAA,EAAA,MAAA;EAAQ,IAAA,CAAA,EAAA,MAAA,EAAA;AAapC;;;;AAGG,UAlMc,QAAA,CAkMd;EAAO,IAAA,EAAA,MAAA;;;;;;;;;;UAtLO,gBAAA;;;;;;;;;;;;;;;;;;;UAoBA,sBAAA;;;;;;;;;;;;;;;cAgBJ,gBAAA;;;;;;sBAQS;;;;gBAQA;;;;cAWR;;;;cAOA;;;;kBAOI;;;;kBAOA;;;;gBAOF;;;;;;;;4BA8DY;;;;4BAaA;;;;;iBAaN,sBAAA,yBAEV,QAAQ,0BACjB,QAAQ"}