@deimoscloud/coreai 0.1.9 → 0.1.10

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 (196) hide show
  1. package/dist/cli/index.js +1 -1
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -1
  6. package/.prettierrc +0 -9
  7. package/AGENT_SPEC.md +0 -347
  8. package/ARCHITECTURE.md +0 -547
  9. package/DRAFT_PRD.md +0 -1440
  10. package/IMPLEMENTATION_PLAN.md +0 -256
  11. package/PRODUCT.md +0 -473
  12. package/WORKFLOWS.md +0 -295
  13. package/commands/core/check-inbox.md +0 -34
  14. package/commands/core/delegate.md +0 -30
  15. package/commands/core/git-commit.md +0 -144
  16. package/commands/core/pr-create.md +0 -193
  17. package/commands/core/review.md +0 -56
  18. package/commands/core/sprint-status.md +0 -65
  19. package/commands/optional/docs-update.md +0 -200
  20. package/commands/optional/jira-create.md +0 -200
  21. package/commands/optional/jira-transition.md +0 -184
  22. package/commands/optional/worktree-cleanup.md +0 -167
  23. package/commands/optional/worktree-setup.md +0 -110
  24. package/eslint.config.js +0 -29
  25. package/jest.config.js +0 -22
  26. package/knowledge-library/README.md +0 -118
  27. package/knowledge-library/android-engineer/context/current.txt +0 -42
  28. package/knowledge-library/android-engineer/control/decisions.txt +0 -9
  29. package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
  30. package/knowledge-library/android-engineer/control/objectives.txt +0 -26
  31. package/knowledge-library/android-engineer/history/.gitkeep +0 -0
  32. package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
  33. package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
  34. package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
  35. package/knowledge-library/architecture.txt +0 -61
  36. package/knowledge-library/backend-engineer/context/current.txt +0 -42
  37. package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
  38. package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
  39. package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
  40. package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
  41. package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
  42. package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
  43. package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
  44. package/knowledge-library/context.txt +0 -52
  45. package/knowledge-library/devops-engineer/context/current.txt +0 -42
  46. package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
  47. package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
  48. package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
  49. package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
  50. package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
  51. package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
  52. package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
  53. package/knowledge-library/engineering-manager/context/current.txt +0 -40
  54. package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
  55. package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
  56. package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
  57. package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
  58. package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
  59. package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
  60. package/knowledge-library/prd.txt +0 -81
  61. package/knowledge-library/product-manager/context/current.txt +0 -42
  62. package/knowledge-library/product-manager/control/decisions.txt +0 -9
  63. package/knowledge-library/product-manager/control/dependencies.txt +0 -19
  64. package/knowledge-library/product-manager/control/objectives.txt +0 -26
  65. package/knowledge-library/product-manager/history/.gitkeep +0 -0
  66. package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
  67. package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
  68. package/knowledge-library/product-manager/tech/.gitkeep +0 -0
  69. package/knowledge-library/qa-engineer/context/current.txt +0 -42
  70. package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
  71. package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
  72. package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
  73. package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
  74. package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
  75. package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
  76. package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
  77. package/knowledge-library/security-engineer/context/current.txt +0 -42
  78. package/knowledge-library/security-engineer/control/decisions.txt +0 -9
  79. package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
  80. package/knowledge-library/security-engineer/control/objectives.txt +0 -26
  81. package/knowledge-library/security-engineer/history/.gitkeep +0 -0
  82. package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
  83. package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
  84. package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
  85. package/knowledge-library/solutions-architect/context/current.txt +0 -42
  86. package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
  87. package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
  88. package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
  89. package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
  90. package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
  91. package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
  92. package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
  93. package/knowledge-library/wearos-engineer/context/current.txt +0 -42
  94. package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
  95. package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
  96. package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
  97. package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
  98. package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
  99. package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
  100. package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
  101. package/scripts/add-agent.sh +0 -323
  102. package/scripts/install.sh +0 -354
  103. package/src/adapters/factory.test.ts +0 -386
  104. package/src/adapters/factory.ts +0 -305
  105. package/src/adapters/index.ts +0 -113
  106. package/src/adapters/interfaces.ts +0 -268
  107. package/src/adapters/mcp/client.test.ts +0 -130
  108. package/src/adapters/mcp/client.ts +0 -451
  109. package/src/adapters/mcp/discovery.test.ts +0 -315
  110. package/src/adapters/mcp/discovery.ts +0 -340
  111. package/src/adapters/mcp/index.ts +0 -66
  112. package/src/adapters/mcp/mapper.test.ts +0 -218
  113. package/src/adapters/mcp/mapper.ts +0 -536
  114. package/src/adapters/mcp/registry.test.ts +0 -433
  115. package/src/adapters/mcp/registry.ts +0 -550
  116. package/src/adapters/mcp/types.ts +0 -258
  117. package/src/adapters/native/filesystem.test.ts +0 -350
  118. package/src/adapters/native/filesystem.ts +0 -393
  119. package/src/adapters/native/github.test.ts +0 -173
  120. package/src/adapters/native/github.ts +0 -627
  121. package/src/adapters/native/index.ts +0 -22
  122. package/src/adapters/native/selector.test.ts +0 -224
  123. package/src/adapters/native/selector.ts +0 -150
  124. package/src/adapters/types.ts +0 -270
  125. package/src/agents/compiler.test.ts +0 -410
  126. package/src/agents/compiler.ts +0 -424
  127. package/src/agents/index.ts +0 -37
  128. package/src/agents/loader.test.ts +0 -319
  129. package/src/agents/loader.ts +0 -143
  130. package/src/agents/resolver.test.ts +0 -282
  131. package/src/agents/resolver.ts +0 -262
  132. package/src/agents/types.ts +0 -97
  133. package/src/cache/index.ts +0 -38
  134. package/src/cache/interfaces.ts +0 -283
  135. package/src/cache/manager.test.ts +0 -266
  136. package/src/cache/manager.ts +0 -388
  137. package/src/cache/provider.test.ts +0 -485
  138. package/src/cache/provider.ts +0 -745
  139. package/src/cache/types.test.ts +0 -192
  140. package/src/cache/types.ts +0 -313
  141. package/src/cli/commands/build.test.ts +0 -248
  142. package/src/cli/commands/build.ts +0 -284
  143. package/src/cli/commands/cache.test.ts +0 -221
  144. package/src/cli/commands/cache.ts +0 -229
  145. package/src/cli/commands/index.ts +0 -63
  146. package/src/cli/commands/init.test.ts +0 -173
  147. package/src/cli/commands/init.ts +0 -296
  148. package/src/cli/commands/skills.test.ts +0 -272
  149. package/src/cli/commands/skills.ts +0 -348
  150. package/src/cli/commands/status.test.ts +0 -392
  151. package/src/cli/commands/status.ts +0 -332
  152. package/src/cli/commands/sync.test.ts +0 -213
  153. package/src/cli/commands/sync.ts +0 -251
  154. package/src/cli/commands/validate.test.ts +0 -216
  155. package/src/cli/commands/validate.ts +0 -340
  156. package/src/cli/index.test.ts +0 -190
  157. package/src/cli/index.ts +0 -493
  158. package/src/commands/context.test.ts +0 -163
  159. package/src/commands/context.ts +0 -111
  160. package/src/commands/index.ts +0 -56
  161. package/src/commands/loader.test.ts +0 -273
  162. package/src/commands/loader.ts +0 -355
  163. package/src/commands/registry.test.ts +0 -384
  164. package/src/commands/registry.ts +0 -248
  165. package/src/commands/runner.test.ts +0 -297
  166. package/src/commands/runner.ts +0 -222
  167. package/src/commands/types.ts +0 -361
  168. package/src/config/index.ts +0 -19
  169. package/src/config/loader.test.ts +0 -262
  170. package/src/config/loader.ts +0 -188
  171. package/src/config/types.ts +0 -154
  172. package/src/context/index.ts +0 -14
  173. package/src/context/loader.test.ts +0 -334
  174. package/src/context/loader.ts +0 -357
  175. package/src/index.test.ts +0 -13
  176. package/src/index.ts +0 -268
  177. package/src/knowledge-library/index.ts +0 -44
  178. package/src/knowledge-library/manager.test.ts +0 -536
  179. package/src/knowledge-library/manager.ts +0 -804
  180. package/src/knowledge-library/types.ts +0 -432
  181. package/src/skills/generator.test.ts +0 -602
  182. package/src/skills/generator.ts +0 -491
  183. package/src/skills/index.ts +0 -27
  184. package/src/skills/templates.ts +0 -520
  185. package/src/skills/types.ts +0 -251
  186. package/templates/completion-report.md +0 -72
  187. package/templates/feedback.md +0 -56
  188. package/templates/project-files/CLAUDE.md.template +0 -109
  189. package/templates/project-files/coreai.json.example +0 -47
  190. package/templates/project-files/mcp.json.template +0 -20
  191. package/templates/review-complete.md +0 -64
  192. package/templates/review-request.md +0 -67
  193. package/templates/task-assignment.md +0 -51
  194. package/tsconfig.build.json +0 -4
  195. package/tsconfig.json +0 -26
  196. package/tsup.config.ts +0 -23
@@ -1,258 +0,0 @@
1
- /**
2
- * MCP Integration Types
3
- *
4
- * Types for MCP server configuration and integration.
5
- */
6
-
7
- /**
8
- * Transport type for MCP servers
9
- */
10
- export type McpTransportType = 'stdio' | 'http' | 'sse';
11
-
12
- /**
13
- * Configuration for a stdio-based MCP server
14
- */
15
- export interface StdioServerConfig {
16
- transport: 'stdio';
17
- command: string;
18
- args?: string[];
19
- env?: Record<string, string>;
20
- cwd?: string;
21
- }
22
-
23
- /**
24
- * Configuration for an HTTP-based MCP server
25
- */
26
- export interface HttpServerConfig {
27
- transport: 'http' | 'sse';
28
- url: string;
29
- headers?: Record<string, string>;
30
- }
31
-
32
- /**
33
- * Union type for all MCP server configurations
34
- */
35
- export type McpServerConfig = StdioServerConfig | HttpServerConfig;
36
-
37
- /**
38
- * MCP server definition from config
39
- */
40
- export interface McpServerDefinition {
41
- /**
42
- * Unique name for this server
43
- */
44
- name: string;
45
-
46
- /**
47
- * Server configuration
48
- */
49
- config: McpServerConfig;
50
-
51
- /**
52
- * Whether this server is enabled
53
- */
54
- enabled?: boolean;
55
-
56
- /**
57
- * Description of what this server provides
58
- */
59
- description?: string;
60
- }
61
-
62
- /**
63
- * MCP config file structure (e.g., mcp.json)
64
- */
65
- export interface McpConfigFile {
66
- /**
67
- * MCP servers to connect to
68
- */
69
- mcpServers?: Record<string, McpServerConfig>;
70
- }
71
-
72
- /**
73
- * Information about a connected MCP server
74
- */
75
- export interface McpServerInfo {
76
- /**
77
- * Server name
78
- */
79
- name: string;
80
-
81
- /**
82
- * Server version (if available)
83
- */
84
- version?: string;
85
-
86
- /**
87
- * Protocol version
88
- */
89
- protocolVersion?: string;
90
-
91
- /**
92
- * Server capabilities
93
- */
94
- capabilities?: McpCapabilities;
95
-
96
- /**
97
- * Server instructions (if any)
98
- */
99
- instructions?: string;
100
-
101
- /**
102
- * Whether the server is connected
103
- */
104
- connected: boolean;
105
- }
106
-
107
- /**
108
- * MCP server capabilities
109
- */
110
- export interface McpCapabilities {
111
- tools?: boolean;
112
- resources?: boolean;
113
- prompts?: boolean;
114
- logging?: boolean;
115
- }
116
-
117
- /**
118
- * MCP tool definition
119
- */
120
- export interface McpTool {
121
- /**
122
- * Tool name
123
- */
124
- name: string;
125
-
126
- /**
127
- * Tool description
128
- */
129
- description?: string;
130
-
131
- /**
132
- * Input schema for the tool
133
- */
134
- inputSchema: {
135
- type: 'object';
136
- properties?: Record<string, unknown>;
137
- required?: string[];
138
- };
139
-
140
- /**
141
- * Tool annotations
142
- */
143
- annotations?: {
144
- title?: string;
145
- readOnlyHint?: boolean;
146
- destructiveHint?: boolean;
147
- idempotentHint?: boolean;
148
- };
149
- }
150
-
151
- /**
152
- * MCP resource definition
153
- */
154
- export interface McpResource {
155
- /**
156
- * Resource URI
157
- */
158
- uri: string;
159
-
160
- /**
161
- * Resource name
162
- */
163
- name: string;
164
-
165
- /**
166
- * Resource description
167
- */
168
- description?: string;
169
-
170
- /**
171
- * MIME type
172
- */
173
- mimeType?: string;
174
- }
175
-
176
- /**
177
- * Result of calling an MCP tool
178
- */
179
- export interface McpToolResult {
180
- /**
181
- * Tool output content
182
- */
183
- content: McpContent[];
184
-
185
- /**
186
- * Whether the tool call resulted in an error
187
- */
188
- isError?: boolean;
189
-
190
- /**
191
- * Structured content (if tool has outputSchema)
192
- */
193
- structuredContent?: Record<string, unknown>;
194
- }
195
-
196
- /**
197
- * Content returned by MCP tools and resources
198
- */
199
- export type McpContent = McpTextContent | McpImageContent | McpResourceContent;
200
-
201
- /**
202
- * Text content
203
- */
204
- export interface McpTextContent {
205
- type: 'text';
206
- text: string;
207
- }
208
-
209
- /**
210
- * Image content
211
- */
212
- export interface McpImageContent {
213
- type: 'image';
214
- data: string;
215
- mimeType: string;
216
- }
217
-
218
- /**
219
- * Embedded resource content
220
- */
221
- export interface McpResourceContent {
222
- type: 'resource';
223
- resource: {
224
- uri: string;
225
- text?: string;
226
- blob?: string;
227
- mimeType?: string;
228
- };
229
- }
230
-
231
- /**
232
- * Error from MCP operations
233
- */
234
- export class McpError extends Error {
235
- constructor(
236
- message: string,
237
- public readonly code: McpErrorCode,
238
- public readonly server?: string,
239
- cause?: Error
240
- ) {
241
- super(message, { cause });
242
- this.name = 'McpError';
243
- }
244
- }
245
-
246
- /**
247
- * MCP error codes
248
- */
249
- export type McpErrorCode =
250
- | 'connection_failed'
251
- | 'connection_closed'
252
- | 'server_not_found'
253
- | 'tool_not_found'
254
- | 'resource_not_found'
255
- | 'invalid_config'
256
- | 'transport_error'
257
- | 'protocol_error'
258
- | 'timeout';
@@ -1,350 +0,0 @@
1
- import { mkdtempSync, rmSync, writeFileSync, mkdirSync, readFileSync } from 'fs';
2
- import { join } from 'path';
3
- import { tmpdir } from 'os';
4
- import { FilesystemAdapter, createFilesystemAdapter } from './filesystem.js';
5
- import { AdapterError } from '../types.js';
6
-
7
- describe('FilesystemAdapter', () => {
8
- let tempDir: string;
9
- let adapter: FilesystemAdapter;
10
-
11
- beforeEach(() => {
12
- tempDir = mkdtempSync(join(tmpdir(), 'filesystem-adapter-test-'));
13
- adapter = createFilesystemAdapter({ basePath: tempDir });
14
- });
15
-
16
- afterEach(() => {
17
- rmSync(tempDir, { recursive: true, force: true });
18
- });
19
-
20
- describe('constructor', () => {
21
- it('should create adapter with base path', () => {
22
- const info = adapter.getInfo();
23
- expect(info.type).toBe('state');
24
- expect(info.provider).toBe('filesystem');
25
- expect(info.implementation).toBe('native');
26
- expect(info.connected).toBe(false);
27
- });
28
- });
29
-
30
- describe('connect', () => {
31
- it('should connect when base path exists', async () => {
32
- await adapter.connect();
33
- expect(adapter.isConnected()).toBe(true);
34
- });
35
-
36
- it('should create base path if it does not exist', async () => {
37
- const newPath = join(tempDir, 'new-dir');
38
- const newAdapter = createFilesystemAdapter({ basePath: newPath });
39
-
40
- await newAdapter.connect();
41
- expect(newAdapter.isConnected()).toBe(true);
42
- });
43
-
44
- it('should throw if base path is a file', async () => {
45
- const filePath = join(tempDir, 'file.txt');
46
- writeFileSync(filePath, 'content');
47
-
48
- const fileAdapter = createFilesystemAdapter({ basePath: filePath });
49
- await expect(fileAdapter.connect()).rejects.toThrow(AdapterError);
50
- });
51
- });
52
-
53
- describe('disconnect', () => {
54
- it('should disconnect', async () => {
55
- await adapter.connect();
56
- await adapter.disconnect();
57
- expect(adapter.isConnected()).toBe(false);
58
- });
59
- });
60
-
61
- describe('read', () => {
62
- beforeEach(async () => {
63
- await adapter.connect();
64
- });
65
-
66
- it('should read file content', async () => {
67
- writeFileSync(join(tempDir, 'test.txt'), 'hello world');
68
-
69
- const content = await adapter.read('test.txt');
70
- expect(content).toBe('hello world');
71
- });
72
-
73
- it('should read file from subdirectory', async () => {
74
- mkdirSync(join(tempDir, 'subdir'));
75
- writeFileSync(join(tempDir, 'subdir', 'file.txt'), 'nested content');
76
-
77
- const content = await adapter.read('subdir/file.txt');
78
- expect(content).toBe('nested content');
79
- });
80
-
81
- it('should throw for non-existent file', async () => {
82
- await expect(adapter.read('nonexistent.txt')).rejects.toThrow(AdapterError);
83
- });
84
-
85
- it('should throw if not connected', async () => {
86
- await adapter.disconnect();
87
- await expect(adapter.read('test.txt')).rejects.toThrow(AdapterError);
88
- });
89
- });
90
-
91
- describe('write', () => {
92
- beforeEach(async () => {
93
- await adapter.connect();
94
- });
95
-
96
- it('should write file content', async () => {
97
- await adapter.write('output.txt', 'new content');
98
-
99
- const content = readFileSync(join(tempDir, 'output.txt'), 'utf-8');
100
- expect(content).toBe('new content');
101
- });
102
-
103
- it('should overwrite existing file', async () => {
104
- writeFileSync(join(tempDir, 'existing.txt'), 'old content');
105
-
106
- await adapter.write('existing.txt', 'new content');
107
-
108
- const content = readFileSync(join(tempDir, 'existing.txt'), 'utf-8');
109
- expect(content).toBe('new content');
110
- });
111
-
112
- it('should create parent directories with recursive option', async () => {
113
- await adapter.write('deep/nested/file.txt', 'content', { recursive: true });
114
-
115
- const content = readFileSync(join(tempDir, 'deep/nested/file.txt'), 'utf-8');
116
- expect(content).toBe('content');
117
- });
118
-
119
- it('should throw for non-existent parent without recursive', async () => {
120
- await expect(adapter.write('nonexistent/file.txt', 'content')).rejects.toThrow(AdapterError);
121
- });
122
- });
123
-
124
- describe('exists', () => {
125
- beforeEach(async () => {
126
- await adapter.connect();
127
- });
128
-
129
- it('should return true for existing file', async () => {
130
- writeFileSync(join(tempDir, 'exists.txt'), 'content');
131
-
132
- const exists = await adapter.exists('exists.txt');
133
- expect(exists).toBe(true);
134
- });
135
-
136
- it('should return true for existing directory', async () => {
137
- mkdirSync(join(tempDir, 'subdir'));
138
-
139
- const exists = await adapter.exists('subdir');
140
- expect(exists).toBe(true);
141
- });
142
-
143
- it('should return false for non-existent path', async () => {
144
- const exists = await adapter.exists('nonexistent');
145
- expect(exists).toBe(false);
146
- });
147
- });
148
-
149
- describe('list', () => {
150
- beforeEach(async () => {
151
- await adapter.connect();
152
- });
153
-
154
- it('should list directory contents', async () => {
155
- writeFileSync(join(tempDir, 'file1.txt'), 'content1');
156
- writeFileSync(join(tempDir, 'file2.txt'), 'content2');
157
- mkdirSync(join(tempDir, 'subdir'));
158
-
159
- const entries = await adapter.list('.');
160
- expect(entries.length).toBe(3);
161
-
162
- const names = entries.map((e) => e.name).sort();
163
- expect(names).toEqual(['file1.txt', 'file2.txt', 'subdir']);
164
-
165
- const file1 = entries.find((e) => e.name === 'file1.txt');
166
- expect(file1?.type).toBe('file');
167
- expect(file1?.size).toBeDefined();
168
-
169
- const subdir = entries.find((e) => e.name === 'subdir');
170
- expect(subdir?.type).toBe('directory');
171
- });
172
-
173
- it('should throw for non-existent directory', async () => {
174
- await expect(adapter.list('nonexistent')).rejects.toThrow(AdapterError);
175
- });
176
-
177
- it('should throw if path is a file', async () => {
178
- writeFileSync(join(tempDir, 'file.txt'), 'content');
179
- await expect(adapter.list('file.txt')).rejects.toThrow(AdapterError);
180
- });
181
- });
182
-
183
- describe('delete', () => {
184
- beforeEach(async () => {
185
- await adapter.connect();
186
- });
187
-
188
- it('should delete a file', async () => {
189
- writeFileSync(join(tempDir, 'to-delete.txt'), 'content');
190
-
191
- await adapter.delete('to-delete.txt');
192
-
193
- const exists = await adapter.exists('to-delete.txt');
194
- expect(exists).toBe(false);
195
- });
196
-
197
- it('should delete empty directory', async () => {
198
- mkdirSync(join(tempDir, 'empty-dir'));
199
-
200
- await adapter.delete('empty-dir');
201
-
202
- const exists = await adapter.exists('empty-dir');
203
- expect(exists).toBe(false);
204
- });
205
-
206
- it('should delete non-empty directory with recursive', async () => {
207
- mkdirSync(join(tempDir, 'non-empty'));
208
- writeFileSync(join(tempDir, 'non-empty', 'file.txt'), 'content');
209
-
210
- await adapter.delete('non-empty', { recursive: true });
211
-
212
- const exists = await adapter.exists('non-empty');
213
- expect(exists).toBe(false);
214
- });
215
-
216
- it('should throw for non-empty directory without recursive', async () => {
217
- mkdirSync(join(tempDir, 'non-empty'));
218
- writeFileSync(join(tempDir, 'non-empty', 'file.txt'), 'content');
219
-
220
- await expect(adapter.delete('non-empty')).rejects.toThrow(AdapterError);
221
- });
222
-
223
- it('should not throw for non-existent path', async () => {
224
- await expect(adapter.delete('nonexistent')).resolves.toBeUndefined();
225
- });
226
- });
227
-
228
- describe('mkdir', () => {
229
- beforeEach(async () => {
230
- await adapter.connect();
231
- });
232
-
233
- it('should create directory', async () => {
234
- await adapter.mkdir('new-dir');
235
-
236
- const exists = await adapter.exists('new-dir');
237
- expect(exists).toBe(true);
238
- });
239
-
240
- it('should create nested directories with recursive', async () => {
241
- await adapter.mkdir('a/b/c', { recursive: true });
242
-
243
- const exists = await adapter.exists('a/b/c');
244
- expect(exists).toBe(true);
245
- });
246
-
247
- it('should not throw if directory already exists', async () => {
248
- mkdirSync(join(tempDir, 'existing-dir'));
249
-
250
- await expect(adapter.mkdir('existing-dir')).resolves.toBeUndefined();
251
- });
252
-
253
- it('should throw for nested path without recursive', async () => {
254
- await expect(adapter.mkdir('a/b/c')).rejects.toThrow(AdapterError);
255
- });
256
- });
257
-
258
- describe('move', () => {
259
- beforeEach(async () => {
260
- await adapter.connect();
261
- });
262
-
263
- it('should move/rename a file', async () => {
264
- writeFileSync(join(tempDir, 'source.txt'), 'content');
265
-
266
- await adapter.move('source.txt', 'dest.txt');
267
-
268
- expect(await adapter.exists('source.txt')).toBe(false);
269
- expect(await adapter.exists('dest.txt')).toBe(true);
270
-
271
- const content = await adapter.read('dest.txt');
272
- expect(content).toBe('content');
273
- });
274
-
275
- it('should move/rename a directory', async () => {
276
- mkdirSync(join(tempDir, 'source-dir'));
277
- writeFileSync(join(tempDir, 'source-dir', 'file.txt'), 'content');
278
-
279
- await adapter.move('source-dir', 'dest-dir');
280
-
281
- expect(await adapter.exists('source-dir')).toBe(false);
282
- expect(await adapter.exists('dest-dir')).toBe(true);
283
- expect(await adapter.exists('dest-dir/file.txt')).toBe(true);
284
- });
285
-
286
- it('should throw for non-existent source', async () => {
287
- await expect(adapter.move('nonexistent', 'dest')).rejects.toThrow(AdapterError);
288
- });
289
- });
290
-
291
- describe('copy', () => {
292
- beforeEach(async () => {
293
- await adapter.connect();
294
- });
295
-
296
- it('should copy a file', async () => {
297
- writeFileSync(join(tempDir, 'source.txt'), 'content');
298
-
299
- await adapter.copy('source.txt', 'copy.txt');
300
-
301
- expect(await adapter.exists('source.txt')).toBe(true);
302
- expect(await adapter.exists('copy.txt')).toBe(true);
303
-
304
- const content = await adapter.read('copy.txt');
305
- expect(content).toBe('content');
306
- });
307
-
308
- it('should copy a directory recursively', async () => {
309
- mkdirSync(join(tempDir, 'source-dir'));
310
- mkdirSync(join(tempDir, 'source-dir', 'nested'));
311
- writeFileSync(join(tempDir, 'source-dir', 'file.txt'), 'content');
312
- writeFileSync(join(tempDir, 'source-dir', 'nested', 'nested.txt'), 'nested');
313
-
314
- await adapter.copy('source-dir', 'copy-dir');
315
-
316
- expect(await adapter.exists('source-dir')).toBe(true);
317
- expect(await adapter.exists('copy-dir')).toBe(true);
318
- expect(await adapter.exists('copy-dir/file.txt')).toBe(true);
319
- expect(await adapter.exists('copy-dir/nested/nested.txt')).toBe(true);
320
-
321
- const content = await adapter.read('copy-dir/nested/nested.txt');
322
- expect(content).toBe('nested');
323
- });
324
-
325
- it('should throw for non-existent source', async () => {
326
- await expect(adapter.copy('nonexistent', 'dest')).rejects.toThrow(AdapterError);
327
- });
328
- });
329
-
330
- describe('path traversal protection', () => {
331
- beforeEach(async () => {
332
- await adapter.connect();
333
- });
334
-
335
- it('should prevent path traversal with ..', async () => {
336
- await expect(adapter.read('../outside.txt')).rejects.toThrow(AdapterError);
337
- });
338
-
339
- it('should prevent path traversal with absolute paths', async () => {
340
- await expect(adapter.read('/etc/passwd')).rejects.toThrow(AdapterError);
341
- });
342
- });
343
- });
344
-
345
- describe('createFilesystemAdapter', () => {
346
- it('should create a filesystem adapter', () => {
347
- const adapter = createFilesystemAdapter({ basePath: '/tmp' });
348
- expect(adapter).toBeInstanceOf(FilesystemAdapter);
349
- });
350
- });