@maintainabilityai/research-runner 0.1.2 → 0.1.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.
|
@@ -23,8 +23,10 @@ async function callAnthropic(opts) {
|
|
|
23
23
|
throw new Error('ANTHROPIC_API_KEY missing — set the env var or pass apiKey directly');
|
|
24
24
|
}
|
|
25
25
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
26
|
+
// Match github-models default — 8K-token synth responses can run 60–90s.
|
|
27
|
+
const timeoutMs = opts.timeoutMs ?? 120_000;
|
|
26
28
|
const controller = new AbortController();
|
|
27
|
-
const timer = setTimeout(() => controller.abort(),
|
|
29
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
28
30
|
let response;
|
|
29
31
|
try {
|
|
30
32
|
response = await fetchImpl('https://api.anthropic.com/v1/messages', {
|
|
@@ -44,6 +46,12 @@ async function callAnthropic(opts) {
|
|
|
44
46
|
signal: controller.signal,
|
|
45
47
|
});
|
|
46
48
|
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
51
|
+
throw new Error(`Anthropic request timed out after ${timeoutMs}ms (model=${opts.model}, max_tokens=${opts.maxTokens})`);
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`Anthropic fetch failed (model=${opts.model}): ${err instanceof Error ? err.message : String(err)}`);
|
|
54
|
+
}
|
|
47
55
|
finally {
|
|
48
56
|
clearTimeout(timer);
|
|
49
57
|
}
|
|
@@ -25,8 +25,11 @@ async function callGitHubModels(opts) {
|
|
|
25
25
|
}
|
|
26
26
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
27
27
|
const endpoint = opts.endpoint ?? DEFAULT_ENDPOINT;
|
|
28
|
+
// Synthesis prompts can produce 8K-token responses on gpt-4.1, which
|
|
29
|
+
// routinely take 60–90s. Default to 120s so we don't abort mid-stream.
|
|
30
|
+
const timeoutMs = opts.timeoutMs ?? 120_000;
|
|
28
31
|
const controller = new AbortController();
|
|
29
|
-
const timer = setTimeout(() => controller.abort(),
|
|
32
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
30
33
|
const messages = [];
|
|
31
34
|
if (opts.system) {
|
|
32
35
|
messages.push({ role: 'system', content: opts.system });
|
|
@@ -50,6 +53,12 @@ async function callGitHubModels(opts) {
|
|
|
50
53
|
signal: controller.signal,
|
|
51
54
|
});
|
|
52
55
|
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
58
|
+
throw new Error(`GitHub Models request timed out after ${timeoutMs}ms (model=${opts.model}, max_tokens=${opts.maxTokens})`);
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`GitHub Models fetch failed (model=${opts.model}): ${err instanceof Error ? err.message : String(err)}`);
|
|
61
|
+
}
|
|
53
62
|
finally {
|
|
54
63
|
clearTimeout(timer);
|
|
55
64
|
}
|
package/dist/llm/llm-router.js
CHANGED
|
@@ -10,7 +10,16 @@ const MODEL_BY_TIER = {
|
|
|
10
10
|
};
|
|
11
11
|
async function callLlm(opts) {
|
|
12
12
|
const tierModels = MODEL_BY_TIER[opts.tier];
|
|
13
|
-
|
|
13
|
+
// Hybrid routing: GitHub Models free tier caps requests at ~8K input
|
|
14
|
+
// tokens — too small for the synthesis step (full brief + every search
|
|
15
|
+
// result + mesh context routinely exceeds that). When the brief asks
|
|
16
|
+
// for github-models AND an Anthropic key is available, route synth →
|
|
17
|
+
// Anthropic and keep plan (small prompt) on github-models. Caller can
|
|
18
|
+
// force pure github-models by not setting anthropicApiKey.
|
|
19
|
+
const effectiveProvider = opts.provider === 'github-models' && opts.tier === 'synth' && opts.anthropicApiKey
|
|
20
|
+
? 'anthropic'
|
|
21
|
+
: opts.provider;
|
|
22
|
+
if (effectiveProvider === 'anthropic') {
|
|
14
23
|
if (!opts.anthropicApiKey) {
|
|
15
24
|
throw new Error(`callLlm: provider=anthropic requires anthropicApiKey (set ANTHROPIC_API_KEY).`);
|
|
16
25
|
}
|
|
@@ -33,7 +42,7 @@ async function callLlm(opts) {
|
|
|
33
42
|
httpStatus: r.httpStatus,
|
|
34
43
|
};
|
|
35
44
|
}
|
|
36
|
-
if (
|
|
45
|
+
if (effectiveProvider === 'github-models') {
|
|
37
46
|
if (!opts.githubToken) {
|
|
38
47
|
throw new Error(`callLlm: provider=github-models requires githubToken (set GITHUB_TOKEN; workflow needs \`permissions: models: read\`).`);
|
|
39
48
|
}
|
|
@@ -56,5 +65,5 @@ async function callLlm(opts) {
|
|
|
56
65
|
httpStatus: r.httpStatus,
|
|
57
66
|
};
|
|
58
67
|
}
|
|
59
|
-
throw new Error(`callLlm: provider "${
|
|
68
|
+
throw new Error(`callLlm: provider "${effectiveProvider}" not yet implemented (phase 2c.1 ships anthropic + github-models; openai + azure-openai land later).`);
|
|
60
69
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maintainabilityai/research-runner",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Research + PRD agent runner — orchestrates the Archeologist and PRD pipelines for the MaintainabilityAI governance mesh",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "MaintainabilityAI",
|