@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.
- package/dist/config.d.ts +37 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +1 -0
- package/dist/config.test.js +87 -0
- package/dist/config.test.js.map +1 -0
- package/dist/handlers.d.ts +14 -0
- package/dist/handlers.js +239 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +23 -10
- package/dist/index.js.map +1 -1
- package/dist/listFiles.d.ts +11 -0
- package/dist/listFiles.js +100 -0
- package/dist/listFiles.js.map +1 -0
- package/dist/listFiles.test.d.ts +1 -0
- package/dist/listFiles.test.js +49 -0
- package/dist/listFiles.test.js.map +1 -0
- package/dist/replaceInFile.d.ts +1 -0
- package/dist/replaceInFile.js +85 -0
- package/dist/replaceInFile.js.map +1 -0
- package/dist/replaceInFile.test.d.ts +1 -0
- package/dist/replaceInFile.test.js +90 -0
- package/dist/replaceInFile.test.js.map +1 -0
- package/dist/runTask.d.ts +9 -0
- package/dist/runTask.js +107 -0
- package/dist/runTask.js.map +1 -0
- package/dist/utils/listFiles.d.ts +11 -0
- package/dist/utils/listFiles.js +100 -0
- package/dist/utils/listFiles.js.map +1 -0
- package/dist/utils/listFiles.test.d.ts +1 -0
- package/dist/utils/listFiles.test.js +49 -0
- package/dist/utils/listFiles.test.js.map +1 -0
- package/dist/utils/replaceInFile.d.ts +1 -0
- package/dist/utils/replaceInFile.js +85 -0
- package/dist/utils/replaceInFile.js.map +1 -0
- package/dist/utils/replaceInFile.test.d.ts +1 -0
- package/dist/utils/replaceInFile.test.js +90 -0
- package/dist/utils/replaceInFile.test.js.map +1 -0
- package/package.json +9 -3
package/dist/config.d.ts
ADDED
|
@@ -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;
|
package/dist/handlers.js
ADDED
|
@@ -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
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(
|
|
8
|
+
program.name('polka').description('Polka Codes CLI').version(version);
|
|
9
|
+
// Main command for executing tasks
|
|
6
10
|
program
|
|
7
|
-
.
|
|
8
|
-
.
|
|
9
|
-
.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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":"
|
|
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 {};
|