@polka-codes/cli 0.0.4 → 0.1.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 (40) hide show
  1. package/dist/config.d.ts +37 -0
  2. package/dist/config.js +44 -0
  3. package/dist/config.js.map +1 -0
  4. package/dist/config.test.d.ts +1 -0
  5. package/dist/config.test.js +87 -0
  6. package/dist/config.test.js.map +1 -0
  7. package/dist/handlers.d.ts +14 -0
  8. package/dist/handlers.js +239 -0
  9. package/dist/handlers.js.map +1 -0
  10. package/dist/index.d.ts +0 -1
  11. package/dist/index.js +23 -10
  12. package/dist/index.js.map +1 -1
  13. package/dist/listFiles.d.ts +11 -0
  14. package/dist/listFiles.js +100 -0
  15. package/dist/listFiles.js.map +1 -0
  16. package/dist/listFiles.test.d.ts +1 -0
  17. package/dist/listFiles.test.js +49 -0
  18. package/dist/listFiles.test.js.map +1 -0
  19. package/dist/replaceInFile.d.ts +1 -0
  20. package/dist/replaceInFile.js +85 -0
  21. package/dist/replaceInFile.js.map +1 -0
  22. package/dist/replaceInFile.test.d.ts +1 -0
  23. package/dist/replaceInFile.test.js +90 -0
  24. package/dist/replaceInFile.test.js.map +1 -0
  25. package/dist/runTask.d.ts +9 -0
  26. package/dist/runTask.js +107 -0
  27. package/dist/runTask.js.map +1 -0
  28. package/dist/utils/listFiles.d.ts +11 -0
  29. package/dist/utils/listFiles.js +100 -0
  30. package/dist/utils/listFiles.js.map +1 -0
  31. package/dist/utils/listFiles.test.d.ts +1 -0
  32. package/dist/utils/listFiles.test.js +49 -0
  33. package/dist/utils/listFiles.test.js.map +1 -0
  34. package/dist/utils/replaceInFile.d.ts +1 -0
  35. package/dist/utils/replaceInFile.js +85 -0
  36. package/dist/utils/replaceInFile.js.map +1 -0
  37. package/dist/utils/replaceInFile.test.d.ts +1 -0
  38. package/dist/utils/replaceInFile.test.js +90 -0
  39. package/dist/utils/replaceInFile.test.js.map +1 -0
  40. package/package.json +9 -3
@@ -0,0 +1,37 @@
1
+ import { z } from 'zod';
2
+ export declare const configSchema: z.ZodObject<{
3
+ provider: z.ZodOptional<z.ZodString>;
4
+ apiKey: z.ZodOptional<z.ZodString>;
5
+ model: z.ZodOptional<z.ZodString>;
6
+ commands: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
7
+ command: z.ZodString;
8
+ description: z.ZodString;
9
+ }, "strip", z.ZodTypeAny, {
10
+ command: string;
11
+ description: string;
12
+ }, {
13
+ command: string;
14
+ description: string;
15
+ }>]>>>;
16
+ rules: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodArray<z.ZodString, "many">>, z.ZodString]>>;
17
+ }, "strict", z.ZodTypeAny, {
18
+ provider?: string | undefined;
19
+ apiKey?: string | undefined;
20
+ model?: string | undefined;
21
+ commands?: Record<string, string | {
22
+ command: string;
23
+ description: string;
24
+ }> | undefined;
25
+ rules?: string | string[] | undefined;
26
+ }, {
27
+ provider?: string | undefined;
28
+ apiKey?: string | undefined;
29
+ model?: string | undefined;
30
+ commands?: Record<string, string | {
31
+ command: string;
32
+ description: string;
33
+ }> | undefined;
34
+ rules?: string | string[] | undefined;
35
+ }>;
36
+ export type Config = z.infer<typeof configSchema>;
37
+ export declare function loadConfig(path?: string, cwd?: string): Config | undefined;
package/dist/config.js ADDED
@@ -0,0 +1,44 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { parse } from 'yaml';
4
+ import { ZodError, z } from 'zod';
5
+ import { createServiceLogger } from '@polka-codes/core';
6
+ const logger = createServiceLogger('cli/config');
7
+ export const configSchema = z
8
+ .object({
9
+ provider: z.string().optional(),
10
+ apiKey: z.string().optional(),
11
+ model: z.string().optional(),
12
+ commands: z.record(z.string(), z.string().or(z.object({ command: z.string(), description: z.string() }))).optional(),
13
+ rules: z.array(z.string()).optional().or(z.string()).optional(),
14
+ })
15
+ .strict();
16
+ export function loadConfig(path, cwd = process.cwd()) {
17
+ if (path) {
18
+ try {
19
+ return readConfig(path);
20
+ }
21
+ catch (error) {
22
+ logger.error(`Error loading config file: ${path}\n${error}`);
23
+ process.exit(1);
24
+ }
25
+ }
26
+ const configPaths = [join(cwd, '.polkacodes.yml'), join(cwd, '.polkacodes.yaml')];
27
+ for (const path of configPaths) {
28
+ try {
29
+ return readConfig(path);
30
+ }
31
+ catch (error) {
32
+ if (error instanceof ZodError) {
33
+ logger.error(`Error in config file: ${path}\n${error}`);
34
+ process.exit(1);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ const readConfig = (path) => {
40
+ const file = readFileSync(path, 'utf8');
41
+ const config = parse(file);
42
+ return configSchema.parse(config);
43
+ };
44
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,MAAM,MAAM,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAA;AAEhD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpH,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAChE,CAAC;KACD,MAAM,EAAE,CAAA;AAIX,MAAM,UAAU,UAAU,CAAC,IAAa,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACnE,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC;YACH,OAAO,UAAU,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,8BAA8B,IAAI,KAAK,KAAK,EAAE,CAAC,CAAA;YAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAA;IAEjF,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,OAAO,UAAU,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,KAAK,KAAK,EAAE,CAAC,CAAA;gBACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE;IAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;IAC1B,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AACnC,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,87 @@
1
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test } from 'bun:test';
2
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { loadConfig } from './config';
6
+ describe('config', () => {
7
+ let testDir;
8
+ let testSubDir;
9
+ beforeAll(() => {
10
+ testDir = mkdtempSync(join(tmpdir(), 'polkacodes-test-'));
11
+ });
12
+ beforeEach(() => {
13
+ testSubDir = mkdtempSync(join(testDir, 'test-'));
14
+ });
15
+ afterEach(() => {
16
+ rmSync(testSubDir, { recursive: true, force: true });
17
+ });
18
+ afterAll(() => {
19
+ rmSync(testDir, { recursive: true, force: true });
20
+ });
21
+ test('loads config from specified path', () => {
22
+ const configPath = join(testSubDir, 'test-config.yml');
23
+ writeFileSync(configPath, `
24
+ provider: anthropic
25
+ apiKey: test-key
26
+ model: claude-3-opus
27
+ `);
28
+ const config = loadConfig(configPath, testSubDir);
29
+ expect(config).toEqual({
30
+ provider: 'anthropic',
31
+ apiKey: 'test-key',
32
+ model: 'claude-3-opus',
33
+ });
34
+ });
35
+ test('loads config from default paths', () => {
36
+ const configPath = join(testSubDir, '.polkacodes.yml');
37
+ writeFileSync(configPath, `
38
+ provider: deepseek
39
+ apiKey: test-key-2
40
+ model: deepseek-chat
41
+ `);
42
+ const config = loadConfig(undefined, testSubDir);
43
+ expect(config).toEqual({
44
+ provider: 'deepseek',
45
+ apiKey: 'test-key-2',
46
+ model: 'deepseek-chat',
47
+ });
48
+ // Clean up
49
+ writeFileSync(configPath, '');
50
+ });
51
+ test('validates config schema', () => {
52
+ const configPath = join(testSubDir, 'invalid-config.yml');
53
+ writeFileSync(configPath, `
54
+ invalidKey: value
55
+ `);
56
+ expect(() => loadConfig(configPath, testSubDir)).toThrow();
57
+ });
58
+ test('handles commands configuration', () => {
59
+ const configPath = join(testSubDir, 'commands-config.yml');
60
+ writeFileSync(configPath, `
61
+ commands:
62
+ test: echo "test"
63
+ complex:
64
+ command: echo "complex"
65
+ description: A complex command
66
+ `);
67
+ const config = loadConfig(configPath, testSubDir);
68
+ expect(config?.commands).toEqual({
69
+ test: 'echo "test"',
70
+ complex: {
71
+ command: 'echo "complex"',
72
+ description: 'A complex command',
73
+ },
74
+ });
75
+ });
76
+ test('handles rules configuration', () => {
77
+ const configPath = join(testSubDir, 'rules-config.yml');
78
+ writeFileSync(configPath, `
79
+ rules:
80
+ - rule1
81
+ - rule2
82
+ `);
83
+ const config = loadConfig(configPath, testSubDir);
84
+ expect(config?.rules).toEqual(['rule1', 'rule2']);
85
+ });
86
+ });
87
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type ChildProcessWithoutNullStreams } from 'node:child_process';
2
+ import { type ToolHandler } from '@polka-codes/core';
3
+ export type ToolHandlerOptions = {
4
+ executeCommand?: {
5
+ shouldExecute?: (command: string) => Promise<boolean>;
6
+ shouldApprove?: (command: string) => Promise<boolean>;
7
+ commandStarted?: (command: string, child: ChildProcessWithoutNullStreams) => void;
8
+ };
9
+ files?: {
10
+ isPathAllowed?: (path: string) => Promise<boolean>;
11
+ cwd?: string;
12
+ };
13
+ };
14
+ export declare const getToolHandler: (options: ToolHandlerOptions) => ToolHandler;
@@ -0,0 +1,239 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readFile, writeFile } from 'node:fs/promises';
3
+ import { ToolResponseType, allTools, createServiceLogger } from '@polka-codes/core';
4
+ import { listFiles } from './utils/listFiles';
5
+ import { replaceInFile } from './utils/replaceInFile';
6
+ const logger = createServiceLogger('cli/handlers');
7
+ const handleError = async (name, fn) => {
8
+ try {
9
+ return await fn();
10
+ }
11
+ catch (error) {
12
+ logger.warn(error, `Error executing tool: ${name}`);
13
+ return {
14
+ type: ToolResponseType.Error,
15
+ message: `Error executing tool: ${name}
16
+ Error: ${error}`,
17
+ canRetry: false,
18
+ };
19
+ }
20
+ };
21
+ const getString = (args, name, defaultValue) => {
22
+ const ret = args[name] ?? defaultValue;
23
+ if (!ret) {
24
+ throw new Error(`Missing required argument: ${name}`);
25
+ }
26
+ return ret;
27
+ };
28
+ const getBoolean = (args, name, defaultValue) => {
29
+ const ret = args[name];
30
+ if (!ret) {
31
+ if (defaultValue === undefined) {
32
+ throw new Error(`Missing required argument: ${name}`);
33
+ }
34
+ return defaultValue;
35
+ }
36
+ switch (ret.toLowerCase()) {
37
+ case 'true':
38
+ return true;
39
+ case 'false':
40
+ return false;
41
+ default:
42
+ throw new Error(`Invalid argument value: ${name}`);
43
+ }
44
+ };
45
+ const getInt = (args, name, defaultValue) => {
46
+ const ret = args[name];
47
+ if (!ret) {
48
+ if (defaultValue === undefined) {
49
+ throw new Error(`Missing required argument: ${name}`);
50
+ }
51
+ return defaultValue;
52
+ }
53
+ const parsed = Number.parseInt(ret);
54
+ if (Number.isNaN(parsed)) {
55
+ throw new Error(`Invalid argument value: ${name}`);
56
+ }
57
+ return parsed;
58
+ };
59
+ const handlers = {
60
+ executeCommand: async (options, args) => {
61
+ const command = getString(args, 'command');
62
+ const shouldExecute = (await options.executeCommand?.shouldExecute?.(command)) ?? true;
63
+ if (!shouldExecute) {
64
+ return {
65
+ type: ToolResponseType.Invalid,
66
+ message: `<command>${command}</command><command_rejected>Rejected by policy</command_rejected>`,
67
+ };
68
+ }
69
+ const requiresApproval = getBoolean(args, 'requires_approval', false);
70
+ if (requiresApproval) {
71
+ const shouldApprove = await options.executeCommand?.shouldApprove?.(command);
72
+ if (!shouldApprove) {
73
+ return {
74
+ type: ToolResponseType.Invalid,
75
+ message: `<command>${command}</command><command_rejected>Rejected by policy</command_rejected>`,
76
+ };
77
+ }
78
+ }
79
+ // TODO: add timeout
80
+ return new Promise((resolve, reject) => {
81
+ // spawn a shell to execute the command
82
+ logger.trace(`Executing command: ${command}`);
83
+ const child = spawn(command, [], {
84
+ shell: true,
85
+ stdio: 'pipe',
86
+ });
87
+ options.executeCommand?.commandStarted?.(command, child);
88
+ let stdoutText = '';
89
+ let stderrText = '';
90
+ child.stdout.on('data', (data) => {
91
+ stdoutText += data.toString();
92
+ });
93
+ child.stderr.on('data', (data) => {
94
+ stderrText += data.toString();
95
+ });
96
+ child.on('close', (code) => {
97
+ const message = `<command>${command}</command>
98
+ <command_exit_code>${code}</command_exit_code>
99
+ <command_stdout>
100
+ ${stdoutText}
101
+ </command_stdout>
102
+ <command_stderr>
103
+ ${stderrText}
104
+ </command_stderr>
105
+ `;
106
+ if (code === 0) {
107
+ resolve({
108
+ type: ToolResponseType.Reply,
109
+ message,
110
+ });
111
+ }
112
+ else {
113
+ resolve({
114
+ type: ToolResponseType.Error,
115
+ message,
116
+ });
117
+ }
118
+ });
119
+ child.on('error', (err) => {
120
+ reject(err);
121
+ });
122
+ });
123
+ },
124
+ readFile: async (options, args) => {
125
+ const path = getString(args, 'path');
126
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
127
+ if (!isPathAllowed) {
128
+ return {
129
+ type: ToolResponseType.Invalid,
130
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
131
+ };
132
+ }
133
+ const fileContent = await readFile(path, 'utf8');
134
+ return {
135
+ type: ToolResponseType.Reply,
136
+ message: `<read_file_path>${path}</read_file_path>
137
+ <read_file_file_content>${fileContent}</read_file_file_content>`,
138
+ };
139
+ },
140
+ writeToFile: async (options, args) => {
141
+ const path = getString(args, 'path');
142
+ const content = getString(args, 'content');
143
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
144
+ if (!isPathAllowed) {
145
+ return {
146
+ type: ToolResponseType.Invalid,
147
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
148
+ };
149
+ }
150
+ await writeFile(path, content, 'utf8');
151
+ return {
152
+ type: ToolResponseType.Reply,
153
+ message: `<write_file_path>${path}</write_file_path><status>Success</status>`,
154
+ };
155
+ },
156
+ replaceInFile: async (options, args) => {
157
+ const path = getString(args, 'path');
158
+ const diff = getString(args, 'diff');
159
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
160
+ if (!isPathAllowed) {
161
+ return {
162
+ type: ToolResponseType.Invalid,
163
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
164
+ };
165
+ }
166
+ const fileContent = await readFile(path, 'utf8');
167
+ const result = await replaceInFile(fileContent, diff);
168
+ await writeFile(path, result, 'utf8');
169
+ return {
170
+ type: ToolResponseType.Reply,
171
+ message: `<replace_in_file_path>${path}</replace_in_file_path>`,
172
+ };
173
+ },
174
+ searchFiles: async (options, args) => {
175
+ // TODO
176
+ return {
177
+ type: ToolResponseType.Exit,
178
+ message: 'Files searched successfully',
179
+ };
180
+ },
181
+ listFiles: async (options, args) => {
182
+ const path = getString(args, 'path');
183
+ const depth = getInt(args, 'depth', 5);
184
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
185
+ if (!isPathAllowed) {
186
+ return {
187
+ type: ToolResponseType.Invalid,
188
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
189
+ };
190
+ }
191
+ const recursive = depth > 0;
192
+ const [files, limitReached] = await listFiles(path, recursive, depth, options.files?.cwd ?? process.cwd());
193
+ return {
194
+ type: ToolResponseType.Reply,
195
+ message: `<list_files_path>${path}</list_files_path>
196
+ <list_files_depth>${depth}</list_files_depth>
197
+ <list_files_files>
198
+ ${files.join('\n')}
199
+ </list_files_files>
200
+ <list_files_truncated>${limitReached}</list_files_truncated>`,
201
+ };
202
+ },
203
+ listCodeDefinitionNames: async (options, args) => {
204
+ // TODO
205
+ return {
206
+ type: ToolResponseType.Exit,
207
+ message: 'Code definition names listed successfully',
208
+ };
209
+ },
210
+ askFollowupQuestion: async (options, args) => {
211
+ // TODO
212
+ return {
213
+ type: ToolResponseType.Exit,
214
+ message: 'Followup question asked successfully',
215
+ };
216
+ },
217
+ attemptCompletion: async (options, args) => {
218
+ return {
219
+ type: ToolResponseType.Exit,
220
+ message: '<completed>true</completed>',
221
+ };
222
+ },
223
+ };
224
+ const processedHandlers = Object.fromEntries(Object.entries(handlers).map(([toolName, handler]) => {
225
+ return [
226
+ allTools[toolName].name,
227
+ async (options, args) => handleError(toolName, async () => handler(options, args)),
228
+ ];
229
+ }));
230
+ export const getToolHandler = (options) => {
231
+ return async (toolName, args) => {
232
+ const handler = processedHandlers[toolName];
233
+ if (!handler) {
234
+ throw new Error(`Unknown tool: ${toolName}`);
235
+ }
236
+ return handler(options, args);
237
+ };
238
+ };
239
+ //# sourceMappingURL=handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
1
  export {};
package/dist/index.js CHANGED
@@ -1,17 +1,30 @@
1
- #!/usr/bin/env node
2
- import { PolkaCore, VERSION } from '@polka-codes/core';
3
1
  import { Command } from 'commander';
2
+ import { createServiceLogger } from '@polka-codes/core';
3
+ import { version } from '../package.json';
4
+ import { loadConfig } from './config';
5
+ import { runTask } from './runTask';
6
+ const logger = createServiceLogger('cli');
4
7
  const program = new Command();
5
- program.name('polka').description('Polka Codes CLI').version(VERSION);
8
+ program.name('polka').description('Polka Codes CLI').version(version);
9
+ // Main command for executing tasks
6
10
  program
7
- .command('init')
8
- .description('Initialize a new Polka project')
9
- .action(() => {
10
- const core = new PolkaCore({
11
- name: 'polka-project',
12
- version: '0.0.1',
11
+ .argument('[task]', 'The task to execute')
12
+ .option('-c --config <path>', 'Path to config file')
13
+ .option('--api-provider <provider>', 'API provider')
14
+ .option('--model-id <model>', 'Model ID')
15
+ .option('--api-key <key>', 'API key')
16
+ .action(async (taskArg, options) => {
17
+ const config = loadConfig(options.config ?? options.c) ?? {};
18
+ const provider = options.apiProvider || process.env.POLKA_API_PROVIDER || config.provider || 'anthropic';
19
+ const model = options.modelId || process.env.POLKA_MODEL_ID || config.model;
20
+ const apiKey = options.apiKey || process.env.POLKA_API_KEY || config.apiKey;
21
+ await runTask({
22
+ task: taskArg,
23
+ provider,
24
+ model,
25
+ apiKey,
26
+ config,
13
27
  });
14
- console.log('Initialized project with config:', core.getConfig());
15
28
  });
16
29
  program.parse();
17
30
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;AAErE,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC;QACzB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAA;IACF,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;AACnE,CAAC,CAAC,CAAA;AAEJ,OAAO,CAAC,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;AAEzC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;AAErE,mCAAmC;AACnC,OAAO;KACJ,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;KACzC,MAAM,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;KACnD,MAAM,CAAC,2BAA2B,EAAE,cAAc,CAAC;KACnD,MAAM,CAAC,oBAAoB,EAAE,UAAU,CAAC;KACxC,MAAM,CAAC,iBAAiB,EAAE,SAAS,CAAC;KACpC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACjC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAE5D,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAC,QAAQ,IAAI,WAAW,CAAA;IAExG,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,MAAM,CAAC,KAAK,CAAA;IAE3E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM,CAAC,MAAM,CAAA;IAE3E,MAAM,OAAO,CAAC;QACZ,IAAI,EAAE,OAAO;QACb,QAAQ;QACR,KAAK;QACL,MAAM;QACN,MAAM;KACP,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEJ,OAAO,CAAC,KAAK,EAAE,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Lists files under `dirPath` in BFS order, respecting:
3
+ * - A default set of ignores
4
+ * - A root .gitignore under `cwd`
5
+ * - Any .gitignore files in child directories (merged as we go)
6
+ *
7
+ * Returns `[files, limitReached]`:
8
+ * - `files` is the array of file paths (relative to `cwd`)
9
+ * - `limitReached` is `true` if `maxCount` was hit, otherwise `false`
10
+ */
11
+ export declare function listFiles(dirPath: string, recursive: boolean, maxCount: number, cwd: string): Promise<[string[], boolean]>;
@@ -0,0 +1,100 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { join, relative, resolve } from 'node:path';
3
+ import ignore from 'ignore';
4
+ /** Default patterns commonly ignored in projects of various languages. */
5
+ const DEFAULT_IGNORES = [
6
+ '__pycache__',
7
+ '.DS_Store',
8
+ '.env',
9
+ '.git',
10
+ '.idea',
11
+ '.svn',
12
+ '.temp',
13
+ '.vscode',
14
+ 'coverage',
15
+ 'dist',
16
+ 'node_modules',
17
+ 'out',
18
+ 'Thumbs.db',
19
+ ];
20
+ /**
21
+ * Reads a `.gitignore` file in `dirPath` (if it exists) and appends its lines
22
+ * to the `basePatterns`. Returns a new array without mutating the original.
23
+ */
24
+ async function extendPatterns(basePatterns, dirPath) {
25
+ try {
26
+ const gitignorePath = join(dirPath, '.gitignore');
27
+ const content = await fs.readFile(gitignorePath, 'utf8');
28
+ const lines = content.split(/\r?\n/).filter(Boolean);
29
+ return [...basePatterns, ...lines];
30
+ }
31
+ catch {
32
+ // No .gitignore or unreadable
33
+ return basePatterns;
34
+ }
35
+ }
36
+ /** Creates an `ignore` instance from the given patterns. */
37
+ function createIgnore(patterns) {
38
+ return ignore().add(patterns);
39
+ }
40
+ /**
41
+ * Lists files under `dirPath` in BFS order, respecting:
42
+ * - A default set of ignores
43
+ * - A root .gitignore under `cwd`
44
+ * - Any .gitignore files in child directories (merged as we go)
45
+ *
46
+ * Returns `[files, limitReached]`:
47
+ * - `files` is the array of file paths (relative to `cwd`)
48
+ * - `limitReached` is `true` if `maxCount` was hit, otherwise `false`
49
+ */
50
+ export async function listFiles(dirPath, recursive, maxCount, cwd) {
51
+ // Merge default ignores with root .gitignore (if found)
52
+ let rootPatterns = [...DEFAULT_IGNORES];
53
+ try {
54
+ const rootGitignore = await fs.readFile(join(cwd, '.gitignore'), 'utf8');
55
+ const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
56
+ rootPatterns = [...rootPatterns, ...lines];
57
+ }
58
+ catch {
59
+ // No .gitignore at root or unreadable; ignore silently
60
+ }
61
+ // Final results (relative to `cwd`) and indicator if we reached the limit
62
+ const results = [];
63
+ // BFS queue
64
+ // Each entry holds the directory path and the patterns inherited from its parent
65
+ const queue = [{ path: resolve(dirPath), patterns: rootPatterns }];
66
+ // Perform BFS until queue is empty or maxCount is reached
67
+ while (queue.length > 0) {
68
+ // biome-ignore lint/style/noNonNullAssertion: checked above
69
+ const { path: currentPath, patterns: parentPatterns } = queue.shift();
70
+ // Merge parent's patterns with local .gitignore
71
+ const mergedPatterns = await extendPatterns(parentPatterns, currentPath);
72
+ const folderIg = createIgnore(mergedPatterns);
73
+ const entries = await fs.readdir(currentPath, { withFileTypes: true });
74
+ for (const entry of entries) {
75
+ const fullPath = join(currentPath, entry.name);
76
+ // Convert full path to something relative to `cwd`
77
+ const relPath = relative(cwd, fullPath).replace(/\\/g, '/');
78
+ if (folderIg.ignores(relPath)) {
79
+ continue; // Skip ignored entries
80
+ }
81
+ if (entry.isDirectory()) {
82
+ if (recursive) {
83
+ queue.push({ path: fullPath, patterns: mergedPatterns });
84
+ }
85
+ }
86
+ else {
87
+ results.push(relPath);
88
+ if (results.length >= maxCount) {
89
+ results.sort();
90
+ // Stop searching as soon as we reach maxCount
91
+ return [results, true];
92
+ }
93
+ }
94
+ }
95
+ }
96
+ results.sort();
97
+ // If we exhaust the BFS queue, we did not reach maxCount
98
+ return [results, false];
99
+ }
100
+ //# sourceMappingURL=listFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listFiles.js","sourceRoot":"","sources":["../src/listFiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};