ai-ask 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.
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/dist/cli/commands.d.ts +13 -0
- package/dist/cli/commands.js +221 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/prompts.d.ts +2 -0
- package/dist/cli/prompts.js +32 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/cli/repl.d.ts +9 -0
- package/dist/cli/repl.js +166 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/config/env.d.ts +2 -0
- package/dist/config/env.js +8 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/userConfig.d.ts +10 -0
- package/dist/config/userConfig.js +91 -0
- package/dist/config/userConfig.js.map +1 -0
- package/dist/core/explainCommand.d.ts +2 -0
- package/dist/core/explainCommand.js +4 -0
- package/dist/core/explainCommand.js.map +1 -0
- package/dist/core/generateCommand.d.ts +2 -0
- package/dist/core/generateCommand.js +29 -0
- package/dist/core/generateCommand.js.map +1 -0
- package/dist/core/output.d.ts +4 -0
- package/dist/core/output.js +67 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/prompts.d.ts +7 -0
- package/dist/core/prompts.js +71 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/response.d.ts +19 -0
- package/dist/core/response.js +44 -0
- package/dist/core/response.js.map +1 -0
- package/dist/core/session.d.ts +9 -0
- package/dist/core/session.js +23 -0
- package/dist/core/session.js.map +1 -0
- package/dist/exec/runCommand.d.ts +11 -0
- package/dist/exec/runCommand.js +57 -0
- package/dist/exec/runCommand.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/platform/detectPlatform.d.ts +9 -0
- package/dist/platform/detectPlatform.js +49 -0
- package/dist/platform/detectPlatform.js.map +1 -0
- package/dist/platform/detectServiceManager.d.ts +3 -0
- package/dist/platform/detectServiceManager.js +38 -0
- package/dist/platform/detectServiceManager.js.map +1 -0
- package/dist/platform/detectShell.d.ts +3 -0
- package/dist/platform/detectShell.js +21 -0
- package/dist/platform/detectShell.js.map +1 -0
- package/dist/providers/factory.d.ts +2 -0
- package/dist/providers/factory.js +9 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/openai.d.ts +8 -0
- package/dist/providers/openai.js +73 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/safety/classifyRisk.d.ts +7 -0
- package/dist/safety/classifyRisk.js +115 -0
- package/dist/safety/classifyRisk.js.map +1 -0
- package/dist/safety/dangerousPatterns.d.ts +8 -0
- package/dist/safety/dangerousPatterns.js +70 -0
- package/dist/safety/dangerousPatterns.js.map +1 -0
- package/dist/safety/executionPolicy.d.ts +9 -0
- package/dist/safety/executionPolicy.js +21 -0
- package/dist/safety/executionPolicy.js.map +1 -0
- package/dist/types/index.d.ts +79 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/branding.d.ts +6 -0
- package/dist/utils/branding.js +11 -0
- package/dist/utils/branding.js.map +1 -0
- package/dist/utils/errors.d.ts +26 -0
- package/dist/utils/errors.js +59 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +14 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/strings.d.ts +5 -0
- package/dist/utils/strings.js +30 -0
- package/dist/utils/strings.js.map +1 -0
- package/package.json +69 -0
package/dist/cli/repl.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import clipboardy from "clipboardy";
|
|
2
|
+
import readline from "node:readline/promises";
|
|
3
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
4
|
+
import { formatExplanationOnly, formatReplHelp, formatSuggestion } from "../core/output.js";
|
|
5
|
+
import { InMemorySession } from "../core/session.js";
|
|
6
|
+
import { generateCommand } from "../core/generateCommand.js";
|
|
7
|
+
import { assessCommandRisk } from "../safety/classifyRisk.js";
|
|
8
|
+
import { enforceExecutionPolicy } from "../safety/executionPolicy.js";
|
|
9
|
+
import { runCommand } from "../exec/runCommand.js";
|
|
10
|
+
import { ClipboardError, ExecutionPolicyError, UserCancelledError, getErrorMessage } from "../utils/errors.js";
|
|
11
|
+
import { formatReplBanner } from "../utils/branding.js";
|
|
12
|
+
function resolveReplCommand(inputValue) {
|
|
13
|
+
const normalized = inputValue.trim().toLowerCase();
|
|
14
|
+
if (normalized === "help") {
|
|
15
|
+
return "help";
|
|
16
|
+
}
|
|
17
|
+
if (normalized === "last") {
|
|
18
|
+
return "last";
|
|
19
|
+
}
|
|
20
|
+
if (normalized.startsWith("explain")) {
|
|
21
|
+
return "explain";
|
|
22
|
+
}
|
|
23
|
+
if (normalized.startsWith("run")) {
|
|
24
|
+
return "run";
|
|
25
|
+
}
|
|
26
|
+
if (normalized === "copy") {
|
|
27
|
+
return "copy";
|
|
28
|
+
}
|
|
29
|
+
if (normalized === "clear") {
|
|
30
|
+
return "clear";
|
|
31
|
+
}
|
|
32
|
+
if (normalized === "exit" || normalized === "quit") {
|
|
33
|
+
return "exit";
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
async function copyCommand(command) {
|
|
38
|
+
try {
|
|
39
|
+
await clipboardy.write(command);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new ClipboardError("Clipboard unavailable. Command printed below instead.", error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function startRepl(options) {
|
|
46
|
+
const session = new InMemorySession();
|
|
47
|
+
const rl = readline.createInterface({ input, output, terminal: true });
|
|
48
|
+
const handleSigint = () => {
|
|
49
|
+
output.write("\n");
|
|
50
|
+
rl.close();
|
|
51
|
+
};
|
|
52
|
+
process.once("SIGINT", handleSigint);
|
|
53
|
+
try {
|
|
54
|
+
output.write(`${formatReplBanner()}\nInteractive mode. Type help for commands.\n`);
|
|
55
|
+
while (true) {
|
|
56
|
+
let line;
|
|
57
|
+
try {
|
|
58
|
+
line = await rl.question("ai-cmd > ");
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
const inputValue = line.trim();
|
|
64
|
+
if (inputValue.length === 0) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const replCommand = resolveReplCommand(inputValue);
|
|
68
|
+
const lastSuggestion = session.getLastSuggestion();
|
|
69
|
+
if (replCommand === "exit") {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (replCommand === "help") {
|
|
73
|
+
output.write(`${formatReplHelp(options.color)}\n`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
if (replCommand === "clear") {
|
|
78
|
+
session.clear();
|
|
79
|
+
output.write("Session cleared.\n");
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (replCommand && !lastSuggestion) {
|
|
83
|
+
output.write("No command in session yet. Ask a question first.\n");
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (replCommand === "last" && lastSuggestion) {
|
|
87
|
+
output.write(`${formatSuggestion(lastSuggestion, {
|
|
88
|
+
color: options.color,
|
|
89
|
+
explain: true,
|
|
90
|
+
json: false
|
|
91
|
+
})}\n`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (replCommand === "explain" && lastSuggestion) {
|
|
95
|
+
output.write(`${formatExplanationOnly(lastSuggestion, options.color)}\n`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (replCommand === "copy" && lastSuggestion) {
|
|
99
|
+
try {
|
|
100
|
+
await copyCommand(lastSuggestion.command);
|
|
101
|
+
output.write("Command copied to clipboard.\n");
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error instanceof ClipboardError) {
|
|
105
|
+
output.write(`${error.message}\n${lastSuggestion.command}\n`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (replCommand === "run" && lastSuggestion) {
|
|
113
|
+
if (options.platform.os === "unsupported") {
|
|
114
|
+
output.write("Execution is disabled on unsupported host OSes. Use a Unix-like shell or WSL.\n");
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const assessment = assessCommandRisk(lastSuggestion.command);
|
|
118
|
+
output.write(`${formatSuggestion(lastSuggestion, {
|
|
119
|
+
color: options.color,
|
|
120
|
+
explain: true,
|
|
121
|
+
json: false
|
|
122
|
+
})}\n`);
|
|
123
|
+
await enforceExecutionPolicy({
|
|
124
|
+
command: lastSuggestion.command,
|
|
125
|
+
risk: assessment.level,
|
|
126
|
+
yes: false,
|
|
127
|
+
prompt: options.prompt,
|
|
128
|
+
...(assessment.reasons[0] ? { reason: assessment.reasons[0] } : {})
|
|
129
|
+
});
|
|
130
|
+
await runCommand(lastSuggestion.command, {
|
|
131
|
+
cwd: options.platform.cwd,
|
|
132
|
+
stdio: "inherit"
|
|
133
|
+
});
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const suggestion = await generateCommand({
|
|
137
|
+
question: inputValue,
|
|
138
|
+
platform: options.platform,
|
|
139
|
+
provider: options.provider,
|
|
140
|
+
explainRequested: true,
|
|
141
|
+
history: session.getHistory()
|
|
142
|
+
});
|
|
143
|
+
session.remember(inputValue, suggestion);
|
|
144
|
+
options.logger.debug("Generated command suggestion", suggestion);
|
|
145
|
+
output.write(`${formatSuggestion(suggestion, {
|
|
146
|
+
color: options.color,
|
|
147
|
+
explain: true,
|
|
148
|
+
json: false
|
|
149
|
+
})}\n`);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error instanceof UserCancelledError ||
|
|
153
|
+
error instanceof ExecutionPolicyError) {
|
|
154
|
+
output.write(`${error.message}\n`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
output.write(`${getErrorMessage(error)}\n`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
process.removeListener("SIGINT", handleSigint);
|
|
163
|
+
rl.close();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=repl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/cli/repl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const DEFAULT_CONFIG_PATH = path.join(homedir(), ".ai-cmd", "config.json");
|
|
4
|
+
export function getEnvValue(env, key) {
|
|
5
|
+
const value = env[key];
|
|
6
|
+
return value && value.trim().length > 0 ? value.trim() : undefined;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAC1C,OAAO,EAAE,EACT,SAAS,EACT,aAAa,CACd,CAAC;AAEF,MAAM,UAAU,WAAW,CACzB,GAAsB,EACtB,GAAW;IAEX,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AppConfig } from "../types/index.js";
|
|
2
|
+
export type LoadConfigOptions = {
|
|
3
|
+
env?: NodeJS.ProcessEnv;
|
|
4
|
+
configPath?: string;
|
|
5
|
+
readConfigFile?: (configPath: string) => Promise<string>;
|
|
6
|
+
ensureConfigScaffold?: (configPath: string) => Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
export declare function ensureDefaultConfigScaffold(configPath: string): Promise<void>;
|
|
9
|
+
export declare function loadUserConfig(configPath?: string, readConfigFile?: (configPath: string) => Promise<string>): Promise<Partial<AppConfig>>;
|
|
10
|
+
export declare function loadConfig(options?: LoadConfigOptions): Promise<AppConfig>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { DEFAULT_CONFIG_PATH, getEnvValue } from "./env.js";
|
|
5
|
+
import { ConfigurationError } from "../utils/errors.js";
|
|
6
|
+
const partialConfigSchema = z.object({
|
|
7
|
+
provider: z.literal("openai").optional(),
|
|
8
|
+
model: z.string().min(1).optional(),
|
|
9
|
+
apiKey: z.string().min(1).optional(),
|
|
10
|
+
baseUrl: z.string().url().optional(),
|
|
11
|
+
timeoutMs: z.number().int().positive().optional()
|
|
12
|
+
});
|
|
13
|
+
const finalConfigSchema = z.object({
|
|
14
|
+
provider: z.literal("openai").default("openai"),
|
|
15
|
+
model: z.string().min(1).default("gpt-4.1-mini"),
|
|
16
|
+
apiKey: z.string().min(1),
|
|
17
|
+
baseUrl: z.string().url().default("https://api.openai.com/v1"),
|
|
18
|
+
timeoutMs: z.number().int().positive().default(30_000)
|
|
19
|
+
});
|
|
20
|
+
const DEFAULT_CONFIG_TEMPLATE = {
|
|
21
|
+
provider: "openai",
|
|
22
|
+
model: "gpt-5.4-mini",
|
|
23
|
+
apiKey: "your-api-key-here",
|
|
24
|
+
baseUrl: "https://api.openai.com/v1",
|
|
25
|
+
timeoutMs: 30_000
|
|
26
|
+
};
|
|
27
|
+
export async function ensureDefaultConfigScaffold(configPath) {
|
|
28
|
+
await mkdir(path.dirname(configPath), { recursive: true });
|
|
29
|
+
try {
|
|
30
|
+
await writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG_TEMPLATE, null, 2)}\n`, {
|
|
31
|
+
flag: "wx"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error.code === "EEXIST") {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
throw new ConfigurationError(`Failed to create ${configPath}.`, error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function loadUserConfig(configPath = DEFAULT_CONFIG_PATH, readConfigFile = (inputPath) => readFile(inputPath, "utf8")) {
|
|
42
|
+
try {
|
|
43
|
+
const rawConfig = await readConfigFile(configPath);
|
|
44
|
+
const parsed = JSON.parse(rawConfig);
|
|
45
|
+
const validated = partialConfigSchema.parse(parsed);
|
|
46
|
+
return {
|
|
47
|
+
...(validated.provider ? { provider: validated.provider } : {}),
|
|
48
|
+
...(validated.model ? { model: validated.model } : {}),
|
|
49
|
+
...(validated.apiKey ? { apiKey: validated.apiKey } : {}),
|
|
50
|
+
...(validated.baseUrl ? { baseUrl: validated.baseUrl } : {}),
|
|
51
|
+
...(validated.timeoutMs ? { timeoutMs: validated.timeoutMs } : {})
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error?.code === "ENOENT") {
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
if (error instanceof SyntaxError) {
|
|
59
|
+
throw new ConfigurationError(`Failed to parse ${configPath}: invalid JSON.`, error);
|
|
60
|
+
}
|
|
61
|
+
if (error instanceof z.ZodError) {
|
|
62
|
+
throw new ConfigurationError(`Invalid configuration in ${configPath}.`, error.flatten());
|
|
63
|
+
}
|
|
64
|
+
throw new ConfigurationError(`Failed to read ${configPath}.`, error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export async function loadConfig(options = {}) {
|
|
68
|
+
const env = options.env ?? process.env;
|
|
69
|
+
const configPath = options.configPath ?? DEFAULT_CONFIG_PATH;
|
|
70
|
+
const ensureConfigScaffold = options.ensureConfigScaffold ?? ensureDefaultConfigScaffold;
|
|
71
|
+
const fileConfig = await loadUserConfig(configPath, options.readConfigFile);
|
|
72
|
+
const merged = {
|
|
73
|
+
provider: getEnvValue(env, "AI_PROVIDER") ?? fileConfig.provider ?? "openai",
|
|
74
|
+
model: getEnvValue(env, "AI_MODEL") ?? fileConfig.model ?? "gpt-4.1-mini",
|
|
75
|
+
apiKey: getEnvValue(env, "AI_API_KEY") ?? fileConfig.apiKey,
|
|
76
|
+
baseUrl: getEnvValue(env, "AI_BASE_URL") ??
|
|
77
|
+
fileConfig.baseUrl ??
|
|
78
|
+
"https://api.openai.com/v1",
|
|
79
|
+
timeoutMs: Number.parseInt(getEnvValue(env, "AI_TIMEOUT_MS") ?? String(fileConfig.timeoutMs ?? 30_000), 10) || 30_000
|
|
80
|
+
};
|
|
81
|
+
const parsed = finalConfigSchema.safeParse(merged);
|
|
82
|
+
if (!parsed.success) {
|
|
83
|
+
if (!merged.apiKey) {
|
|
84
|
+
await ensureConfigScaffold(configPath);
|
|
85
|
+
throw new ConfigurationError(`Missing AI_API_KEY. Set it in your environment or edit ${configPath}. A starter config has been created if it did not already exist.`);
|
|
86
|
+
}
|
|
87
|
+
throw new ConfigurationError("Invalid AI configuration.", parsed.error.flatten());
|
|
88
|
+
}
|
|
89
|
+
return parsed.data;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=userConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userConfig.js","sourceRoot":"","sources":["../../src/config/userConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainCommand.js","sourceRoot":"","sources":["../../src/core/explainCommand.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,UAA6B;IAC1D,OAAO,UAAU,CAAC,WAAW,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { buildGenerateObjectRequest } from "./prompts.js";
|
|
2
|
+
import { parseProviderPayload } from "./response.js";
|
|
3
|
+
import { classifyRisk } from "../safety/classifyRisk.js";
|
|
4
|
+
export async function generateCommand(options) {
|
|
5
|
+
const request = buildGenerateObjectRequest({
|
|
6
|
+
question: options.question,
|
|
7
|
+
platform: options.platform,
|
|
8
|
+
explainRequested: options.explainRequested ?? true,
|
|
9
|
+
history: options.history ?? []
|
|
10
|
+
});
|
|
11
|
+
const response = await options.provider.generateObject(request);
|
|
12
|
+
const payload = parseProviderPayload(response.rawText);
|
|
13
|
+
const platformNotes = [
|
|
14
|
+
...(payload.platformNotes ?? []),
|
|
15
|
+
...(options.platform.os === "unsupported"
|
|
16
|
+
? ["Detected unsupported host OS; generated a best-effort Unix-style command."]
|
|
17
|
+
: [])
|
|
18
|
+
];
|
|
19
|
+
return {
|
|
20
|
+
question: options.question,
|
|
21
|
+
command: payload.command,
|
|
22
|
+
explanation: payload.explanation,
|
|
23
|
+
risk: classifyRisk(payload.command),
|
|
24
|
+
platform: options.platform,
|
|
25
|
+
...(platformNotes.length > 0 ? { platformNotes } : {}),
|
|
26
|
+
...(payload.assumptions ? { assumptions: payload.assumptions } : {})
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=generateCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateCommand.js","sourceRoot":"","sources":["../../src/core/generateCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAMzD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+B;IAE/B,MAAM,OAAO,GAAG,0BAA0B,CAAC;QACzC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,IAAI;QAClD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;KAC/B,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG;QACpB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;QAChC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,aAAa;YACvC,CAAC,CAAC,CAAC,2EAA2E,CAAC;YAC/E,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;QACnC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,GAAG,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CommandSuggestion, OutputOptions } from "../types/index.js";
|
|
2
|
+
export declare function formatSuggestion(suggestion: CommandSuggestion, options: OutputOptions): string;
|
|
3
|
+
export declare function formatExplanationOnly(suggestion: CommandSuggestion, color: boolean): string;
|
|
4
|
+
export declare function formatReplHelp(color: boolean): string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Chalk } from "chalk";
|
|
2
|
+
function createPalette(color) {
|
|
3
|
+
return new Chalk({ level: color ? 1 : 0 });
|
|
4
|
+
}
|
|
5
|
+
function colorizeRisk(chalk, risk) {
|
|
6
|
+
if (risk === "high") {
|
|
7
|
+
return chalk.red(risk);
|
|
8
|
+
}
|
|
9
|
+
if (risk === "medium") {
|
|
10
|
+
return chalk.yellow(risk);
|
|
11
|
+
}
|
|
12
|
+
return chalk.green(risk);
|
|
13
|
+
}
|
|
14
|
+
export function formatSuggestion(suggestion, options) {
|
|
15
|
+
if (options.json) {
|
|
16
|
+
return JSON.stringify({
|
|
17
|
+
question: suggestion.question,
|
|
18
|
+
command: suggestion.command,
|
|
19
|
+
explanation: suggestion.explanation,
|
|
20
|
+
risk: suggestion.risk,
|
|
21
|
+
platformNotes: suggestion.platformNotes,
|
|
22
|
+
assumptions: suggestion.assumptions,
|
|
23
|
+
platform: suggestion.platform
|
|
24
|
+
}, null, 2);
|
|
25
|
+
}
|
|
26
|
+
const chalk = createPalette(options.color);
|
|
27
|
+
const lines = [
|
|
28
|
+
chalk.bold("Command"),
|
|
29
|
+
chalk.cyan(suggestion.command)
|
|
30
|
+
];
|
|
31
|
+
if (options.explain) {
|
|
32
|
+
lines.push("", chalk.bold("Explanation"), suggestion.explanation, "");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
lines.push("");
|
|
36
|
+
}
|
|
37
|
+
lines.push(`${chalk.bold("Risk")} ${colorizeRisk(chalk, suggestion.risk)}`);
|
|
38
|
+
if (suggestion.assumptions && suggestion.assumptions.length > 0) {
|
|
39
|
+
lines.push("", chalk.bold("Assumptions"), ...suggestion.assumptions.map((item) => `- ${item}`));
|
|
40
|
+
}
|
|
41
|
+
if (suggestion.platformNotes && suggestion.platformNotes.length > 0) {
|
|
42
|
+
lines.push("", chalk.bold("Platform Notes"), ...suggestion.platformNotes.map((item) => `- ${item}`));
|
|
43
|
+
}
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|
|
46
|
+
export function formatExplanationOnly(suggestion, color) {
|
|
47
|
+
const chalk = createPalette(color);
|
|
48
|
+
const lines = [chalk.bold("Explanation"), suggestion.explanation];
|
|
49
|
+
if (suggestion.assumptions && suggestion.assumptions.length > 0) {
|
|
50
|
+
lines.push("", chalk.bold("Assumptions"), ...suggestion.assumptions.map((item) => `- ${item}`));
|
|
51
|
+
}
|
|
52
|
+
return lines.join("\n");
|
|
53
|
+
}
|
|
54
|
+
export function formatReplHelp(color) {
|
|
55
|
+
const chalk = createPalette(color);
|
|
56
|
+
return [
|
|
57
|
+
chalk.bold("Commands"),
|
|
58
|
+
"help Show this help",
|
|
59
|
+
"last Show the last suggested command",
|
|
60
|
+
"explain Show the explanation for the last command",
|
|
61
|
+
"run Execute the last command with confirmation",
|
|
62
|
+
"copy Copy the last command to the clipboard",
|
|
63
|
+
"clear Clear session memory",
|
|
64
|
+
"exit Leave ai-cmd"
|
|
65
|
+
].join("\n");
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/core/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAI9B,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY,CAAC,KAAuC,EAAE,IAAe;IAC5E,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,UAA6B,EAC7B,OAAsB;IAEtB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,aAAa,EAAE,UAAU,CAAC,aAAa;YACvC,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,QAAQ,EAAE,UAAU,CAAC,QAAQ;SAC9B,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG;QACZ,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;KAC/B,CAAC;IAEF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAI,CACR,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAChE,CAAC;IAEF,IAAI,UAAU,CAAC,WAAW,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,IAAI,UAAU,CAAC,aAAa,IAAI,UAAU,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpE,KAAK,CAAC,IAAI,CACR,EAAE,EACF,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAC5B,GAAG,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CACvD,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,UAA6B,EAC7B,KAAc;IAEd,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAElE,IAAI,UAAU,CAAC,WAAW,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEnC,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;QACtB,0BAA0B;QAC1B,2CAA2C;QAC3C,qDAAqD;QACrD,sDAAsD;QACtD,kDAAkD;QAClD,gCAAgC;QAChC,wBAAwB;KACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConversationTurn, GenerateObjectRequest, PlatformContext } from "../types/index.js";
|
|
2
|
+
export declare function buildGenerateObjectRequest(options: {
|
|
3
|
+
question: string;
|
|
4
|
+
platform: PlatformContext;
|
|
5
|
+
explainRequested: boolean;
|
|
6
|
+
history: ConversationTurn[];
|
|
7
|
+
}): GenerateObjectRequest;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export function buildGenerateObjectRequest(options) {
|
|
2
|
+
const schema = {
|
|
3
|
+
type: "object",
|
|
4
|
+
additionalProperties: false,
|
|
5
|
+
required: ["command", "explanation"],
|
|
6
|
+
properties: {
|
|
7
|
+
command: {
|
|
8
|
+
type: "string",
|
|
9
|
+
description: "Exactly one best shell command on a single line. Use operators like && only when required."
|
|
10
|
+
},
|
|
11
|
+
explanation: {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "A short practical explanation of what the command does."
|
|
14
|
+
},
|
|
15
|
+
platformNotes: {
|
|
16
|
+
type: "array",
|
|
17
|
+
items: { type: "string" }
|
|
18
|
+
},
|
|
19
|
+
assumptions: {
|
|
20
|
+
type: "array",
|
|
21
|
+
items: { type: "string" }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const systemPrompt = [
|
|
26
|
+
"You are ai-cmd, a shell command assistant for Unix-like environments.",
|
|
27
|
+
"Return exactly one best command for the user's current environment.",
|
|
28
|
+
"Prefer standard native tools over obscure alternatives.",
|
|
29
|
+
"Do not invent commands, package names, or service names.",
|
|
30
|
+
"Tailor the command to the detected OS, shell, and service manager.",
|
|
31
|
+
"If the environment is uncertain, make the safest reasonable assumption and state it in assumptions.",
|
|
32
|
+
"Keep explanations concise and practical.",
|
|
33
|
+
"Return valid JSON only. Do not include markdown fences or prose outside the JSON object."
|
|
34
|
+
].join(" ");
|
|
35
|
+
const historyBlock = options.history.length === 0
|
|
36
|
+
? "No previous conversation context."
|
|
37
|
+
: JSON.stringify(options.history.slice(-4), null, 2);
|
|
38
|
+
const userPrompt = [
|
|
39
|
+
"Environment context:",
|
|
40
|
+
JSON.stringify({
|
|
41
|
+
os: options.platform.os,
|
|
42
|
+
shell: options.platform.shell,
|
|
43
|
+
serviceManager: options.platform.serviceManager,
|
|
44
|
+
cwdName: options.platform.cwdName
|
|
45
|
+
}, null, 2),
|
|
46
|
+
"",
|
|
47
|
+
"Conversation context:",
|
|
48
|
+
historyBlock,
|
|
49
|
+
"",
|
|
50
|
+
`Explain output requested: ${options.explainRequested ? "yes" : "no"}`,
|
|
51
|
+
`User question: ${options.question}`,
|
|
52
|
+
"",
|
|
53
|
+
"Response schema:",
|
|
54
|
+
JSON.stringify(schema, null, 2),
|
|
55
|
+
"",
|
|
56
|
+
"Rules:",
|
|
57
|
+
"- command must be a single string on one line",
|
|
58
|
+
"- do not return multiple alternatives",
|
|
59
|
+
"- use assumptions only when needed",
|
|
60
|
+
"- use platformNotes for short platform-specific caveats"
|
|
61
|
+
].join("\n");
|
|
62
|
+
return {
|
|
63
|
+
systemPrompt,
|
|
64
|
+
userPrompt,
|
|
65
|
+
schemaName: "command_suggestion",
|
|
66
|
+
schemaDescription: "A single shell command suggestion for the current environment.",
|
|
67
|
+
jsonSchema: schema,
|
|
68
|
+
temperature: 0.1
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/core/prompts.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,0BAA0B,CAAC,OAK1C;IACC,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;QACpC,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,4FAA4F;aAC/F;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yDAAyD;aACvE;YACD,aAAa,EAAE;gBACb,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aAC1B;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aAC1B;SACF;KACgC,CAAC;IAEpC,MAAM,YAAY,GAAG;QACnB,uEAAuE;QACvE,qEAAqE;QACrE,yDAAyD;QACzD,0DAA0D;QAC1D,oEAAoE;QACpE,qGAAqG;QACrG,0CAA0C;QAC1C,0FAA0F;KAC3F,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,YAAY,GAChB,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAC1B,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEzD,MAAM,UAAU,GAAG;QACjB,sBAAsB;QACtB,IAAI,CAAC,SAAS,CACZ;YACE,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE;YACvB,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK;YAC7B,cAAc,EAAE,OAAO,CAAC,QAAQ,CAAC,cAAc;YAC/C,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO;SAClC,EACD,IAAI,EACJ,CAAC,CACF;QACD,EAAE;QACF,uBAAuB;QACvB,YAAY;QACZ,EAAE;QACF,6BAA6B,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;QACtE,kBAAkB,OAAO,CAAC,QAAQ,EAAE;QACpC,EAAE;QACF,kBAAkB;QAClB,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,EAAE;QACF,QAAQ;QACR,+CAA+C;QAC/C,uCAAuC;QACvC,oCAAoC;QACpC,yDAAyD;KAC1D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;QACL,YAAY;QACZ,UAAU;QACV,UAAU,EAAE,oBAAoB;QAChC,iBAAiB,EAAE,gEAAgE;QACnF,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,GAAG;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ProviderCommandPayload } from "../types/index.js";
|
|
3
|
+
export declare const providerCommandSchema: z.ZodObject<{
|
|
4
|
+
command: z.ZodString;
|
|
5
|
+
explanation: z.ZodString;
|
|
6
|
+
platformNotes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
7
|
+
assumptions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
command: string;
|
|
10
|
+
explanation: string;
|
|
11
|
+
platformNotes?: string[] | undefined;
|
|
12
|
+
assumptions?: string[] | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
command: string;
|
|
15
|
+
explanation: string;
|
|
16
|
+
platformNotes?: string[] | undefined;
|
|
17
|
+
assumptions?: string[] | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function parseProviderPayload(rawText: string): ProviderCommandPayload;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsonrepair } from "jsonrepair";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { extractFirstJsonObject, hasMultipleCommandLines, normalizeOptionalList, normalizeText, stripMarkdownCodeFence } from "../utils/strings.js";
|
|
4
|
+
import { ResponseValidationError } from "../utils/errors.js";
|
|
5
|
+
export const providerCommandSchema = z.object({
|
|
6
|
+
command: z.string().min(1),
|
|
7
|
+
explanation: z.string().min(1),
|
|
8
|
+
platformNotes: z.array(z.string().min(1)).optional(),
|
|
9
|
+
assumptions: z.array(z.string().min(1)).optional()
|
|
10
|
+
});
|
|
11
|
+
function parseJson(rawText) {
|
|
12
|
+
const stripped = stripMarkdownCodeFence(rawText);
|
|
13
|
+
const candidate = extractFirstJsonObject(stripped);
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(candidate);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(jsonrepair(candidate));
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new ResponseValidationError("Failed to generate command: provider returned invalid JSON.", error);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function parseProviderPayload(rawText) {
|
|
27
|
+
const parsed = providerCommandSchema.safeParse(parseJson(rawText));
|
|
28
|
+
if (!parsed.success) {
|
|
29
|
+
throw new ResponseValidationError("Failed to generate command: provider response did not match the expected schema.", parsed.error.flatten());
|
|
30
|
+
}
|
|
31
|
+
const platformNotes = normalizeOptionalList(parsed.data.platformNotes);
|
|
32
|
+
const assumptions = normalizeOptionalList(parsed.data.assumptions);
|
|
33
|
+
const payload = {
|
|
34
|
+
command: parsed.data.command.trim(),
|
|
35
|
+
explanation: normalizeText(parsed.data.explanation),
|
|
36
|
+
...(platformNotes ? { platformNotes } : {}),
|
|
37
|
+
...(assumptions ? { assumptions } : {})
|
|
38
|
+
};
|
|
39
|
+
if (hasMultipleCommandLines(payload.command)) {
|
|
40
|
+
throw new ResponseValidationError("Failed to generate command: provider returned multiple commands instead of one.");
|
|
41
|
+
}
|
|
42
|
+
return payload;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpD,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACnD,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,OAAe;IAChC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAY,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAY,CAAC;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,uBAAuB,CAC/B,6DAA6D,EAC7D,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,uBAAuB,CAC/B,kFAAkF,EAClF,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CACvB,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAEnE,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;QACnC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;QACnD,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACP,CAAC;IAEnC,IAAI,uBAAuB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,uBAAuB,CAC/B,iFAAiF,CAClF,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CommandSuggestion, ConversationTurn } from "../types/index.js";
|
|
2
|
+
export declare class InMemorySession {
|
|
3
|
+
private history;
|
|
4
|
+
private lastSuggestion;
|
|
5
|
+
remember(question: string, suggestion: CommandSuggestion): void;
|
|
6
|
+
getHistory(limit?: number): ConversationTurn[];
|
|
7
|
+
getLastSuggestion(): CommandSuggestion | undefined;
|
|
8
|
+
clear(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class InMemorySession {
|
|
2
|
+
history = [];
|
|
3
|
+
lastSuggestion;
|
|
4
|
+
remember(question, suggestion) {
|
|
5
|
+
this.lastSuggestion = suggestion;
|
|
6
|
+
this.history.push({
|
|
7
|
+
question,
|
|
8
|
+
command: suggestion.command,
|
|
9
|
+
explanation: suggestion.explanation
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
getHistory(limit = 4) {
|
|
13
|
+
return this.history.slice(-limit);
|
|
14
|
+
}
|
|
15
|
+
getLastSuggestion() {
|
|
16
|
+
return this.lastSuggestion;
|
|
17
|
+
}
|
|
18
|
+
clear() {
|
|
19
|
+
this.history = [];
|
|
20
|
+
this.lastSuggestion = undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAClB,OAAO,GAAuB,EAAE,CAAC;IACjC,cAAc,CAAgC;IAE/C,QAAQ,CAAC,QAAgB,EAAE,UAA6B;QAC7D,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,QAAQ;YACR,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,WAAW,EAAE,UAAU,CAAC,WAAW;SACpC,CAAC,CAAC;IACL,CAAC;IAEM,UAAU,CAAC,KAAK,GAAG,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAEM,iBAAiB;QACtB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;CACF"}
|