openshell-ai 1.0.4
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 +354 -0
- package/dist/analytics/client.d.ts +2 -0
- package/dist/analytics/client.js +95 -0
- package/dist/analytics/client.js.map +1 -0
- package/dist/analytics/session.d.ts +15 -0
- package/dist/analytics/session.js +70 -0
- package/dist/analytics/session.js.map +1 -0
- package/dist/cli/commands.d.ts +14 -0
- package/dist/cli/commands.js +265 -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 +12 -0
- package/dist/cli/repl.js +184 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/config/configurator.d.ts +18 -0
- package/dist/config/configurator.js +133 -0
- package/dist/config/configurator.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/providerCatalog.d.ts +8 -0
- package/dist/config/providerCatalog.js +33 -0
- package/dist/config/providerCatalog.js.map +1 -0
- package/dist/config/userConfig.d.ts +12 -0
- package/dist/config/userConfig.js +141 -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 +34 -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 +8 -0
- package/dist/core/prompts.js +75 -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/anthropic.d.ts +8 -0
- package/dist/providers/anthropic.js +67 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/factory.d.ts +2 -0
- package/dist/providers/factory.js +24 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/google.d.ts +8 -0
- package/dist/providers/google.js +76 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/ollama.d.ts +8 -0
- package/dist/providers/ollama.js +67 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +8 -0
- package/dist/providers/openai.js +77 -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 +105 -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 +16 -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/dist/workspace/inspectWorkspace.d.ts +1 -0
- package/dist/workspace/inspectWorkspace.js +174 -0
- package/dist/workspace/inspectWorkspace.js.map +1 -0
- package/package.json +73 -0
|
@@ -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"}
|
|
@@ -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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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -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,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,8 @@
|
|
|
1
|
+
import type { AppConfig, GenerateObjectRequest, ProviderTextResponse } from "../types/index.js";
|
|
2
|
+
import type { AIProvider } from "./types.js";
|
|
3
|
+
export declare class AnthropicProvider implements AIProvider {
|
|
4
|
+
private readonly config;
|
|
5
|
+
readonly name: "anthropic";
|
|
6
|
+
constructor(config: AppConfig);
|
|
7
|
+
generateObject(input: GenerateObjectRequest): Promise<ProviderTextResponse>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ProviderError } from "../utils/errors.js";
|
|
2
|
+
export class AnthropicProvider {
|
|
3
|
+
config;
|
|
4
|
+
name = "anthropic";
|
|
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}/messages`, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
"anthropic-version": "2023-06-01",
|
|
17
|
+
"x-api-key": this.config.apiKey ?? ""
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify({
|
|
20
|
+
model: this.config.model,
|
|
21
|
+
max_tokens: 1_024,
|
|
22
|
+
temperature: input.temperature ?? 0.1,
|
|
23
|
+
system: `${input.systemPrompt}\nReturn only a JSON object that matches the requested schema.`,
|
|
24
|
+
messages: [
|
|
25
|
+
{
|
|
26
|
+
role: "user",
|
|
27
|
+
content: input.userPrompt
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}),
|
|
31
|
+
signal: controller.signal
|
|
32
|
+
});
|
|
33
|
+
const data = (await response.json());
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
throw new ProviderError(data.error?.message
|
|
36
|
+
? `Provider request failed: ${data.error.message}`
|
|
37
|
+
: `Provider request failed with status ${response.status}.`);
|
|
38
|
+
}
|
|
39
|
+
const rawText = data.content
|
|
40
|
+
?.filter((block) => block.type === "text")
|
|
41
|
+
.map((block) => block.text)
|
|
42
|
+
.filter((block) => typeof block === "string")
|
|
43
|
+
.join("");
|
|
44
|
+
if (!rawText || rawText.trim().length === 0) {
|
|
45
|
+
throw new ProviderError("Provider returned an empty response.");
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
provider: this.name,
|
|
49
|
+
model: this.config.model,
|
|
50
|
+
rawText
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof ProviderError) {
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
if (error.name === "AbortError") {
|
|
58
|
+
throw new ProviderError(`Provider request timed out after ${this.config.timeoutMs}ms.`, error);
|
|
59
|
+
}
|
|
60
|
+
throw new ProviderError("Failed to reach AI provider.", error);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ConfigurationError } from "../utils/errors.js";
|
|
2
|
+
import { AnthropicProvider } from "./anthropic.js";
|
|
3
|
+
import { GoogleProvider } from "./google.js";
|
|
4
|
+
import { OllamaProvider } from "./ollama.js";
|
|
5
|
+
import { OpenAICompatibleProvider } from "./openai.js";
|
|
6
|
+
export function createProvider(config) {
|
|
7
|
+
if (config.provider === "openai") {
|
|
8
|
+
return new OpenAICompatibleProvider("openai", config);
|
|
9
|
+
}
|
|
10
|
+
if (config.provider === "anthropic") {
|
|
11
|
+
return new AnthropicProvider(config);
|
|
12
|
+
}
|
|
13
|
+
if (config.provider === "ollama") {
|
|
14
|
+
return new OllamaProvider(config);
|
|
15
|
+
}
|
|
16
|
+
if (config.provider === "google") {
|
|
17
|
+
return new GoogleProvider(config);
|
|
18
|
+
}
|
|
19
|
+
if (config.provider === "vllm") {
|
|
20
|
+
return new OpenAICompatibleProvider("vllm", config);
|
|
21
|
+
}
|
|
22
|
+
throw new ConfigurationError(`Unsupported AI provider: ${config.provider}`);
|
|
23
|
+
}
|
|
24
|
+
//# 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,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,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,QAAQ,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,OAAO,IAAI,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,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 GoogleProvider implements AIProvider {
|
|
4
|
+
private readonly config;
|
|
5
|
+
readonly name: "google";
|
|
6
|
+
constructor(config: AppConfig);
|
|
7
|
+
generateObject(input: GenerateObjectRequest): Promise<ProviderTextResponse>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ProviderError } from "../utils/errors.js";
|
|
2
|
+
export class GoogleProvider {
|
|
3
|
+
config;
|
|
4
|
+
name = "google";
|
|
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}/models/${encodeURIComponent(this.config.model)}:generateContent?key=${encodeURIComponent(this.config.apiKey ?? "")}`, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json"
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
systemInstruction: {
|
|
19
|
+
parts: [
|
|
20
|
+
{
|
|
21
|
+
text: input.systemPrompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
contents: [
|
|
26
|
+
{
|
|
27
|
+
role: "user",
|
|
28
|
+
parts: [
|
|
29
|
+
{
|
|
30
|
+
text: input.userPrompt
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
generationConfig: {
|
|
36
|
+
temperature: input.temperature ?? 0.1,
|
|
37
|
+
responseMimeType: "application/json",
|
|
38
|
+
responseSchema: input.jsonSchema
|
|
39
|
+
}
|
|
40
|
+
}),
|
|
41
|
+
signal: controller.signal
|
|
42
|
+
});
|
|
43
|
+
const data = (await response.json());
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new ProviderError(data.error?.message
|
|
46
|
+
? `Provider request failed: ${data.error.message}`
|
|
47
|
+
: `Provider request failed with status ${response.status}.`);
|
|
48
|
+
}
|
|
49
|
+
const rawText = data.candidates?.[0]?.content?.parts
|
|
50
|
+
?.map((part) => part.text)
|
|
51
|
+
.filter((part) => typeof part === "string")
|
|
52
|
+
.join("");
|
|
53
|
+
if (!rawText || rawText.trim().length === 0) {
|
|
54
|
+
throw new ProviderError("Provider returned an empty response.");
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
provider: this.name,
|
|
58
|
+
model: this.config.model,
|
|
59
|
+
rawText
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof ProviderError) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
if (error.name === "AbortError") {
|
|
67
|
+
throw new ProviderError(`Provider request timed out after ${this.config.timeoutMs}ms.`, error);
|
|
68
|
+
}
|
|
69
|
+
throw new ProviderError("Failed to reach AI provider.", error);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
clearTimeout(timeout);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 OllamaProvider implements AIProvider {
|
|
4
|
+
private readonly config;
|
|
5
|
+
readonly name: "ollama";
|
|
6
|
+
constructor(config: AppConfig);
|
|
7
|
+
generateObject(input: GenerateObjectRequest): Promise<ProviderTextResponse>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ProviderError } from "../utils/errors.js";
|
|
2
|
+
export class OllamaProvider {
|
|
3
|
+
config;
|
|
4
|
+
name = "ollama";
|
|
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`, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json"
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
model: this.config.model,
|
|
19
|
+
stream: false,
|
|
20
|
+
format: input.jsonSchema,
|
|
21
|
+
options: {
|
|
22
|
+
temperature: input.temperature ?? 0.1
|
|
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
|
|
40
|
+
? `Provider request failed: ${data.error}`
|
|
41
|
+
: `Provider request failed with status ${response.status}.`);
|
|
42
|
+
}
|
|
43
|
+
const rawText = data.message?.content;
|
|
44
|
+
if (!rawText || rawText.trim().length === 0) {
|
|
45
|
+
throw new ProviderError("Provider returned an empty response.");
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
provider: this.name,
|
|
49
|
+
model: data.model ?? this.config.model,
|
|
50
|
+
rawText
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof ProviderError) {
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
if (error.name === "AbortError") {
|
|
58
|
+
throw new ProviderError(`Provider request timed out after ${this.config.timeoutMs}ms.`, error);
|
|
59
|
+
}
|
|
60
|
+
throw new ProviderError("Failed to reach AI provider.", error);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUnD,MAAM,OAAO,cAAc;IAGW;IAFpB,IAAI,GAAG,QAAiB,CAAC;IAEzC,YAAoC,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAElD,KAAK,CAAC,cAAc,CACzB,KAA4B;QAE5B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE5E,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,OAAO,EAAE;gBAC1D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;oBACxB,MAAM,EAAE,KAAK;oBACb,MAAM,EAAE,KAAK,CAAC,UAAU;oBACxB,OAAO,EAAE;wBACP,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,GAAG;qBACtC;oBACD,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,QAAQ;4BACd,OAAO,EAAE,KAAK,CAAC,YAAY;yBAC5B;wBACD;4BACE,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,KAAK,CAAC,UAAU;yBAC1B;qBACF;iBACF,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;YAE3D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,aAAa,CACrB,IAAI,CAAC,KAAK;oBACR,CAAC,CAAC,4BAA4B,IAAI,CAAC,KAAK,EAAE;oBAC1C,CAAC,CAAC,uCAAuC,QAAQ,CAAC,MAAM,GAAG,CAC9D,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;YAEtC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5C,MAAM,IAAI,aAAa,CAAC,sCAAsC,CAAC,CAAC;YAClE,CAAC;YAED,OAAO;gBACL,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK;gBACtC,OAAO;aACR,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,IAAK,KAAe,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC3C,MAAM,IAAI,aAAa,CACrB,oCAAoC,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,EAC9D,KAAK,CACN,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,aAAa,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -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
|
+
readonly name: "openai" | "vllm";
|
|
5
|
+
private readonly config;
|
|
6
|
+
constructor(name: "openai" | "vllm", config: AppConfig);
|
|
7
|
+
generateObject(input: GenerateObjectRequest): Promise<ProviderTextResponse>;
|
|
8
|
+
}
|