@polka-codes/cli 0.0.4 → 0.1.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.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # Polka Codes CLI
2
+
3
+ Command Line Interface for Polka Codes framework.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @polka-codes/cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Commands
14
+
15
+ ```bash
16
+ # Run interactive CLI
17
+ polka
18
+
19
+ # Run specific task
20
+ polka --task your-task
21
+
22
+ # Show help
23
+ polka --help
24
+ ```
25
+
26
+ ### Configuration
27
+
28
+ Create a `.polkacodes.yml` file in your project root:
29
+
30
+ ```yaml
31
+ tasks:
32
+ your-task:
33
+ description: Task description
34
+ steps:
35
+ - name: Step 1
36
+ action: some-action
37
+ ```
38
+
39
+ ### Available Commands
40
+
41
+ - `run`: Execute a specific task
42
+ - `list`: List available tasks
43
+ - `config`: Show current configuration
44
+ - `help`: Show help information
45
+
46
+ ## Development
47
+
48
+ ### Building
49
+
50
+ ```bash
51
+ cd packages/cli
52
+ bun run build
53
+ ```
54
+
55
+ ### Testing
56
+
57
+ ```bash
58
+ bun test
59
+ ```
60
+
61
+ ---
62
+
63
+ *This README was generated by polka.codes*
@@ -0,0 +1,38 @@
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;
38
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,CAAC,EAAE,MAAM,KAAK,CAAA;AAMjC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQd,CAAA;AAEX,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AAEjD,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAsBzF"}
package/dist/config.js ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configSchema = void 0;
4
+ exports.loadConfig = loadConfig;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const yaml_1 = require("yaml");
8
+ const zod_1 = require("zod");
9
+ const core_1 = require("@polka-codes/core");
10
+ const logger = (0, core_1.createServiceLogger)('cli/config');
11
+ exports.configSchema = zod_1.z
12
+ .object({
13
+ provider: zod_1.z.string().optional(),
14
+ apiKey: zod_1.z.string().optional(),
15
+ model: zod_1.z.string().optional(),
16
+ commands: zod_1.z.record(zod_1.z.string(), zod_1.z.string().or(zod_1.z.object({ command: zod_1.z.string(), description: zod_1.z.string() }))).optional(),
17
+ rules: zod_1.z.array(zod_1.z.string()).optional().or(zod_1.z.string()).optional(),
18
+ })
19
+ .strict();
20
+ function loadConfig(path, cwd = process.cwd()) {
21
+ if (path) {
22
+ try {
23
+ return readConfig(path);
24
+ }
25
+ catch (error) {
26
+ logger.error(`Error loading config file: ${path}\n${error}`);
27
+ process.exit(1);
28
+ }
29
+ }
30
+ const configPaths = [(0, node_path_1.join)(cwd, '.polkacodes.yml'), (0, node_path_1.join)(cwd, '.polkacodes.yaml')];
31
+ for (const path of configPaths) {
32
+ try {
33
+ return readConfig(path);
34
+ }
35
+ catch (error) {
36
+ if (error instanceof zod_1.ZodError) {
37
+ logger.error(`Error in config file: ${path}\n${error}`);
38
+ process.exit(1);
39
+ }
40
+ }
41
+ }
42
+ }
43
+ const readConfig = (path) => {
44
+ const file = (0, node_fs_1.readFileSync)(path, 'utf8');
45
+ const config = (0, yaml_1.parse)(file);
46
+ return exports.configSchema.parse(config);
47
+ };
48
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAqBA,gCAsBC;AA3CD,qCAAsC;AACtC,yCAAgC;AAChC,+BAA4B;AAC5B,6BAAiC;AAEjC,4CAAuD;AAEvD,MAAM,MAAM,GAAG,IAAA,0BAAmB,EAAC,YAAY,CAAC,CAAA;AAEnC,QAAA,YAAY,GAAG,OAAC;KAC1B,MAAM,CAAC;IACN,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,OAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpH,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAChE,CAAC;KACD,MAAM,EAAE,CAAA;AAIX,SAAgB,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,IAAA,gBAAI,EAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAA,gBAAI,EAAC,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,cAAQ,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,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACvC,MAAM,MAAM,GAAG,IAAA,YAAK,EAAC,IAAI,CAAC,CAAA;IAC1B,OAAO,oBAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AACnC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const node_fs_1 = require("node:fs");
5
+ const node_os_1 = require("node:os");
6
+ const node_path_1 = require("node:path");
7
+ const config_1 = require("./config");
8
+ (0, bun_test_1.describe)('config', () => {
9
+ let testDir;
10
+ let testSubDir;
11
+ (0, bun_test_1.beforeAll)(() => {
12
+ testDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'polkacodes-test-'));
13
+ });
14
+ (0, bun_test_1.beforeEach)(() => {
15
+ testSubDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)(testDir, 'test-'));
16
+ });
17
+ (0, bun_test_1.afterEach)(() => {
18
+ (0, node_fs_1.rmSync)(testSubDir, { recursive: true, force: true });
19
+ });
20
+ (0, bun_test_1.afterAll)(() => {
21
+ (0, node_fs_1.rmSync)(testDir, { recursive: true, force: true });
22
+ });
23
+ (0, bun_test_1.test)('loads config from specified path', () => {
24
+ const configPath = (0, node_path_1.join)(testSubDir, 'test-config.yml');
25
+ (0, node_fs_1.writeFileSync)(configPath, `
26
+ provider: anthropic
27
+ apiKey: test-key
28
+ model: claude-3-opus
29
+ `);
30
+ const config = (0, config_1.loadConfig)(configPath, testSubDir);
31
+ (0, bun_test_1.expect)(config).toEqual({
32
+ provider: 'anthropic',
33
+ apiKey: 'test-key',
34
+ model: 'claude-3-opus',
35
+ });
36
+ });
37
+ (0, bun_test_1.test)('loads config from default paths', () => {
38
+ const configPath = (0, node_path_1.join)(testSubDir, '.polkacodes.yml');
39
+ (0, node_fs_1.writeFileSync)(configPath, `
40
+ provider: deepseek
41
+ apiKey: test-key-2
42
+ model: deepseek-chat
43
+ `);
44
+ const config = (0, config_1.loadConfig)(undefined, testSubDir);
45
+ (0, bun_test_1.expect)(config).toEqual({
46
+ provider: 'deepseek',
47
+ apiKey: 'test-key-2',
48
+ model: 'deepseek-chat',
49
+ });
50
+ // Clean up
51
+ (0, node_fs_1.writeFileSync)(configPath, '');
52
+ });
53
+ (0, bun_test_1.test)('validates config schema', () => {
54
+ const configPath = (0, node_path_1.join)(testSubDir, 'invalid-config.yml');
55
+ (0, node_fs_1.writeFileSync)(configPath, `
56
+ invalidKey: value
57
+ `);
58
+ (0, bun_test_1.expect)(() => (0, config_1.loadConfig)(configPath, testSubDir)).toThrow();
59
+ });
60
+ (0, bun_test_1.test)('handles commands configuration', () => {
61
+ const configPath = (0, node_path_1.join)(testSubDir, 'commands-config.yml');
62
+ (0, node_fs_1.writeFileSync)(configPath, `
63
+ commands:
64
+ test: echo "test"
65
+ complex:
66
+ command: echo "complex"
67
+ description: A complex command
68
+ `);
69
+ const config = (0, config_1.loadConfig)(configPath, testSubDir);
70
+ (0, bun_test_1.expect)(config?.commands).toEqual({
71
+ test: 'echo "test"',
72
+ complex: {
73
+ command: 'echo "complex"',
74
+ description: 'A complex command',
75
+ },
76
+ });
77
+ });
78
+ (0, bun_test_1.test)('handles rules configuration', () => {
79
+ const configPath = (0, node_path_1.join)(testSubDir, 'rules-config.yml');
80
+ (0, node_fs_1.writeFileSync)(configPath, `
81
+ rules:
82
+ - rule1
83
+ - rule2
84
+ `);
85
+ const config = (0, config_1.loadConfig)(configPath, testSubDir);
86
+ (0, bun_test_1.expect)(config?.rules).toEqual(['rule1', 'rule2']);
87
+ });
88
+ });
89
+ //# 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,15 @@
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;
15
+ //# sourceMappingURL=handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,8BAA8B,EAAS,MAAM,oBAAoB,CAAA;AAE/E,OAAO,EAAE,KAAK,WAAW,EAAsE,MAAM,mBAAmB,CAAA;AA8RxH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,cAAc,CAAC,EAAE;QACf,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;QACrD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;QACrD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,8BAA8B,KAAK,IAAI,CAAA;KAClF,CAAA;IACD,KAAK,CAAC,EAAE;QACN,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;QAClD,GAAG,CAAC,EAAE,MAAM,CAAA;KACb,CAAA;CACF,CAAA;AAED,eAAO,MAAM,cAAc,YAAa,kBAAkB,KAAG,WAQ5D,CAAA"}
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getToolHandler = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const promises_1 = require("node:fs/promises");
6
+ const core_1 = require("@polka-codes/core");
7
+ const listFiles_1 = require("./utils/listFiles");
8
+ const replaceInFile_1 = require("./utils/replaceInFile");
9
+ const logger = (0, core_1.createServiceLogger)('cli/handlers');
10
+ const handleError = async (name, fn) => {
11
+ try {
12
+ return await fn();
13
+ }
14
+ catch (error) {
15
+ logger.warn(error, `Error executing tool: ${name}`);
16
+ return {
17
+ type: core_1.ToolResponseType.Error,
18
+ message: `Error executing tool: ${name}
19
+ Error: ${error}`,
20
+ canRetry: false,
21
+ };
22
+ }
23
+ };
24
+ const getString = (args, name, defaultValue) => {
25
+ const ret = args[name] ?? defaultValue;
26
+ if (!ret) {
27
+ throw new Error(`Missing required argument: ${name}`);
28
+ }
29
+ return ret;
30
+ };
31
+ const getStringArray = (args, name, defaultValue) => {
32
+ const ret = args[name];
33
+ if (!ret) {
34
+ if (defaultValue === undefined) {
35
+ throw new Error(`Missing required argument: ${name}`);
36
+ }
37
+ return defaultValue;
38
+ }
39
+ return ret.split(',');
40
+ };
41
+ const getBoolean = (args, name, defaultValue) => {
42
+ const ret = args[name];
43
+ if (!ret) {
44
+ if (defaultValue === undefined) {
45
+ throw new Error(`Missing required argument: ${name}`);
46
+ }
47
+ return defaultValue;
48
+ }
49
+ switch (ret.toLowerCase()) {
50
+ case 'true':
51
+ return true;
52
+ case 'false':
53
+ return false;
54
+ default:
55
+ throw new Error(`Invalid argument value: ${name}`);
56
+ }
57
+ };
58
+ const getInt = (args, name, defaultValue) => {
59
+ const ret = args[name];
60
+ if (!ret) {
61
+ if (defaultValue === undefined) {
62
+ throw new Error(`Missing required argument: ${name}`);
63
+ }
64
+ return defaultValue;
65
+ }
66
+ const parsed = Number.parseInt(ret);
67
+ if (Number.isNaN(parsed)) {
68
+ throw new Error(`Invalid argument value: ${name}`);
69
+ }
70
+ return parsed;
71
+ };
72
+ const handlers = {
73
+ executeCommand: async (options, args) => {
74
+ const command = getString(args, 'command');
75
+ const shouldExecute = (await options.executeCommand?.shouldExecute?.(command)) ?? true;
76
+ if (!shouldExecute) {
77
+ return {
78
+ type: core_1.ToolResponseType.Invalid,
79
+ message: `<command>${command}</command><command_rejected>Rejected by policy</command_rejected>`,
80
+ };
81
+ }
82
+ const requiresApproval = getBoolean(args, 'requires_approval', false);
83
+ if (requiresApproval) {
84
+ const shouldApprove = await options.executeCommand?.shouldApprove?.(command);
85
+ if (!shouldApprove) {
86
+ return {
87
+ type: core_1.ToolResponseType.Invalid,
88
+ message: `<command>${command}</command><command_rejected>Rejected by policy</command_rejected>`,
89
+ };
90
+ }
91
+ }
92
+ // TODO: add timeout
93
+ return new Promise((resolve, reject) => {
94
+ // spawn a shell to execute the command
95
+ logger.trace(`Executing command: ${command}`);
96
+ const child = (0, node_child_process_1.spawn)(command, [], {
97
+ shell: true,
98
+ stdio: 'pipe',
99
+ });
100
+ options.executeCommand?.commandStarted?.(command, child);
101
+ let stdoutText = '';
102
+ let stderrText = '';
103
+ child.stdout.on('data', (data) => {
104
+ stdoutText += data.toString();
105
+ });
106
+ child.stderr.on('data', (data) => {
107
+ stderrText += data.toString();
108
+ });
109
+ child.on('close', (code) => {
110
+ const message = `<command>${command}</command>
111
+ <command_exit_code>${code}</command_exit_code>
112
+ <command_stdout>
113
+ ${stdoutText}
114
+ </command_stdout>
115
+ <command_stderr>
116
+ ${stderrText}
117
+ </command_stderr>
118
+ `;
119
+ if (code === 0) {
120
+ resolve({
121
+ type: core_1.ToolResponseType.Reply,
122
+ message,
123
+ });
124
+ }
125
+ else {
126
+ resolve({
127
+ type: core_1.ToolResponseType.Error,
128
+ message,
129
+ });
130
+ }
131
+ });
132
+ child.on('error', (err) => {
133
+ reject(err);
134
+ });
135
+ });
136
+ },
137
+ readFile: async (options, args) => {
138
+ const paths = getStringArray(args, 'path');
139
+ for (const path of paths) {
140
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
141
+ if (!isPathAllowed) {
142
+ return {
143
+ type: core_1.ToolResponseType.Invalid,
144
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
145
+ };
146
+ }
147
+ }
148
+ const resp = [];
149
+ for (const path of paths) {
150
+ const fileContent = await (0, promises_1.readFile)(path, 'utf8');
151
+ resp.push(`<read_file_file_conten path="${path}">${fileContent}</read_file_file_content>`);
152
+ }
153
+ return {
154
+ type: core_1.ToolResponseType.Reply,
155
+ message: resp.join('\n'),
156
+ };
157
+ },
158
+ writeToFile: async (options, args) => {
159
+ const path = getString(args, 'path');
160
+ const content = getString(args, 'content');
161
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
162
+ if (!isPathAllowed) {
163
+ return {
164
+ type: core_1.ToolResponseType.Invalid,
165
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
166
+ };
167
+ }
168
+ await (0, promises_1.writeFile)(path, content, 'utf8');
169
+ return {
170
+ type: core_1.ToolResponseType.Reply,
171
+ message: `<write_file_path>${path}</write_file_path><status>Success</status>`,
172
+ };
173
+ },
174
+ replaceInFile: async (options, args) => {
175
+ const path = getString(args, 'path');
176
+ const diff = getString(args, 'diff');
177
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
178
+ if (!isPathAllowed) {
179
+ return {
180
+ type: core_1.ToolResponseType.Invalid,
181
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
182
+ };
183
+ }
184
+ const fileContent = await (0, promises_1.readFile)(path, 'utf8');
185
+ const result = await (0, replaceInFile_1.replaceInFile)(fileContent, diff);
186
+ await (0, promises_1.writeFile)(path, result, 'utf8');
187
+ return {
188
+ type: core_1.ToolResponseType.Reply,
189
+ message: `<replace_in_file_path>${path}</replace_in_file_path>`,
190
+ };
191
+ },
192
+ searchFiles: async (options, args) => {
193
+ // TODO
194
+ return {
195
+ type: core_1.ToolResponseType.Exit,
196
+ message: 'Files searched successfully',
197
+ };
198
+ },
199
+ listFiles: async (options, args) => {
200
+ const path = getString(args, 'path');
201
+ const depth = getInt(args, 'depth', 5);
202
+ const isPathAllowed = (await options.files?.isPathAllowed?.(path)) ?? true;
203
+ if (!isPathAllowed) {
204
+ return {
205
+ type: core_1.ToolResponseType.Invalid,
206
+ message: `<path>${path}</path><path_rejected>Rejected by policy</path_rejected>`,
207
+ };
208
+ }
209
+ const recursive = depth > 0;
210
+ const [files, limitReached] = await (0, listFiles_1.listFiles)(path, recursive, depth, options.files?.cwd ?? process.cwd());
211
+ return {
212
+ type: core_1.ToolResponseType.Reply,
213
+ message: `<list_files_path>${path}</list_files_path>
214
+ <list_files_depth>${depth}</list_files_depth>
215
+ <list_files_files>
216
+ ${files.join('\n')}
217
+ </list_files_files>
218
+ <list_files_truncated>${limitReached}</list_files_truncated>`,
219
+ };
220
+ },
221
+ listCodeDefinitionNames: async (options, args) => {
222
+ // TODO
223
+ return {
224
+ type: core_1.ToolResponseType.Exit,
225
+ message: 'Code definition names listed successfully',
226
+ };
227
+ },
228
+ askFollowupQuestion: async (options, args) => {
229
+ // TODO
230
+ return {
231
+ type: core_1.ToolResponseType.Exit,
232
+ message: 'Followup question asked successfully',
233
+ };
234
+ },
235
+ attemptCompletion: async (options, args) => {
236
+ return {
237
+ type: core_1.ToolResponseType.Exit,
238
+ message: '<completed>true</completed>',
239
+ };
240
+ },
241
+ };
242
+ const processedHandlers = Object.fromEntries(Object.entries(handlers).map(([toolName, handler]) => {
243
+ return [
244
+ core_1.allTools[toolName].name,
245
+ async (options, args) => handleError(toolName, async () => handler(options, args)),
246
+ ];
247
+ }));
248
+ const getToolHandler = (options) => {
249
+ return async (toolName, args) => {
250
+ const handler = processedHandlers[toolName];
251
+ if (!handler) {
252
+ throw new Error(`Unknown tool: ${toolName}`);
253
+ }
254
+ return handler(options, args);
255
+ };
256
+ };
257
+ exports.getToolHandler = getToolHandler;
258
+ //# 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,2 @@
1
- #!/usr/bin/env node
2
1
  export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -1,17 +1,30 @@
1
- #!/usr/bin/env node
2
- import { PolkaCore, VERSION } from '@polka-codes/core';
3
- import { Command } from 'commander';
4
- const program = new Command();
5
- program.name('polka').description('Polka Codes CLI').version(VERSION);
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const commander_1 = require("commander");
4
+ const package_json_1 = require("../package.json");
5
+ const config_1 = require("./config");
6
+ const runTask_1 = require("./runTask");
7
+ const program = new commander_1.Command();
8
+ program.name('polka').description('Polka Codes CLI').version(package_json_1.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 = (0, config_1.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 (0, runTask_1.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,yCAAmC;AAEnC,kDAAyC;AACzC,qCAAqC;AACrC,uCAAmC;AAEnC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAA;AAE7B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,sBAAO,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,IAAA,mBAAU,EAAC,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,IAAA,iBAAO,EAAC;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,10 @@
1
+ import type { Config } from './config';
2
+ export type RunTaskOptions = {
3
+ task: string;
4
+ provider: string;
5
+ model: string;
6
+ apiKey: string;
7
+ config: Config;
8
+ };
9
+ export declare const runTask: (options: RunTaskOptions) => Promise<void>;
10
+ //# sourceMappingURL=runTask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runTask.d.ts","sourceRoot":"","sources":["../src/runTask.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAItC,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAID,eAAO,MAAM,OAAO,YAAmB,cAAc,kBA8GpD,CAAA"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runTask = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const node_os_1 = tslib_1.__importDefault(require("node:os"));
6
+ const core_1 = require("@polka-codes/core");
7
+ const handlers_1 = require("./handlers");
8
+ const listFiles_1 = require("./utils/listFiles");
9
+ const logger = (0, core_1.createServiceLogger)('cli/runTask');
10
+ const runTask = async (options) => {
11
+ logger.debug(options, 'Running task');
12
+ const { task, provider, model, apiKey, config } = options;
13
+ // Create service with the configured options
14
+ const service = (0, core_1.createService)(provider, {
15
+ apiKey,
16
+ modelId: model,
17
+ });
18
+ let rules = config.rules;
19
+ if (typeof rules === 'string') {
20
+ rules = [rules];
21
+ }
22
+ const agent = new core_1.CoderAgent({
23
+ ai: service,
24
+ os: node_os_1.default.platform(),
25
+ customInstructions: rules,
26
+ commands: config.commands,
27
+ toolHandler: (0, handlers_1.getToolHandler)({
28
+ executeCommand: {
29
+ async shouldExecute(command) {
30
+ // TODO: command whitelist
31
+ return true;
32
+ },
33
+ async shouldApprove(command) {
34
+ // TODO: config for auto approve
35
+ return true;
36
+ },
37
+ commandStarted(command, child) {
38
+ console.log(`$ >>>> $ ${command}`);
39
+ child.stdout.on('data', (data) => {
40
+ process.stdout.write(data.toString());
41
+ });
42
+ child.stderr.on('data', (data) => {
43
+ process.stderr.write(data.toString());
44
+ });
45
+ child.on('close', (code) => {
46
+ console.log(`$ <<<< $ Command exited with code: ${code}`);
47
+ });
48
+ },
49
+ },
50
+ }),
51
+ });
52
+ const cwd = process.cwd();
53
+ const [fileList, limited] = await (0, listFiles_1.listFiles)(cwd, true, 100, cwd);
54
+ const fileContext = `<files>
55
+ ${fileList.join('\n')}${limited ? '\n<files_truncated>true</files_truncated>' : ''}
56
+ </files>`;
57
+ const usage = {
58
+ inputTokens: 0,
59
+ outputTokens: 0,
60
+ cacheWriteTokens: 0,
61
+ cacheReadTokens: 0,
62
+ totalCost: 0,
63
+ };
64
+ await agent.startTask({
65
+ task,
66
+ context: `<now_date>${new Date().toISOString()}</now_date>${fileContext}`,
67
+ maxIterations: 10,
68
+ callback: (event) => {
69
+ if (event.kind === 'usage') {
70
+ usage.inputTokens += event.info.inputTokens;
71
+ usage.outputTokens += event.info.outputTokens;
72
+ usage.cacheWriteTokens += event.info.cacheWriteTokens ?? 0;
73
+ usage.cacheReadTokens += event.info.cacheReadTokens ?? 0;
74
+ usage.totalCost += event.info.totalCost ?? 0;
75
+ }
76
+ if (event.kind === 'start_request') {
77
+ console.log('>>>>');
78
+ const { userContent } = event;
79
+ if (userContent) {
80
+ for (const content of userContent) {
81
+ console.log(content.type === 'text' ? content.text : '');
82
+ }
83
+ }
84
+ console.log('====');
85
+ }
86
+ if (event.newText) {
87
+ process.stdout.write(event.newText);
88
+ }
89
+ if (event.kind === 'end_request') {
90
+ process.stdout.write('\n');
91
+ console.log('<<<<');
92
+ }
93
+ },
94
+ });
95
+ if (!usage.totalCost) {
96
+ // we need to calculate the total cost
97
+ const modelInfo = agent.model.info;
98
+ const inputCost = (modelInfo.inputPrice ?? 0) * usage.inputTokens;
99
+ const outputCost = (modelInfo.outputPrice ?? 0) * usage.outputTokens;
100
+ const cacheReadCost = (modelInfo.cacheReadsPrice ?? 0) * usage.cacheReadTokens;
101
+ const cacheWriteCost = (modelInfo.cacheWritesPrice ?? 0) * usage.cacheWriteTokens;
102
+ usage.totalCost = (inputCost + outputCost + cacheReadCost + cacheWriteCost) / 1_000_000;
103
+ }
104
+ console.log('Usages:');
105
+ console.log(`Input tokens: ${usage.inputTokens}`);
106
+ console.log(`Output tokens: ${usage.outputTokens}`);
107
+ console.log(`Cache read tokens: ${usage.cacheReadTokens}`);
108
+ console.log(`Cache write tokens: ${usage.cacheWriteTokens}`);
109
+ console.log(`Total cost: ${usage.totalCost}`);
110
+ };
111
+ exports.runTask = runTask;
112
+ //# sourceMappingURL=runTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runTask.js","sourceRoot":"","sources":["../src/runTask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
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]>;
12
+ //# sourceMappingURL=listFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listFiles.d.ts","sourceRoot":"","sources":["../../src/utils/listFiles.ts"],"names":[],"mappings":"AA0CA;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC,CAwDhI"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listFiles = listFiles;
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const ignore_1 = tslib_1.__importDefault(require("ignore"));
8
+ /** Default patterns commonly ignored in projects of various languages. */
9
+ const DEFAULT_IGNORES = [
10
+ '__pycache__',
11
+ '.DS_Store',
12
+ '.env',
13
+ '.git',
14
+ '.idea',
15
+ '.svn',
16
+ '.temp',
17
+ '.vscode',
18
+ 'coverage',
19
+ 'dist',
20
+ 'node_modules',
21
+ 'out',
22
+ 'Thumbs.db',
23
+ ];
24
+ /**
25
+ * Reads a `.gitignore` file in `dirPath` (if it exists) and appends its lines
26
+ * to the `basePatterns`. Returns a new array without mutating the original.
27
+ */
28
+ async function extendPatterns(basePatterns, dirPath) {
29
+ try {
30
+ const gitignorePath = (0, node_path_1.join)(dirPath, '.gitignore');
31
+ const content = await node_fs_1.promises.readFile(gitignorePath, 'utf8');
32
+ const lines = content.split(/\r?\n/).filter(Boolean);
33
+ return [...basePatterns, ...lines];
34
+ }
35
+ catch {
36
+ // No .gitignore or unreadable
37
+ return basePatterns;
38
+ }
39
+ }
40
+ /** Creates an `ignore` instance from the given patterns. */
41
+ function createIgnore(patterns) {
42
+ return (0, ignore_1.default)().add(patterns);
43
+ }
44
+ /**
45
+ * Lists files under `dirPath` in BFS order, respecting:
46
+ * - A default set of ignores
47
+ * - A root .gitignore under `cwd`
48
+ * - Any .gitignore files in child directories (merged as we go)
49
+ *
50
+ * Returns `[files, limitReached]`:
51
+ * - `files` is the array of file paths (relative to `cwd`)
52
+ * - `limitReached` is `true` if `maxCount` was hit, otherwise `false`
53
+ */
54
+ async function listFiles(dirPath, recursive, maxCount, cwd) {
55
+ // Merge default ignores with root .gitignore (if found)
56
+ let rootPatterns = [...DEFAULT_IGNORES];
57
+ try {
58
+ const rootGitignore = await node_fs_1.promises.readFile((0, node_path_1.join)(cwd, '.gitignore'), 'utf8');
59
+ const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
60
+ rootPatterns = [...rootPatterns, ...lines];
61
+ }
62
+ catch {
63
+ // No .gitignore at root or unreadable; ignore silently
64
+ }
65
+ // Final results (relative to `cwd`) and indicator if we reached the limit
66
+ const results = [];
67
+ // BFS queue
68
+ // Each entry holds the directory path and the patterns inherited from its parent
69
+ const queue = [{ path: (0, node_path_1.resolve)(dirPath), patterns: rootPatterns }];
70
+ // Perform BFS until queue is empty or maxCount is reached
71
+ while (queue.length > 0) {
72
+ // biome-ignore lint/style/noNonNullAssertion: checked above
73
+ const { path: currentPath, patterns: parentPatterns } = queue.shift();
74
+ // Merge parent's patterns with local .gitignore
75
+ const mergedPatterns = await extendPatterns(parentPatterns, currentPath);
76
+ const folderIg = createIgnore(mergedPatterns);
77
+ const entries = await node_fs_1.promises.readdir(currentPath, { withFileTypes: true });
78
+ for (const entry of entries) {
79
+ const fullPath = (0, node_path_1.join)(currentPath, entry.name);
80
+ // Convert full path to something relative to `cwd`
81
+ const relPath = (0, node_path_1.relative)(cwd, fullPath).replace(/\\/g, '/');
82
+ if (folderIg.ignores(relPath)) {
83
+ continue; // Skip ignored entries
84
+ }
85
+ if (entry.isDirectory()) {
86
+ if (recursive) {
87
+ queue.push({ path: fullPath, patterns: mergedPatterns });
88
+ }
89
+ }
90
+ else {
91
+ results.push(relPath);
92
+ if (results.length >= maxCount) {
93
+ results.sort();
94
+ // Stop searching as soon as we reach maxCount
95
+ return [results, true];
96
+ }
97
+ }
98
+ }
99
+ }
100
+ results.sort();
101
+ // If we exhaust the BFS queue, we did not reach maxCount
102
+ return [results, false];
103
+ }
104
+ //# sourceMappingURL=listFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listFiles.js","sourceRoot":"","sources":["../../src/utils/listFiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=listFiles.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listFiles.test.d.ts","sourceRoot":"","sources":["../../src/utils/listFiles.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const listFiles_1 = require("./listFiles");
7
+ (0, bun_test_1.describe)('listFiles', () => {
8
+ const testDir = (0, node_path_1.join)(__dirname, 'test-fixtures');
9
+ (0, bun_test_1.beforeAll)(async () => {
10
+ // Create test directory structure
11
+ await node_fs_1.promises.mkdir(testDir, { recursive: true });
12
+ await node_fs_1.promises.writeFile((0, node_path_1.join)(testDir, '.gitignore'), 'ignored.txt\nsubdir/ignored-too.txt');
13
+ await node_fs_1.promises.writeFile((0, node_path_1.join)(testDir, 'file1.txt'), '');
14
+ await node_fs_1.promises.writeFile((0, node_path_1.join)(testDir, 'file2.txt'), '');
15
+ await node_fs_1.promises.writeFile((0, node_path_1.join)(testDir, 'ignored.txt'), '');
16
+ // Create subdirectory
17
+ const subDir = (0, node_path_1.join)(testDir, 'subdir');
18
+ await node_fs_1.promises.mkdir(subDir);
19
+ await node_fs_1.promises.writeFile((0, node_path_1.join)(subDir, 'file3.txt'), '');
20
+ await node_fs_1.promises.writeFile((0, node_path_1.join)(subDir, 'ignored-too.txt'), '');
21
+ });
22
+ (0, bun_test_1.afterAll)(async () => {
23
+ // Clean up test directory
24
+ await node_fs_1.promises.rm(testDir, { recursive: true, force: true });
25
+ });
26
+ (0, bun_test_1.it)('should list files in directory', async () => {
27
+ const [files] = await (0, listFiles_1.listFiles)(testDir, false, 10, testDir);
28
+ (0, bun_test_1.expect)(files).toEqual(['.gitignore', 'file1.txt', 'file2.txt']);
29
+ });
30
+ (0, bun_test_1.it)('should list files recursively', async () => {
31
+ const [files] = await (0, listFiles_1.listFiles)(testDir, true, 10, testDir);
32
+ (0, bun_test_1.expect)(files).toEqual(['.gitignore', 'file1.txt', 'file2.txt', 'subdir/file3.txt']);
33
+ });
34
+ (0, bun_test_1.it)('should respect maxCount', async () => {
35
+ const [files, limitReached] = await (0, listFiles_1.listFiles)(testDir, true, 3, testDir);
36
+ (0, bun_test_1.expect)(files.length).toBe(3);
37
+ (0, bun_test_1.expect)(limitReached).toBe(true);
38
+ (0, bun_test_1.expect)(files).toEqual(['.gitignore', 'file1.txt', 'file2.txt']);
39
+ });
40
+ (0, bun_test_1.it)('should handle empty directory', async () => {
41
+ const emptyDir = (0, node_path_1.join)(testDir, 'empty');
42
+ await node_fs_1.promises.mkdir(emptyDir);
43
+ const [files] = await (0, listFiles_1.listFiles)(emptyDir, true, 10, emptyDir);
44
+ (0, bun_test_1.expect)(files).toEqual([]);
45
+ await node_fs_1.promises.rm(emptyDir, { recursive: true });
46
+ });
47
+ (0, bun_test_1.it)('should handle non-existent directory', async () => {
48
+ (0, bun_test_1.expect)((0, listFiles_1.listFiles)((0, node_path_1.join)(testDir, 'nonexistent'), false, 10, testDir)).rejects.toThrow();
49
+ });
50
+ });
51
+ //# sourceMappingURL=listFiles.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listFiles.test.js","sourceRoot":"","sources":["../../src/utils/listFiles.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const replaceInFile: (fileContent: string, diff: string) => Promise<string>;
2
+ //# sourceMappingURL=replaceInFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replaceInFile.d.ts","sourceRoot":"","sources":["../../src/utils/replaceInFile.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,gBAAuB,MAAM,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAoFrF,CAAA"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /* Example diff block format:
3
+ <<<<<<< SEARCH
4
+ // original text
5
+ =======
6
+ // replacement text
7
+ >>>>>>> REPLACE
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.replaceInFile = void 0;
11
+ const replaceInFile = async (fileContent, diff) => {
12
+ // Regex to match blocks of the form:
13
+ // <<<<<<< SEARCH
14
+ // (some lines)
15
+ // =======
16
+ // (some lines)
17
+ // >>>>>>> REPLACE
18
+ const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
19
+ // Parse diff blocks
20
+ const blocks = [];
21
+ for (let match = blockPattern.exec(diff); match !== null; match = blockPattern.exec(diff)) {
22
+ blocks.push({ search: match[1], replace: match[2] });
23
+ }
24
+ if (blocks.length === 0) {
25
+ throw new Error('No valid diff blocks found.');
26
+ }
27
+ // Helper: try to find the search text in fileContent with progressive relaxation
28
+ const findAndReplace = (content, search, replace) => {
29
+ // 1) Direct exact match
30
+ let index = content.indexOf(search);
31
+ if (index !== -1) {
32
+ return content.slice(0, index) + replace + content.slice(index + search.length);
33
+ }
34
+ // 2) Trim leading/ending whitespace in search and content
35
+ const trimmedSearch = search.trim();
36
+ const trimmedContent = content.trim();
37
+ const offset = content.indexOf(trimmedContent); // to restore original indexing if found
38
+ index = trimmedContent.indexOf(trimmedSearch);
39
+ if (index !== -1) {
40
+ // compute correct absolute index in the original content
41
+ const absoluteIndex = offset + index;
42
+ return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
43
+ }
44
+ // 3) Whitespace-agnostic match:
45
+ // Replace all consecutive whitespace in search and content with a single marker
46
+ // to see if there's a match ignoring whitespace diffs
47
+ const normalizedSearch = trimmedSearch.replace(/\s+/g, ' ');
48
+ const normalizedContent = trimmedContent.replace(/\s+/g, ' ');
49
+ index = normalizedContent.indexOf(normalizedSearch);
50
+ if (index !== -1) {
51
+ // Find actual location in the original content. We do a rough approach here:
52
+ // We know the substring's "normalized" start is at 'index' in normalizedContent.
53
+ // A simple way is to walk through the original trimmedContent to find where that occurs.
54
+ // For brevity, we'll do a naive re-scan and hope it's correct in typical cases.
55
+ let runningIndex = 0;
56
+ let actualPos = offset;
57
+ for (const segment of trimmedSearch.replace(/\s+/g, ' ').split(' ')) {
58
+ const segIndex = content.indexOf(segment, actualPos);
59
+ if (segIndex === -1) {
60
+ break; // mismatch, won't happen if we truly found it
61
+ }
62
+ if (runningIndex === 0) {
63
+ // First segment helps define the start
64
+ actualPos = segIndex;
65
+ }
66
+ else {
67
+ // Move just after the segment to keep scanning
68
+ actualPos = segIndex + segment.length;
69
+ }
70
+ runningIndex++;
71
+ }
72
+ // By the time we’re done, actualPos should be the end of the matched substring.
73
+ // We do a length calc for the final replacement index:
74
+ // but we need the total length of trimmedSearch minus whitespace. We'll reconstruct:
75
+ const strippedSearch = trimmedSearch.replace(/\s+/g, '');
76
+ const endPos = actualPos; // The end of the final segment
77
+ const startPos = endPos - strippedSearch.length;
78
+ return content.slice(0, startPos) + replace + content.slice(endPos);
79
+ }
80
+ throw new Error(`Could not find the following text in file:\n${search}`);
81
+ };
82
+ let updatedFile = fileContent;
83
+ for (const { search, replace } of blocks) {
84
+ updatedFile = findAndReplace(updatedFile, search, replace);
85
+ }
86
+ return updatedFile;
87
+ };
88
+ exports.replaceInFile = replaceInFile;
89
+ //# sourceMappingURL=replaceInFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replaceInFile.js","sourceRoot":"","sources":["../../src/utils/replaceInFile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=replaceInFile.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replaceInFile.test.d.ts","sourceRoot":"","sources":["../../src/utils/replaceInFile.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const replaceInFile_1 = require("./replaceInFile");
5
+ (0, bun_test_1.describe)('replaceInFile', () => {
6
+ (0, bun_test_1.it)('should perform basic single replacement', async () => {
7
+ const content = `line1
8
+ line2
9
+ line3`;
10
+ const diff = `<<<<<<< SEARCH
11
+ line2
12
+ =======
13
+ new line2
14
+ >>>>>>> REPLACE`;
15
+ const result = await (0, replaceInFile_1.replaceInFile)(content, diff);
16
+ (0, bun_test_1.expect)(result).toBe(`line1
17
+ new line2
18
+ line3`);
19
+ });
20
+ (0, bun_test_1.it)('should handle multiple replacements', async () => {
21
+ const content = `line1
22
+ line2
23
+ line3
24
+ line2`;
25
+ const diff = `<<<<<<< SEARCH
26
+ line2
27
+ =======
28
+ new line2
29
+ >>>>>>> REPLACE
30
+ <<<<<<< SEARCH
31
+ line3
32
+ =======
33
+ new line3
34
+ >>>>>>> REPLACE`;
35
+ const result = await (0, replaceInFile_1.replaceInFile)(content, diff);
36
+ (0, bun_test_1.expect)(result).toBe(`line1
37
+ new line2
38
+ new line3
39
+ line2`);
40
+ });
41
+ (0, bun_test_1.it)('should handle whitespace variations', async () => {
42
+ const content = `line1
43
+ line2
44
+ line3`;
45
+ const diff = `<<<<<<< SEARCH
46
+ line2
47
+ =======
48
+ new line2
49
+ >>>>>>> REPLACE`;
50
+ const result = await (0, replaceInFile_1.replaceInFile)(content, diff);
51
+ (0, bun_test_1.expect)(result).toBe(`line1
52
+ new line2
53
+ line3`);
54
+ });
55
+ (0, bun_test_1.it)('should throw error when no blocks found', async () => {
56
+ const content = `line1
57
+ line2`;
58
+ const diff = 'invalid format';
59
+ (0, bun_test_1.expect)((0, replaceInFile_1.replaceInFile)(content, diff)).rejects.toThrow('No valid diff blocks found');
60
+ });
61
+ (0, bun_test_1.it)('should throw error when search text not found', async () => {
62
+ const content = `line1
63
+ line2`;
64
+ const diff = `<<<<<<< SEARCH
65
+ line3
66
+ =======
67
+ new line3
68
+ >>>>>>> REPLACE`;
69
+ (0, bun_test_1.expect)((0, replaceInFile_1.replaceInFile)(content, diff)).rejects.toThrow('Could not find the following text in file');
70
+ });
71
+ (0, bun_test_1.it)('should handle empty file', async () => {
72
+ const content = '';
73
+ const diff = `<<<<<<< SEARCH
74
+ line1
75
+ =======
76
+ new line1
77
+ >>>>>>> REPLACE`;
78
+ (0, bun_test_1.expect)((0, replaceInFile_1.replaceInFile)(content, diff)).rejects.toThrow('Could not find the following text in file');
79
+ });
80
+ (0, bun_test_1.it)('should handle empty replacement', async () => {
81
+ const content = `line1
82
+ line2`;
83
+ const diff = `<<<<<<< SEARCH
84
+ line2
85
+ =======
86
+ >>>>>>> REPLACE`;
87
+ const result = await (0, replaceInFile_1.replaceInFile)(content, diff);
88
+ (0, bun_test_1.expect)(result).toBe(`line1
89
+ `);
90
+ });
91
+ });
92
+ //# sourceMappingURL=replaceInFile.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replaceInFile.test.js","sourceRoot":"","sources":["../../src/utils/replaceInFile.test.ts"],"names":[],"mappings":";;AAAA,uCAA+C;AAE/C,mDAA+C;AAE/C,IAAA,mBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAA,aAAE,EAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,OAAO,GAAG;;MAEd,CAAA;QACF,MAAM,IAAI,GAAG;;;;gBAID,CAAA;QAEZ,MAAM,MAAM,GAAG,MAAM,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QACjD,IAAA,iBAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC;;MAElB,CAAC,CAAA;IACL,CAAC,CAAC,CAAA;IAEF,IAAA,aAAE,EAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,OAAO,GAAG;;;MAGd,CAAA;QACF,MAAM,IAAI,GAAG;;;;;;;;;gBASD,CAAA;QAEZ,MAAM,MAAM,GAAG,MAAM,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QACjD,IAAA,iBAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC;;;MAGlB,CAAC,CAAA;IACL,CAAC,CAAC,CAAA;IAEF,IAAA,aAAE,EAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,OAAO,GAAG;;MAEd,CAAA;QACF,MAAM,IAAI,GAAG;;;;gBAID,CAAA;QAEZ,MAAM,MAAM,GAAG,MAAM,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QACjD,IAAA,iBAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC;;MAElB,CAAC,CAAA;IACL,CAAC,CAAC,CAAA;IAEF,IAAA,aAAE,EAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,OAAO,GAAG;MACd,CAAA;QACF,MAAM,IAAI,GAAG,gBAAgB,CAAA;QAE7B,IAAA,iBAAM,EAAC,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;IAEF,IAAA,aAAE,EAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,OAAO,GAAG;MACd,CAAA;QACF,MAAM,IAAI,GAAG;;;;gBAID,CAAA;QAEZ,IAAA,iBAAM,EAAC,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAA;IACnG,CAAC,CAAC,CAAA;IAEF,IAAA,aAAE,EAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,OAAO,GAAG,EAAE,CAAA;QAClB,MAAM,IAAI,GAAG;;;;gBAID,CAAA;QAEZ,IAAA,iBAAM,EAAC,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAA;IACnG,CAAC,CAAC,CAAA;IAEF,IAAA,aAAE,EAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,OAAO,GAAG;MACd,CAAA;QACF,MAAM,IAAI,GAAG;;;gBAGD,CAAA;QAEZ,MAAM,MAAM,GAAG,MAAM,IAAA,6BAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QACjD,IAAA,iBAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC;CACvB,CAAC,CAAA;IACA,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@polka-codes/cli",
3
- "version": "0.0.4",
3
+ "version": "0.1.1",
4
+ "license": "AGPL-3.0",
4
5
  "type": "module",
5
6
  "bin": {
6
7
  "polka": "./dist/index.js"
@@ -12,8 +13,13 @@
12
13
  }
13
14
  },
14
15
  "dependencies": {
15
- "@polka-codes/core": "0.0.1",
16
- "commander": "^13.0.0"
16
+ "@polka-codes/core": "0.1.0",
17
+ "commander": "^13.0.0",
18
+ "ignore": "^7.0.3",
19
+ "pino-pretty": "^13.0.0",
20
+ "readline": "^1.3.0",
21
+ "yaml": "^2.7.0",
22
+ "zod": "^3.24.1"
17
23
  },
18
24
  "files": ["dist"]
19
25
  }