auspex 0.5.1 → 0.6.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/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +20 -4
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/report.d.ts.map +1 -1
- package/dist/agent/report.js +4 -1
- package/dist/agent/report.js.map +1 -1
- package/dist/browser/snapshot.d.ts.map +1 -1
- package/dist/browser/snapshot.js +14 -12
- package/dist/browser/snapshot.js.map +1 -1
- package/dist/config/defaults.d.ts +4 -3
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +6 -5
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +119 -6
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +7 -3
- package/dist/config/schema.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/adapter-agentium.d.ts +21 -0
- package/dist/llm/adapter-agentium.d.ts.map +1 -0
- package/dist/llm/adapter-agentium.js +204 -0
- package/dist/llm/adapter-agentium.js.map +1 -0
- package/dist/llm/adapter-openai.d.ts +19 -0
- package/dist/llm/adapter-openai.d.ts.map +1 -0
- package/dist/llm/adapter-openai.js +91 -0
- package/dist/llm/adapter-openai.js.map +1 -0
- package/dist/llm/client.d.ts +13 -13
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +45 -82
- package/dist/llm/client.js.map +1 -1
- package/dist/llm/types.d.ts +29 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +2 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/scraper/extractors/content.js +1 -1
- package/dist/scraper/extractors/content.js.map +1 -1
- package/dist/scraper/index.js +1 -1
- package/dist/scraper/index.js.map +1 -1
- package/dist/types.d.ts +11 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -1
- package/readme.md +127 -11
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwB1C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,gFAAgF;AAChF,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAS1B,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,+EAA+E;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAgB7C,gFAAgF;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,gFAAgF;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ILLMAdapter, LLMRequestParams, LLMResponse } from "./types.js";
|
|
2
|
+
export interface AgentiumAdapterConfig {
|
|
3
|
+
modelPath?: string;
|
|
4
|
+
modelDir?: string;
|
|
5
|
+
gpuLayers?: number | "auto";
|
|
6
|
+
contextSize?: number | "auto";
|
|
7
|
+
temperature?: number;
|
|
8
|
+
maxTokens?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class AgentiumAdapter implements ILLMAdapter {
|
|
11
|
+
private config;
|
|
12
|
+
private engine;
|
|
13
|
+
private grammar;
|
|
14
|
+
private initPromise;
|
|
15
|
+
constructor(config: AgentiumAdapterConfig);
|
|
16
|
+
ensureInitialized(): Promise<void>;
|
|
17
|
+
private init;
|
|
18
|
+
decideAction(params: LLMRequestParams): Promise<LLMResponse>;
|
|
19
|
+
dispose(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=adapter-agentium.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-agentium.d.ts","sourceRoot":"","sources":["../../src/llm/adapter-agentium.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyB7E,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuFD,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,WAAW,CAA8B;gBAErC,MAAM,EAAE,qBAAqB;IAIzC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;YAOpB,IAAI;IAsEZ,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAuD5D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAG/B"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, renameSync, createWriteStream } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve, isAbsolute } from "node:path";
|
|
4
|
+
import { buildSystemPrompt, buildUserMessage } from "./prompt.js";
|
|
5
|
+
const DEFAULT_MODEL_DIR = join(homedir(), ".auspex", "models");
|
|
6
|
+
const DEFAULT_MODEL_FILENAME = "Qwen2.5-7B-Instruct-Q4_K_M.gguf";
|
|
7
|
+
const DEFAULT_MODEL_URL = `https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/${DEFAULT_MODEL_FILENAME}`;
|
|
8
|
+
const ACTION_JSON_SCHEMA = {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
type: { type: "string" },
|
|
12
|
+
selector: { type: "string" },
|
|
13
|
+
text: { type: "string" },
|
|
14
|
+
value: { type: "string" },
|
|
15
|
+
key: { type: "string" },
|
|
16
|
+
url: { type: "string" },
|
|
17
|
+
ms: { type: "integer" },
|
|
18
|
+
direction: { type: "string" },
|
|
19
|
+
amount: { type: "integer" },
|
|
20
|
+
result: { type: "string" },
|
|
21
|
+
query: { type: "string" },
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
let agentiumModule = null;
|
|
25
|
+
async function loadAgentium() {
|
|
26
|
+
if (!agentiumModule) {
|
|
27
|
+
try {
|
|
28
|
+
agentiumModule = await import("agentium");
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error('[auspex] The "agentium" package is required for provider: "agentium". Install it with: npm install agentium');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return agentiumModule;
|
|
35
|
+
}
|
|
36
|
+
const engineCache = new Map();
|
|
37
|
+
let engineCacheInitLock = null;
|
|
38
|
+
async function downloadFile(url, destPath) {
|
|
39
|
+
const dir = resolve(destPath, "..");
|
|
40
|
+
mkdirSync(dir, { recursive: true });
|
|
41
|
+
const tmpPath = destPath + ".tmp";
|
|
42
|
+
console.log(`[auspex] Downloading model from ${url}`);
|
|
43
|
+
console.log(`[auspex] Saving to ${destPath}`);
|
|
44
|
+
const response = await fetch(url, { redirect: "follow" });
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error(`[auspex] Model download failed: HTTP ${response.status} ${response.statusText}.\n` +
|
|
47
|
+
`Download the model manually and set modelPath in config.`);
|
|
48
|
+
}
|
|
49
|
+
if (!response.body) {
|
|
50
|
+
throw new Error("[auspex] Model download failed: empty response body.");
|
|
51
|
+
}
|
|
52
|
+
const contentLength = response.headers.get("content-length");
|
|
53
|
+
const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
|
|
54
|
+
let downloadedBytes = 0;
|
|
55
|
+
const writer = createWriteStream(tmpPath);
|
|
56
|
+
const reader = response.body.getReader();
|
|
57
|
+
let lastLog = 0;
|
|
58
|
+
try {
|
|
59
|
+
while (true) {
|
|
60
|
+
const { done, value } = await reader.read();
|
|
61
|
+
if (done)
|
|
62
|
+
break;
|
|
63
|
+
writer.write(value);
|
|
64
|
+
downloadedBytes += value.length;
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
if (totalBytes > 0 && now - lastLog > 5_000) {
|
|
67
|
+
const pct = Math.round((downloadedBytes / totalBytes) * 100);
|
|
68
|
+
const mb = (downloadedBytes / 1024 / 1024).toFixed(1);
|
|
69
|
+
const totalMb = (totalBytes / 1024 / 1024).toFixed(1);
|
|
70
|
+
console.log(`[auspex] Downloading: ${pct}% (${mb} / ${totalMb} MB)`);
|
|
71
|
+
lastLog = now;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
writer.end();
|
|
77
|
+
}
|
|
78
|
+
await new Promise((res, rej) => {
|
|
79
|
+
writer.on("finish", res);
|
|
80
|
+
writer.on("error", rej);
|
|
81
|
+
});
|
|
82
|
+
renameSync(tmpPath, destPath);
|
|
83
|
+
const finalMb = (downloadedBytes / 1024 / 1024).toFixed(1);
|
|
84
|
+
console.log(`[auspex] Model download complete (${finalMb} MB).`);
|
|
85
|
+
}
|
|
86
|
+
export class AgentiumAdapter {
|
|
87
|
+
config;
|
|
88
|
+
engine = null;
|
|
89
|
+
grammar = null;
|
|
90
|
+
initPromise = null;
|
|
91
|
+
constructor(config) {
|
|
92
|
+
this.config = config;
|
|
93
|
+
}
|
|
94
|
+
ensureInitialized() {
|
|
95
|
+
if (!this.initPromise) {
|
|
96
|
+
this.initPromise = this.init();
|
|
97
|
+
}
|
|
98
|
+
return this.initPromise;
|
|
99
|
+
}
|
|
100
|
+
async init() {
|
|
101
|
+
if (this.engine)
|
|
102
|
+
return;
|
|
103
|
+
const modelDir = this.config.modelDir ?? DEFAULT_MODEL_DIR;
|
|
104
|
+
let modelPath = this.config.modelPath ?? join(modelDir, DEFAULT_MODEL_FILENAME);
|
|
105
|
+
if (!isAbsolute(modelPath)) {
|
|
106
|
+
modelPath = resolve(modelPath);
|
|
107
|
+
}
|
|
108
|
+
const cached = engineCache.get(modelPath);
|
|
109
|
+
if (cached) {
|
|
110
|
+
this.engine = cached.engine;
|
|
111
|
+
this.grammar = cached.grammar;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
while (engineCacheInitLock) {
|
|
115
|
+
await engineCacheInitLock;
|
|
116
|
+
const pending = engineCache.get(modelPath);
|
|
117
|
+
if (pending) {
|
|
118
|
+
this.engine = pending.engine;
|
|
119
|
+
this.grammar = pending.grammar;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
engineCacheInitLock = (async () => {
|
|
124
|
+
try {
|
|
125
|
+
const { createEngine } = await loadAgentium();
|
|
126
|
+
if (!existsSync(modelPath)) {
|
|
127
|
+
if (this.config.modelPath) {
|
|
128
|
+
throw new Error(`[auspex] Model file not found: ${modelPath}.\n` +
|
|
129
|
+
`Download it manually or remove modelPath to use the default model with auto-download.`);
|
|
130
|
+
}
|
|
131
|
+
await downloadFile(DEFAULT_MODEL_URL, modelPath);
|
|
132
|
+
}
|
|
133
|
+
console.log(`[auspex] Loading model from ${modelPath} ...`);
|
|
134
|
+
const engine = await createEngine({
|
|
135
|
+
modelPath,
|
|
136
|
+
gpuLayers: this.config.gpuLayers ?? "auto",
|
|
137
|
+
contextSize: this.config.contextSize ?? "auto",
|
|
138
|
+
});
|
|
139
|
+
const grammar = await engine.createGrammar(ACTION_JSON_SCHEMA);
|
|
140
|
+
engineCache.set(modelPath, { engine, grammar, modelPath });
|
|
141
|
+
this.engine = engine;
|
|
142
|
+
this.grammar = grammar;
|
|
143
|
+
console.log("[auspex] Model loaded successfully.");
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
engineCacheInitLock = null;
|
|
147
|
+
}
|
|
148
|
+
})();
|
|
149
|
+
await engineCacheInitLock;
|
|
150
|
+
const entry = engineCache.get(modelPath);
|
|
151
|
+
if (entry && !this.engine) {
|
|
152
|
+
this.engine = entry.engine;
|
|
153
|
+
this.grammar = entry.grammar;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async decideAction(params) {
|
|
157
|
+
await this.ensureInitialized();
|
|
158
|
+
if (params.screenshot) {
|
|
159
|
+
console.warn("[auspex] Screenshots are not supported with provider: agentium (local models). The screenshot will be ignored.");
|
|
160
|
+
}
|
|
161
|
+
const systemPrompt = buildSystemPrompt(false, !!params.searchAvailable);
|
|
162
|
+
const userMessage = buildUserMessage(params.prompt, params.snapshot, params.history, params.schemaDescription, params.timeStatus);
|
|
163
|
+
const session = await this.engine.createSession({ systemPrompt });
|
|
164
|
+
try {
|
|
165
|
+
const response = await session.prompt(userMessage, {
|
|
166
|
+
grammar: this.grammar,
|
|
167
|
+
temperature: this.config.temperature ?? 0,
|
|
168
|
+
maxTokens: this.config.maxTokens ?? 2048,
|
|
169
|
+
});
|
|
170
|
+
let parsed;
|
|
171
|
+
try {
|
|
172
|
+
parsed = this.grammar.parse(response);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
parsed = JSON.parse(response);
|
|
176
|
+
}
|
|
177
|
+
let promptTokens = 0;
|
|
178
|
+
let completionTokens = 0;
|
|
179
|
+
try {
|
|
180
|
+
promptTokens = this.engine.tokenize(systemPrompt + userMessage).length;
|
|
181
|
+
completionTokens = this.engine.tokenize(response).length;
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
promptTokens = Math.round((systemPrompt.length + userMessage.length) / 4);
|
|
185
|
+
completionTokens = Math.round(response.length / 4);
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
data: parsed,
|
|
189
|
+
usage: {
|
|
190
|
+
promptTokens,
|
|
191
|
+
completionTokens,
|
|
192
|
+
totalTokens: promptTokens + completionTokens,
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
await session.dispose().catch(() => { });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async dispose() {
|
|
201
|
+
// Shared engine is never disposed — reused across runs, freed on process exit.
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=adapter-agentium.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-agentium.js","sourceRoot":"","sources":["../../src/llm/adapter-agentium.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ILLMAdapter, LLMRequestParams, LLMResponse } from "./types.js";
|
|
2
|
+
export interface OpenAIAdapterConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
model: string;
|
|
5
|
+
temperature: number;
|
|
6
|
+
maxTokens?: number;
|
|
7
|
+
topP?: number;
|
|
8
|
+
frequencyPenalty?: number;
|
|
9
|
+
presencePenalty?: number;
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class OpenAIAdapter implements ILLMAdapter {
|
|
13
|
+
private client;
|
|
14
|
+
private model;
|
|
15
|
+
private params;
|
|
16
|
+
constructor(config: OpenAIAdapterConfig);
|
|
17
|
+
decideAction(params: LLMRequestParams): Promise<LLMResponse>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=adapter-openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-openai.d.ts","sourceRoot":"","sources":["../../src/llm/adapter-openai.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG7E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqBD,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAkH;gBAEpH,MAAM,EAAE,mBAAmB;IAYjC,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;CAmEnE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
import { buildSystemPrompt, buildUserMessage, buildVisionContent } from "./prompt.js";
|
|
3
|
+
const MAX_RETRIES = 3;
|
|
4
|
+
const BASE_DELAY_MS = 1_000;
|
|
5
|
+
function isRetryableError(err) {
|
|
6
|
+
if (err instanceof OpenAI.APIError) {
|
|
7
|
+
return err.status === 429 || err.status === 408 || (err.status !== undefined && err.status >= 500);
|
|
8
|
+
}
|
|
9
|
+
if (err instanceof Error) {
|
|
10
|
+
const msg = err.message.toLowerCase();
|
|
11
|
+
return msg.includes("econnreset") || msg.includes("etimedout") ||
|
|
12
|
+
msg.includes("socket hang up") || msg.includes("fetch failed");
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
function sleep(ms) {
|
|
17
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
|
+
}
|
|
19
|
+
export class OpenAIAdapter {
|
|
20
|
+
client;
|
|
21
|
+
model;
|
|
22
|
+
params;
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.client = new OpenAI({ apiKey: config.apiKey, baseURL: config.baseUrl });
|
|
25
|
+
this.model = config.model;
|
|
26
|
+
this.params = {
|
|
27
|
+
temperature: config.temperature,
|
|
28
|
+
maxTokens: config.maxTokens,
|
|
29
|
+
topP: config.topP,
|
|
30
|
+
frequencyPenalty: config.frequencyPenalty,
|
|
31
|
+
presencePenalty: config.presencePenalty,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async decideAction(params) {
|
|
35
|
+
let lastError;
|
|
36
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
37
|
+
try {
|
|
38
|
+
const textContent = buildUserMessage(params.prompt, params.snapshot, params.history, params.schemaDescription, params.timeStatus);
|
|
39
|
+
const userContent = params.screenshot
|
|
40
|
+
? buildVisionContent(textContent, params.screenshot)
|
|
41
|
+
: textContent;
|
|
42
|
+
const completionParams = {
|
|
43
|
+
model: this.model,
|
|
44
|
+
temperature: this.params.temperature,
|
|
45
|
+
max_completion_tokens: this.params.maxTokens,
|
|
46
|
+
top_p: this.params.topP,
|
|
47
|
+
frequency_penalty: this.params.frequencyPenalty,
|
|
48
|
+
presence_penalty: this.params.presencePenalty,
|
|
49
|
+
messages: [
|
|
50
|
+
{ role: "system", content: buildSystemPrompt(!!params.visionAvailable, !!params.searchAvailable) },
|
|
51
|
+
{ role: "user", content: userContent },
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
if (!params.screenshot) {
|
|
55
|
+
completionParams.response_format = { type: "json_object" };
|
|
56
|
+
}
|
|
57
|
+
const response = await this.client.chat.completions.create(completionParams);
|
|
58
|
+
const choice = response.choices[0];
|
|
59
|
+
const finishReason = choice?.finish_reason;
|
|
60
|
+
if (finishReason === "length") {
|
|
61
|
+
throw new Error(`LLM response cut off by token limit (max_completion_tokens=${this.params.maxTokens}). ` +
|
|
62
|
+
"Increase maxTokens in AgentConfig if this happens frequently.");
|
|
63
|
+
}
|
|
64
|
+
const content = choice?.message?.content;
|
|
65
|
+
if (!content) {
|
|
66
|
+
throw new Error(`LLM returned empty response (finish_reason: ${finishReason ?? "unknown"})`);
|
|
67
|
+
}
|
|
68
|
+
const usage = response.usage;
|
|
69
|
+
return {
|
|
70
|
+
data: JSON.parse(content),
|
|
71
|
+
usage: {
|
|
72
|
+
promptTokens: usage?.prompt_tokens ?? 0,
|
|
73
|
+
completionTokens: usage?.completion_tokens ?? 0,
|
|
74
|
+
totalTokens: usage?.total_tokens ?? 0,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
lastError = err;
|
|
80
|
+
if (attempt < MAX_RETRIES && isRetryableError(err)) {
|
|
81
|
+
const delay = BASE_DELAY_MS * Math.pow(2, attempt - 1);
|
|
82
|
+
await sleep(delay);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
throw lastError;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=adapter-openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-openai.js","sourceRoot":"","sources":["../../src/llm/adapter-openai.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/client.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
import type { LLMProvider, LLMResponse } from "./types.js";
|
|
2
|
+
export interface LLMClientConfig {
|
|
3
|
+
provider: LLMProvider;
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
model: string;
|
|
2
7
|
temperature: number;
|
|
3
8
|
maxTokens?: number;
|
|
4
9
|
topP?: number;
|
|
5
10
|
frequencyPenalty?: number;
|
|
6
11
|
presencePenalty?: number;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
promptTokens: number;
|
|
12
|
-
completionTokens: number;
|
|
13
|
-
totalTokens: number;
|
|
14
|
-
};
|
|
12
|
+
modelPath?: string;
|
|
13
|
+
modelDir?: string;
|
|
14
|
+
gpuLayers?: number | "auto";
|
|
15
|
+
contextSize?: number | "auto";
|
|
15
16
|
}
|
|
16
17
|
export declare class LLMClient {
|
|
17
|
-
private
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
constructor(apiKey: string, model: string, params: LLMParams, baseUrl?: string);
|
|
18
|
+
private adapter;
|
|
19
|
+
private initPromise;
|
|
20
|
+
constructor(config: LLMClientConfig);
|
|
21
21
|
decideAction(prompt: string, snapshot: string, history: string[], schemaDescription?: string, screenshot?: string, visionAvailable?: boolean, searchAvailable?: boolean, timeStatus?: {
|
|
22
22
|
remainingMs: number;
|
|
23
23
|
totalMs: number;
|
package/dist/llm/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,WAAW,EAAoB,WAAW,EAAE,MAAM,YAAY,CAAC;AAI1F,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,WAAW,CAA8B;gBAErC,MAAM,EAAE,eAAe;IA6B7B,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EAAE,EACjB,iBAAiB,CAAC,EAAE,MAAM,EAC1B,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,OAAO,EACzB,eAAe,CAAC,EAAE,OAAO,EACzB,UAAU,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAC9F,OAAO,CAAC,WAAW,CAAC;CAgBxB"}
|
package/dist/llm/client.js
CHANGED
|
@@ -1,88 +1,51 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
const MAX_RETRIES = 3;
|
|
4
|
-
const BASE_DELAY_MS = 1_000;
|
|
5
|
-
function isRetryableError(err) {
|
|
6
|
-
if (err instanceof OpenAI.APIError) {
|
|
7
|
-
// Retry on rate limit (429), server errors (5xx), and timeout (408)
|
|
8
|
-
return err.status === 429 || err.status === 408 || (err.status !== undefined && err.status >= 500);
|
|
9
|
-
}
|
|
10
|
-
// Retry on network errors
|
|
11
|
-
if (err instanceof Error) {
|
|
12
|
-
const msg = err.message.toLowerCase();
|
|
13
|
-
return msg.includes("econnreset") || msg.includes("etimedout") ||
|
|
14
|
-
msg.includes("socket hang up") || msg.includes("fetch failed");
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
function sleep(ms) {
|
|
19
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
20
|
-
}
|
|
1
|
+
import { OpenAIAdapter } from "./adapter-openai.js";
|
|
2
|
+
import { AgentiumAdapter } from "./adapter-agentium.js";
|
|
21
3
|
export class LLMClient {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
temperature: this.params.temperature,
|
|
41
|
-
max_completion_tokens: this.params.maxTokens,
|
|
42
|
-
top_p: this.params.topP,
|
|
43
|
-
frequency_penalty: this.params.frequencyPenalty,
|
|
44
|
-
presence_penalty: this.params.presencePenalty,
|
|
45
|
-
messages: [
|
|
46
|
-
{ role: "system", content: buildSystemPrompt(!!visionAvailable, !!searchAvailable) },
|
|
47
|
-
{ role: "user", content: userContent },
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
// JSON mode is not reliably supported alongside vision on all providers
|
|
51
|
-
if (!screenshot) {
|
|
52
|
-
params.response_format = { type: "json_object" };
|
|
53
|
-
}
|
|
54
|
-
const response = await this.client.chat.completions.create(params);
|
|
55
|
-
const choice = response.choices[0];
|
|
56
|
-
const finishReason = choice?.finish_reason;
|
|
57
|
-
if (finishReason === "length") {
|
|
58
|
-
throw new Error(`LLM response cut off by token limit (max_completion_tokens=${this.params.maxTokens}). ` +
|
|
59
|
-
"Increase maxTokens in AgentConfig if this happens frequently.");
|
|
60
|
-
}
|
|
61
|
-
const content = choice?.message?.content;
|
|
62
|
-
if (!content) {
|
|
63
|
-
throw new Error(`LLM returned empty response (finish_reason: ${finishReason ?? "unknown"})`);
|
|
64
|
-
}
|
|
65
|
-
const usage = response.usage;
|
|
66
|
-
return {
|
|
67
|
-
data: JSON.parse(content),
|
|
68
|
-
usage: {
|
|
69
|
-
promptTokens: usage?.prompt_tokens ?? 0,
|
|
70
|
-
completionTokens: usage?.completion_tokens ?? 0,
|
|
71
|
-
totalTokens: usage?.total_tokens ?? 0,
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
lastError = err;
|
|
77
|
-
if (attempt < MAX_RETRIES && isRetryableError(err)) {
|
|
78
|
-
const delay = BASE_DELAY_MS * Math.pow(2, attempt - 1);
|
|
79
|
-
await sleep(delay);
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
throw err;
|
|
4
|
+
adapter;
|
|
5
|
+
initPromise = null;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
if (config.provider === "agentium") {
|
|
8
|
+
const adapter = new AgentiumAdapter({
|
|
9
|
+
modelPath: config.modelPath,
|
|
10
|
+
modelDir: config.modelDir,
|
|
11
|
+
gpuLayers: config.gpuLayers,
|
|
12
|
+
contextSize: config.contextSize,
|
|
13
|
+
temperature: config.temperature,
|
|
14
|
+
maxTokens: config.maxTokens,
|
|
15
|
+
});
|
|
16
|
+
this.adapter = adapter;
|
|
17
|
+
this.initPromise = adapter.ensureInitialized();
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
if (!config.apiKey) {
|
|
21
|
+
throw new Error("llmApiKey is required when provider is 'openai'");
|
|
83
22
|
}
|
|
23
|
+
this.adapter = new OpenAIAdapter({
|
|
24
|
+
apiKey: config.apiKey,
|
|
25
|
+
model: config.model,
|
|
26
|
+
temperature: config.temperature,
|
|
27
|
+
maxTokens: config.maxTokens,
|
|
28
|
+
topP: config.topP,
|
|
29
|
+
frequencyPenalty: config.frequencyPenalty,
|
|
30
|
+
presencePenalty: config.presencePenalty,
|
|
31
|
+
baseUrl: config.baseUrl,
|
|
32
|
+
});
|
|
84
33
|
}
|
|
85
|
-
|
|
34
|
+
}
|
|
35
|
+
async decideAction(prompt, snapshot, history, schemaDescription, screenshot, visionAvailable, searchAvailable, timeStatus) {
|
|
36
|
+
if (this.initPromise)
|
|
37
|
+
await this.initPromise;
|
|
38
|
+
const params = {
|
|
39
|
+
prompt,
|
|
40
|
+
snapshot,
|
|
41
|
+
history,
|
|
42
|
+
schemaDescription,
|
|
43
|
+
screenshot,
|
|
44
|
+
visionAvailable,
|
|
45
|
+
searchAvailable,
|
|
46
|
+
timeStatus,
|
|
47
|
+
};
|
|
48
|
+
return this.adapter.decideAction(params);
|
|
86
49
|
}
|
|
87
50
|
}
|
|
88
51
|
//# sourceMappingURL=client.js.map
|
package/dist/llm/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkBxD,MAAM,OAAO,SAAS;IACZ,OAAO,CAAc;IACrB,WAAW,GAAyB,IAAI,CAAC;IAEjD,YAAY,MAAuB;QACjC,IAAI,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC;gBAClC,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC;gBAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,eAAe,EAAE,MAAM,CAAC,eAAe;gBACvC,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,MAAc,EACd,QAAgB,EAChB,OAAiB,EACjB,iBAA0B,EAC1B,UAAmB,EACnB,eAAyB,EACzB,eAAyB,EACzB,UAA+F;QAE/F,IAAI,IAAI,CAAC,WAAW;YAAE,MAAM,IAAI,CAAC,WAAW,CAAC;QAE7C,MAAM,MAAM,GAAqB;YAC/B,MAAM;YACN,QAAQ;YACR,OAAO;YACP,iBAAiB;YACjB,UAAU;YACV,eAAe;YACf,eAAe;YACf,UAAU;SACX,CAAC;QAEF,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type LLMProvider = "openai" | "agentium";
|
|
2
|
+
export interface LLMResponse {
|
|
3
|
+
data: unknown;
|
|
4
|
+
usage: {
|
|
5
|
+
promptTokens: number;
|
|
6
|
+
completionTokens: number;
|
|
7
|
+
totalTokens: number;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface LLMRequestParams {
|
|
11
|
+
prompt: string;
|
|
12
|
+
snapshot: string;
|
|
13
|
+
history: string[];
|
|
14
|
+
schemaDescription?: string;
|
|
15
|
+
screenshot?: string;
|
|
16
|
+
visionAvailable?: boolean;
|
|
17
|
+
searchAvailable?: boolean;
|
|
18
|
+
timeStatus?: {
|
|
19
|
+
remainingMs: number;
|
|
20
|
+
totalMs: number;
|
|
21
|
+
iteration: number;
|
|
22
|
+
maxIterations: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface ILLMAdapter {
|
|
26
|
+
decideAction(params: LLMRequestParams): Promise<LLMResponse>;
|
|
27
|
+
dispose?(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":""}
|
|
@@ -144,7 +144,7 @@ export function extractLinksWithMetadata(html, baseUrl, existing$) {
|
|
|
144
144
|
seen.add(resolved);
|
|
145
145
|
const title = ($(el).text().trim() || $(el).attr("title") || "")
|
|
146
146
|
.replace(/\s+/g, " ")
|
|
147
|
-
.slice(0,
|
|
147
|
+
.slice(0, 500); // Increased: allow longer link titles
|
|
148
148
|
links.push({ url: resolved, title: title || undefined });
|
|
149
149
|
}
|
|
150
150
|
});
|