ai-cmd 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +275 -0
  3. package/dist/cli/commands.d.ts +13 -0
  4. package/dist/cli/commands.js +221 -0
  5. package/dist/cli/commands.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.js +4 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/cli/prompts.d.ts +2 -0
  10. package/dist/cli/prompts.js +32 -0
  11. package/dist/cli/prompts.js.map +1 -0
  12. package/dist/cli/repl.d.ts +9 -0
  13. package/dist/cli/repl.js +166 -0
  14. package/dist/cli/repl.js.map +1 -0
  15. package/dist/config/env.d.ts +2 -0
  16. package/dist/config/env.js +8 -0
  17. package/dist/config/env.js.map +1 -0
  18. package/dist/config/userConfig.d.ts +10 -0
  19. package/dist/config/userConfig.js +91 -0
  20. package/dist/config/userConfig.js.map +1 -0
  21. package/dist/core/explainCommand.d.ts +2 -0
  22. package/dist/core/explainCommand.js +4 -0
  23. package/dist/core/explainCommand.js.map +1 -0
  24. package/dist/core/generateCommand.d.ts +2 -0
  25. package/dist/core/generateCommand.js +29 -0
  26. package/dist/core/generateCommand.js.map +1 -0
  27. package/dist/core/output.d.ts +4 -0
  28. package/dist/core/output.js +67 -0
  29. package/dist/core/output.js.map +1 -0
  30. package/dist/core/prompts.d.ts +7 -0
  31. package/dist/core/prompts.js +71 -0
  32. package/dist/core/prompts.js.map +1 -0
  33. package/dist/core/response.d.ts +19 -0
  34. package/dist/core/response.js +44 -0
  35. package/dist/core/response.js.map +1 -0
  36. package/dist/core/session.d.ts +9 -0
  37. package/dist/core/session.js +23 -0
  38. package/dist/core/session.js.map +1 -0
  39. package/dist/exec/runCommand.d.ts +11 -0
  40. package/dist/exec/runCommand.js +57 -0
  41. package/dist/exec/runCommand.js.map +1 -0
  42. package/dist/index.d.ts +5 -0
  43. package/dist/index.js +6 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/platform/detectPlatform.d.ts +9 -0
  46. package/dist/platform/detectPlatform.js +49 -0
  47. package/dist/platform/detectPlatform.js.map +1 -0
  48. package/dist/platform/detectServiceManager.d.ts +3 -0
  49. package/dist/platform/detectServiceManager.js +38 -0
  50. package/dist/platform/detectServiceManager.js.map +1 -0
  51. package/dist/platform/detectShell.d.ts +3 -0
  52. package/dist/platform/detectShell.js +21 -0
  53. package/dist/platform/detectShell.js.map +1 -0
  54. package/dist/providers/factory.d.ts +2 -0
  55. package/dist/providers/factory.js +9 -0
  56. package/dist/providers/factory.js.map +1 -0
  57. package/dist/providers/openai.d.ts +8 -0
  58. package/dist/providers/openai.js +73 -0
  59. package/dist/providers/openai.js.map +1 -0
  60. package/dist/providers/types.d.ts +1 -0
  61. package/dist/providers/types.js +2 -0
  62. package/dist/providers/types.js.map +1 -0
  63. package/dist/safety/classifyRisk.d.ts +7 -0
  64. package/dist/safety/classifyRisk.js +115 -0
  65. package/dist/safety/classifyRisk.js.map +1 -0
  66. package/dist/safety/dangerousPatterns.d.ts +8 -0
  67. package/dist/safety/dangerousPatterns.js +70 -0
  68. package/dist/safety/dangerousPatterns.js.map +1 -0
  69. package/dist/safety/executionPolicy.d.ts +9 -0
  70. package/dist/safety/executionPolicy.js +21 -0
  71. package/dist/safety/executionPolicy.js.map +1 -0
  72. package/dist/types/index.d.ts +79 -0
  73. package/dist/types/index.js +2 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/utils/branding.d.ts +6 -0
  76. package/dist/utils/branding.js +11 -0
  77. package/dist/utils/branding.js.map +1 -0
  78. package/dist/utils/errors.d.ts +26 -0
  79. package/dist/utils/errors.js +59 -0
  80. package/dist/utils/errors.js.map +1 -0
  81. package/dist/utils/logger.d.ts +5 -0
  82. package/dist/utils/logger.js +14 -0
  83. package/dist/utils/logger.js.map +1 -0
  84. package/dist/utils/strings.d.ts +5 -0
  85. package/dist/utils/strings.js +30 -0
  86. package/dist/utils/strings.js.map +1 -0
  87. package/package.json +69 -0
@@ -0,0 +1,11 @@
1
+ export interface RunCommandOptions {
2
+ cwd?: string;
3
+ env?: NodeJS.ProcessEnv;
4
+ stdio?: "inherit" | "pipe";
5
+ }
6
+ export declare function needsShellExecution(command: string): boolean;
7
+ export declare function runCommand(command: string, options?: RunCommandOptions): Promise<{
8
+ exitCode: number;
9
+ stdout: string;
10
+ stderr: string;
11
+ }>;
@@ -0,0 +1,57 @@
1
+ import { execa, execaCommand } from "execa";
2
+ import { parse as parseShellCommand } from "shell-quote";
3
+ import { ExecutionError } from "../utils/errors.js";
4
+ const SHELL_REQUIRED_PATTERN = /[|&;<>()$`*?[\]{}]|\b(?:if|then|fi|for|do|done|while|case)\b|^\s*[A-Za-z_][A-Za-z0-9_]*=/;
5
+ export function needsShellExecution(command) {
6
+ return SHELL_REQUIRED_PATTERN.test(command);
7
+ }
8
+ export async function runCommand(command, options = {}) {
9
+ try {
10
+ if (needsShellExecution(command)) {
11
+ const executionOptions = {
12
+ ...(options.cwd ? { cwd: options.cwd } : {}),
13
+ ...(options.env ? { env: options.env } : {}),
14
+ stdio: options.stdio ?? "inherit",
15
+ reject: false,
16
+ shell: true
17
+ };
18
+ const result = await execaCommand(command, {
19
+ ...executionOptions
20
+ });
21
+ if (result.exitCode !== 0) {
22
+ throw new ExecutionError(`Command failed with exit code ${result.exitCode}.`, result.stderr || result.stdout);
23
+ }
24
+ return {
25
+ exitCode: result.exitCode ?? 0,
26
+ stdout: result.stdout ?? "",
27
+ stderr: result.stderr ?? ""
28
+ };
29
+ }
30
+ const tokens = parseShellCommand(command).filter((part) => typeof part === "string");
31
+ const [file, ...args] = tokens;
32
+ if (!file) {
33
+ throw new ExecutionError("No executable command was produced.");
34
+ }
35
+ const result = await execa(file, args, {
36
+ ...(options.cwd ? { cwd: options.cwd } : {}),
37
+ ...(options.env ? { env: options.env } : {}),
38
+ stdio: options.stdio ?? "inherit",
39
+ reject: false
40
+ });
41
+ if (result.exitCode !== 0) {
42
+ throw new ExecutionError(`Command failed with exit code ${result.exitCode}.`, result.stderr || result.stdout);
43
+ }
44
+ return {
45
+ exitCode: result.exitCode ?? 0,
46
+ stdout: result.stdout ?? "",
47
+ stderr: result.stderr ?? ""
48
+ };
49
+ }
50
+ catch (error) {
51
+ if (error instanceof ExecutionError) {
52
+ throw error;
53
+ }
54
+ throw new ExecutionError("Failed to execute command.", error);
55
+ }
56
+ }
57
+ //# sourceMappingURL=runCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runCommand.js","sourceRoot":"","sources":["../../src/exec/runCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export * from "./types/index.js";
2
+ export * from "./config/userConfig.js";
3
+ export * from "./core/generateCommand.js";
4
+ export * from "./platform/detectPlatform.js";
5
+ export * from "./safety/classifyRisk.js";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from "./types/index.js";
2
+ export * from "./config/userConfig.js";
3
+ export * from "./core/generateCommand.js";
4
+ export * from "./platform/detectPlatform.js";
5
+ export * from "./safety/classifyRisk.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { OperatingSystem, PlatformContext } from "../types/index.js";
2
+ export type InferOperatingSystemOptions = {
3
+ platform: NodeJS.Platform;
4
+ env?: NodeJS.ProcessEnv;
5
+ procVersion?: string;
6
+ };
7
+ export declare function inferOperatingSystem(options: InferOperatingSystemOptions): OperatingSystem;
8
+ export declare function detectOperatingSystem(): Promise<OperatingSystem>;
9
+ export declare function detectPlatformContext(): Promise<PlatformContext>;
@@ -0,0 +1,49 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { detectServiceManager } from "./detectServiceManager.js";
4
+ import { detectShell } from "./detectShell.js";
5
+ export function inferOperatingSystem(options) {
6
+ if (options.platform === "darwin") {
7
+ return "macos";
8
+ }
9
+ if (options.platform === "linux") {
10
+ const wslEnv = options.env?.WSL_DISTRO_NAME ||
11
+ options.env?.WSL_INTEROP ||
12
+ options.procVersion?.toLowerCase().includes("microsoft");
13
+ return wslEnv ? "wsl" : "linux";
14
+ }
15
+ if (options.platform === "freebsd" || options.platform === "openbsd") {
16
+ return "unix";
17
+ }
18
+ return "unsupported";
19
+ }
20
+ async function readProcVersion() {
21
+ try {
22
+ return await readFile("/proc/version", "utf8");
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ }
28
+ export async function detectOperatingSystem() {
29
+ const procVersion = process.platform === "linux" ? await readProcVersion() : undefined;
30
+ return inferOperatingSystem({
31
+ platform: process.platform,
32
+ env: process.env,
33
+ ...(procVersion ? { procVersion } : {})
34
+ });
35
+ }
36
+ export async function detectPlatformContext() {
37
+ const os = await detectOperatingSystem();
38
+ const shell = detectShell();
39
+ const serviceManager = await detectServiceManager(os);
40
+ const cwd = process.cwd();
41
+ return {
42
+ os,
43
+ shell,
44
+ serviceManager,
45
+ cwd,
46
+ cwdName: path.basename(cwd) || cwd
47
+ };
48
+ }
49
+ //# sourceMappingURL=detectPlatform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectPlatform.js","sourceRoot":"","sources":["../../src/platform/detectPlatform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAS/C,MAAM,UAAU,oBAAoB,CAClC,OAAoC;IAEpC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,MAAM,GACV,OAAO,CAAC,GAAG,EAAE,eAAe;YAC5B,OAAO,CAAC,GAAG,EAAE,WAAW;YACxB,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAE3D,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IAClC,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACrE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,eAAe,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAEvF,OAAO,oBAAoB,CAAC;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,EAAE,GAAG,MAAM,qBAAqB,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,OAAO;QACL,EAAE;QACF,KAAK;QACL,cAAc;QACd,GAAG;QACH,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG;KACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { OperatingSystem, ServiceManager } from "../types/index.js";
2
+ export declare function commandExists(command: string, envPath?: string | undefined): Promise<boolean>;
3
+ export declare function detectServiceManager(os: OperatingSystem, exists?: (command: string) => Promise<boolean>): Promise<ServiceManager>;
@@ -0,0 +1,38 @@
1
+ import { access } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { constants } from "node:fs";
4
+ export async function commandExists(command, envPath = process.env.PATH) {
5
+ if (!envPath) {
6
+ return false;
7
+ }
8
+ for (const entry of envPath.split(path.delimiter)) {
9
+ const fullPath = path.join(entry, command);
10
+ try {
11
+ await access(fullPath, constants.X_OK);
12
+ return true;
13
+ }
14
+ catch {
15
+ continue;
16
+ }
17
+ }
18
+ return false;
19
+ }
20
+ export async function detectServiceManager(os, exists = commandExists) {
21
+ if (os === "macos") {
22
+ return "launchctl";
23
+ }
24
+ if (os !== "linux" && os !== "wsl" && os !== "unix") {
25
+ return "unknown";
26
+ }
27
+ if (await exists("systemctl")) {
28
+ return "systemctl";
29
+ }
30
+ if (await exists("service")) {
31
+ return "service";
32
+ }
33
+ if (await exists("rc-service")) {
34
+ return "rc-service";
35
+ }
36
+ return "unknown";
37
+ }
38
+ //# sourceMappingURL=detectServiceManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectServiceManager.js","sourceRoot":"","sources":["../../src/platform/detectServiceManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAmB,EACnB,SAAgD,aAAa;IAE7D,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QACpD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ShellType } from "../types/index.js";
2
+ export declare function inferShellType(shellPath: string | undefined): ShellType;
3
+ export declare function detectShell(shellPath?: string | undefined): ShellType;
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ export function inferShellType(shellPath) {
3
+ if (!shellPath) {
4
+ return "unknown";
5
+ }
6
+ const shellName = path.basename(shellPath).toLowerCase();
7
+ if (shellName.includes("zsh")) {
8
+ return "zsh";
9
+ }
10
+ if (shellName.includes("bash")) {
11
+ return "bash";
12
+ }
13
+ if (shellName === "sh" || shellName.endsWith("/sh")) {
14
+ return "sh";
15
+ }
16
+ return "unknown";
17
+ }
18
+ export function detectShell(shellPath = process.env.SHELL) {
19
+ return inferShellType(shellPath);
20
+ }
21
+ //# sourceMappingURL=detectShell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectShell.js","sourceRoot":"","sources":["../../src/platform/detectShell.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,MAAM,UAAU,cAAc,CAAC,SAA6B;IAC1D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAEzD,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK;IACvD,OAAO,cAAc,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { AppConfig, AIProvider } from "../types/index.js";
2
+ export declare function createProvider(config: AppConfig): AIProvider;
@@ -0,0 +1,9 @@
1
+ import { ConfigurationError } from "../utils/errors.js";
2
+ import { OpenAICompatibleProvider } from "./openai.js";
3
+ export function createProvider(config) {
4
+ if (config.provider === "openai") {
5
+ return new OpenAICompatibleProvider(config);
6
+ }
7
+ throw new ConfigurationError(`Unsupported AI provider: ${config.provider}`);
8
+ }
9
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/providers/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,UAAU,cAAc,CAAC,MAAiB;IAC9C,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,IAAI,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,IAAI,kBAAkB,CAAC,4BAA4B,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { AppConfig, GenerateObjectRequest, ProviderTextResponse } from "../types/index.js";
2
+ import type { AIProvider } from "./types.js";
3
+ export declare class OpenAICompatibleProvider implements AIProvider {
4
+ private readonly config;
5
+ readonly name: "openai";
6
+ constructor(config: AppConfig);
7
+ generateObject(input: GenerateObjectRequest): Promise<ProviderTextResponse>;
8
+ }
@@ -0,0 +1,73 @@
1
+ import { ProviderError } from "../utils/errors.js";
2
+ export class OpenAICompatibleProvider {
3
+ config;
4
+ name = "openai";
5
+ constructor(config) {
6
+ this.config = config;
7
+ }
8
+ async generateObject(input) {
9
+ const controller = new AbortController();
10
+ const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
11
+ try {
12
+ const response = await fetch(`${this.config.baseUrl}/chat/completions`, {
13
+ method: "POST",
14
+ headers: {
15
+ Authorization: `Bearer ${this.config.apiKey}`,
16
+ "Content-Type": "application/json"
17
+ },
18
+ body: JSON.stringify({
19
+ model: this.config.model,
20
+ temperature: input.temperature ?? 0.1,
21
+ response_format: {
22
+ type: "json_object"
23
+ },
24
+ messages: [
25
+ {
26
+ role: "system",
27
+ content: input.systemPrompt
28
+ },
29
+ {
30
+ role: "user",
31
+ content: input.userPrompt
32
+ }
33
+ ]
34
+ }),
35
+ signal: controller.signal
36
+ });
37
+ const data = (await response.json());
38
+ if (!response.ok) {
39
+ throw new ProviderError(data.error?.message
40
+ ? `Provider request failed: ${data.error.message}`
41
+ : `Provider request failed with status ${response.status}.`);
42
+ }
43
+ const message = data.choices?.[0]?.message?.content;
44
+ const rawText = Array.isArray(message)
45
+ ? message
46
+ .map((part) => part.text)
47
+ .filter((part) => typeof part === "string")
48
+ .join("")
49
+ : message;
50
+ if (!rawText || rawText.trim().length === 0) {
51
+ throw new ProviderError("Provider returned an empty response.");
52
+ }
53
+ return {
54
+ provider: this.name,
55
+ model: this.config.model,
56
+ rawText
57
+ };
58
+ }
59
+ catch (error) {
60
+ if (error instanceof ProviderError) {
61
+ throw error;
62
+ }
63
+ if (error.name === "AbortError") {
64
+ throw new ProviderError(`Provider request timed out after ${this.config.timeoutMs}ms.`, error);
65
+ }
66
+ throw new ProviderError("Failed to reach AI provider.", error);
67
+ }
68
+ finally {
69
+ clearTimeout(timeout);
70
+ }
71
+ }
72
+ }
73
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export type { AIProvider, GenerateObjectRequest, ProviderTextResponse } from "../types/index.js";
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { RiskLevel } from "../types/index.js";
2
+ export interface RiskAssessment {
3
+ level: RiskLevel;
4
+ reasons: string[];
5
+ }
6
+ export declare function assessCommandRisk(command: string): RiskAssessment;
7
+ export declare function classifyRisk(command: string): RiskLevel;
@@ -0,0 +1,115 @@
1
+ import { parse as parseShellCommand } from "shell-quote";
2
+ import { HIGH_RISK_RULES, MEDIUM_RISK_RULES } from "./dangerousPatterns.js";
3
+ const SAFE_DELETE_TARGETS = new Set([
4
+ "node_modules",
5
+ "./node_modules",
6
+ "dist",
7
+ "./dist",
8
+ "build",
9
+ "./build",
10
+ ".turbo",
11
+ "./.turbo",
12
+ ".next",
13
+ "./.next",
14
+ "coverage",
15
+ "./coverage"
16
+ ]);
17
+ function tokenizeCommand(command) {
18
+ return parseShellCommand(command)
19
+ .filter((part) => typeof part === "string")
20
+ .map((part) => part.trim())
21
+ .filter((part) => part.length > 0);
22
+ }
23
+ function assessRecursiveDelete(command) {
24
+ if (!/\brm\b/i.test(command) || !/-[^\s]*r/i.test(command) || !/-[^\s]*f/i.test(command)) {
25
+ return undefined;
26
+ }
27
+ const rmSegment = command
28
+ .split(/\s*(?:&&|\|\||;|\|)\s*/)
29
+ .find((segment) => /\brm\b/i.test(segment));
30
+ if (!rmSegment) {
31
+ return undefined;
32
+ }
33
+ const tokens = tokenizeCommand(rmSegment);
34
+ const rmIndex = tokens.findIndex((token) => token === "rm" || token.endsWith("/rm"));
35
+ if (rmIndex === -1) {
36
+ return undefined;
37
+ }
38
+ const targets = [];
39
+ for (const token of tokens.slice(rmIndex + 1)) {
40
+ if (token.startsWith("-")) {
41
+ continue;
42
+ }
43
+ targets.push(token);
44
+ }
45
+ if (targets.length === 0) {
46
+ return {
47
+ level: "high",
48
+ reasons: ["This recursive delete command does not clearly scope its targets."]
49
+ };
50
+ }
51
+ if (targets.some((target) => [
52
+ "/",
53
+ "/*",
54
+ "~",
55
+ "~/",
56
+ ".",
57
+ "./",
58
+ "..",
59
+ "../"
60
+ ].includes(target)) ||
61
+ targets.some((target) => target.startsWith("/") || target.startsWith("~")) ||
62
+ targets.some((target) => target.includes("..")) ||
63
+ targets.some((target) => target.includes("*"))) {
64
+ return {
65
+ level: "high",
66
+ reasons: [
67
+ "This command can delete files recursively outside the current project."
68
+ ]
69
+ };
70
+ }
71
+ if (targets.every((target) => SAFE_DELETE_TARGETS.has(target))) {
72
+ return {
73
+ level: "medium",
74
+ reasons: ["This command recursively deletes common project build artifacts."]
75
+ };
76
+ }
77
+ return {
78
+ level: "high",
79
+ reasons: ["This command recursively deletes directories with a broad target scope."]
80
+ };
81
+ }
82
+ export function assessCommandRisk(command) {
83
+ const reasons = [];
84
+ const recursiveDeleteRisk = assessRecursiveDelete(command);
85
+ if (recursiveDeleteRisk?.level === "high") {
86
+ return recursiveDeleteRisk;
87
+ }
88
+ for (const rule of HIGH_RISK_RULES) {
89
+ if (rule.pattern.test(command)) {
90
+ reasons.push(rule.reason);
91
+ }
92
+ }
93
+ if (reasons.length > 0) {
94
+ return {
95
+ level: "high",
96
+ reasons
97
+ };
98
+ }
99
+ if (recursiveDeleteRisk?.level === "medium") {
100
+ reasons.push(...recursiveDeleteRisk.reasons);
101
+ }
102
+ for (const rule of MEDIUM_RISK_RULES) {
103
+ if (rule.pattern.test(command)) {
104
+ reasons.push(rule.reason);
105
+ }
106
+ }
107
+ return {
108
+ level: reasons.length > 0 ? "medium" : "low",
109
+ reasons
110
+ };
111
+ }
112
+ export function classifyRisk(command) {
113
+ return assessCommandRisk(command).level;
114
+ }
115
+ //# sourceMappingURL=classifyRisk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifyRisk.js","sourceRoot":"","sources":["../../src/safety/classifyRisk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { RiskLevel } from "../types/index.js";
2
+ export interface RiskRule {
3
+ risk: RiskLevel;
4
+ pattern: RegExp;
5
+ reason: string;
6
+ }
7
+ export declare const HIGH_RISK_RULES: RiskRule[];
8
+ export declare const MEDIUM_RISK_RULES: RiskRule[];
@@ -0,0 +1,70 @@
1
+ export const HIGH_RISK_RULES = [
2
+ {
3
+ risk: "high",
4
+ pattern: /\b(?:curl|wget)\b[\s\S]*\|\s*(?:sudo\s+)?(?:sh|bash|zsh)\b/i,
5
+ reason: "This command downloads remote content and executes it in a shell."
6
+ },
7
+ {
8
+ risk: "high",
9
+ pattern: /\b(?:dd|mkfs(?:\.\w+)?|fdisk|parted)\b/i,
10
+ reason: "This command can modify or erase disks."
11
+ },
12
+ {
13
+ risk: "high",
14
+ pattern: /\bchmod\s+-R\s+777\s+\//i,
15
+ reason: "This command recursively grants unsafe permissions at the filesystem root."
16
+ },
17
+ {
18
+ risk: "high",
19
+ pattern: /\bgit\s+reset\s+--hard\b/i,
20
+ reason: "This command can permanently discard uncommitted changes."
21
+ },
22
+ {
23
+ risk: "high",
24
+ pattern: /\b(?:apt(?:-get)?|yum|dnf|pacman|apk|zypper)\s+(?:purge|remove|autoremove)\b/i,
25
+ reason: "This command removes system packages and can affect system stability."
26
+ },
27
+ {
28
+ risk: "high",
29
+ pattern: /\b(?:userdel|groupdel|deluser)\b/i,
30
+ reason: "This command removes system accounts."
31
+ }
32
+ ];
33
+ export const MEDIUM_RISK_RULES = [
34
+ {
35
+ risk: "medium",
36
+ pattern: /\b(?:systemctl|service|rc-service)\s+(?:restart|stop)\b/i,
37
+ reason: "This command changes the state of a system service."
38
+ },
39
+ {
40
+ risk: "medium",
41
+ pattern: /\b(?:launchctl\s+(?:stop|kickstart)|brew\s+services\s+(?:stop|restart))\b/i,
42
+ reason: "This command changes the state of a macOS service."
43
+ },
44
+ {
45
+ risk: "medium",
46
+ pattern: /\b(?:npm|pnpm|yarn|bun)\s+(?:install|add|update|upgrade|remove|uninstall)\b/i,
47
+ reason: "This command changes project dependencies."
48
+ },
49
+ {
50
+ risk: "medium",
51
+ pattern: /\bdocker\s+compose\s+down\b/i,
52
+ reason: "This command stops and removes running containers."
53
+ },
54
+ {
55
+ risk: "medium",
56
+ pattern: /\b(?:kill|killall|pkill)\b/i,
57
+ reason: "This command stops running processes."
58
+ },
59
+ {
60
+ risk: "medium",
61
+ pattern: /\b(?:reboot|shutdown)\b/i,
62
+ reason: "This command disrupts the current system session."
63
+ },
64
+ {
65
+ risk: "medium",
66
+ pattern: /\bgit\s+clean\s+-f/i,
67
+ reason: "This command removes untracked files from the repository."
68
+ }
69
+ ];
70
+ //# sourceMappingURL=dangerousPatterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dangerousPatterns.js","sourceRoot":"","sources":["../../src/safety/dangerousPatterns.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,6DAA6D;QACtE,MAAM,EAAE,mEAAmE;KAC5E;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,yCAAyC;QAClD,MAAM,EAAE,yCAAyC;KAClD;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,4EAA4E;KACrF;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,2BAA2B;QACpC,MAAM,EAAE,2DAA2D;KACpE;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EACL,+EAA+E;QACjF,MAAM,EAAE,uEAAuE;KAChF;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,mCAAmC;QAC5C,MAAM,EAAE,uCAAuC;KAChD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,0DAA0D;QACnE,MAAM,EAAE,qDAAqD;KAC9D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,4EAA4E;QACrF,MAAM,EAAE,oDAAoD;KAC7D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,8EAA8E;QACvF,MAAM,EAAE,4CAA4C;KACrD;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,8BAA8B;QACvC,MAAM,EAAE,oDAAoD;KAC7D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,6BAA6B;QACtC,MAAM,EAAE,uCAAuC;KAChD;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,mDAAmD;KAC5D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,2DAA2D;KACpE;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { PromptAdapter, RiskLevel } from "../types/index.js";
2
+ export declare const HIGH_RISK_CONFIRMATION = "EXECUTE HIGH RISK COMMAND";
3
+ export declare function enforceExecutionPolicy(options: {
4
+ command: string;
5
+ risk: RiskLevel;
6
+ yes: boolean;
7
+ prompt: PromptAdapter;
8
+ reason?: string;
9
+ }): Promise<void>;
@@ -0,0 +1,21 @@
1
+ import { ExecutionPolicyError, UserCancelledError } from "../utils/errors.js";
2
+ export const HIGH_RISK_CONFIRMATION = "EXECUTE HIGH RISK COMMAND";
3
+ export async function enforceExecutionPolicy(options) {
4
+ const riskLabel = options.risk.toUpperCase();
5
+ if (options.risk === "high") {
6
+ const detail = options.reason ?? "This command can make destructive system or filesystem changes.";
7
+ const confirmation = await options.prompt.text(`Risk: ${riskLabel}\n${detail}\nType ${HIGH_RISK_CONFIRMATION} to continue:`);
8
+ if (confirmation.trim() !== HIGH_RISK_CONFIRMATION) {
9
+ throw new ExecutionPolicyError("High-risk command confirmation was not accepted.");
10
+ }
11
+ return;
12
+ }
13
+ if (options.yes) {
14
+ return;
15
+ }
16
+ const confirmed = await options.prompt.confirm(`Execute this ${options.risk}-risk command?\n${options.command}`, false);
17
+ if (!confirmed) {
18
+ throw new UserCancelledError("Command execution cancelled.");
19
+ }
20
+ }
21
+ //# sourceMappingURL=executionPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executionPolicy.js","sourceRoot":"","sources":["../../src/safety/executionPolicy.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,sBAAsB,GAAG,2BAA2B,CAAC;AAElE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAM5C;IACC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAE7C,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,IAAI,iEAAiE,CAAC;QACtF,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAC5C,SAAS,SAAS,KAAK,MAAM,UAAU,sBAAsB,eAAe,CAC7E,CAAC;QAEF,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,sBAAsB,EAAE,CAAC;YACnD,MAAM,IAAI,oBAAoB,CAAC,kDAAkD,CAAC,CAAC;QACrF,CAAC;QAED,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAC5C,gBAAgB,OAAO,CAAC,IAAI,mBAAmB,OAAO,CAAC,OAAO,EAAE,EAChE,KAAK,CACN,CAAC;IAEF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAAC,8BAA8B,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}