@juspay/neurolink 9.51.4 → 9.53.0
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/CHANGELOG.md +12 -0
- package/README.md +19 -0
- package/dist/agent/directTools.d.ts +2 -2
- package/dist/auth/errors.d.ts +1 -1
- package/dist/auth/middleware/AuthMiddleware.d.ts +1 -1
- package/dist/auth/providers/BaseAuthProvider.d.ts +1 -1
- package/dist/autoresearch/config.d.ts +11 -0
- package/dist/autoresearch/config.js +108 -0
- package/dist/autoresearch/errors.d.ts +40 -0
- package/dist/autoresearch/errors.js +20 -0
- package/dist/autoresearch/index.d.ts +23 -0
- package/dist/autoresearch/index.js +34 -0
- package/dist/autoresearch/phasePolicy.d.ts +9 -0
- package/dist/autoresearch/phasePolicy.js +69 -0
- package/dist/autoresearch/promptCompiler.d.ts +15 -0
- package/dist/autoresearch/promptCompiler.js +120 -0
- package/dist/autoresearch/repoPolicy.d.ts +32 -0
- package/dist/autoresearch/repoPolicy.js +128 -0
- package/dist/autoresearch/resultRecorder.d.ts +20 -0
- package/dist/autoresearch/resultRecorder.js +130 -0
- package/dist/autoresearch/runner.d.ts +10 -0
- package/dist/autoresearch/runner.js +102 -0
- package/dist/autoresearch/stateStore.d.ts +12 -0
- package/dist/autoresearch/stateStore.js +163 -0
- package/dist/autoresearch/summaryParser.d.ts +16 -0
- package/dist/autoresearch/summaryParser.js +94 -0
- package/dist/autoresearch/tools.d.ts +257 -0
- package/dist/autoresearch/tools.js +617 -0
- package/dist/autoresearch/worker.d.ts +71 -0
- package/dist/autoresearch/worker.js +417 -0
- package/dist/browser/neurolink.min.js +340 -324
- package/dist/cli/commands/autoresearch.d.ts +41 -0
- package/dist/cli/commands/autoresearch.js +487 -0
- package/dist/cli/commands/config.d.ts +1 -1
- package/dist/cli/commands/task.d.ts +2 -0
- package/dist/cli/commands/task.js +32 -3
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/cli/parser.js +4 -1
- package/dist/core/baseProvider.js +18 -0
- package/dist/core/factory.d.ts +2 -2
- package/dist/core/factory.js +4 -4
- package/dist/evaluation/errors/EvaluationError.d.ts +1 -1
- package/dist/factories/providerFactory.d.ts +4 -4
- package/dist/factories/providerFactory.js +20 -7
- package/dist/factories/providerRegistry.d.ts +5 -0
- package/dist/factories/providerRegistry.js +45 -26
- package/dist/lib/agent/directTools.d.ts +2 -2
- package/dist/lib/auth/errors.d.ts +1 -1
- package/dist/lib/auth/middleware/AuthMiddleware.d.ts +1 -1
- package/dist/lib/auth/providers/BaseAuthProvider.d.ts +1 -1
- package/dist/lib/autoresearch/config.d.ts +11 -0
- package/dist/lib/autoresearch/config.js +109 -0
- package/dist/lib/autoresearch/errors.d.ts +40 -0
- package/dist/lib/autoresearch/errors.js +21 -0
- package/dist/lib/autoresearch/index.d.ts +23 -0
- package/dist/lib/autoresearch/index.js +35 -0
- package/dist/lib/autoresearch/phasePolicy.d.ts +9 -0
- package/dist/lib/autoresearch/phasePolicy.js +70 -0
- package/dist/lib/autoresearch/promptCompiler.d.ts +15 -0
- package/dist/lib/autoresearch/promptCompiler.js +121 -0
- package/dist/lib/autoresearch/repoPolicy.d.ts +32 -0
- package/dist/lib/autoresearch/repoPolicy.js +129 -0
- package/dist/lib/autoresearch/resultRecorder.d.ts +20 -0
- package/dist/lib/autoresearch/resultRecorder.js +131 -0
- package/dist/lib/autoresearch/runner.d.ts +10 -0
- package/dist/lib/autoresearch/runner.js +103 -0
- package/dist/lib/autoresearch/stateStore.d.ts +12 -0
- package/dist/lib/autoresearch/stateStore.js +164 -0
- package/dist/lib/autoresearch/summaryParser.d.ts +16 -0
- package/dist/lib/autoresearch/summaryParser.js +95 -0
- package/dist/lib/autoresearch/tools.d.ts +257 -0
- package/dist/lib/autoresearch/tools.js +618 -0
- package/dist/lib/autoresearch/worker.d.ts +71 -0
- package/dist/lib/autoresearch/worker.js +418 -0
- package/dist/lib/core/baseProvider.js +18 -0
- package/dist/lib/core/factory.d.ts +2 -2
- package/dist/lib/core/factory.js +4 -4
- package/dist/lib/evaluation/errors/EvaluationError.d.ts +1 -1
- package/dist/lib/factories/providerFactory.d.ts +4 -4
- package/dist/lib/factories/providerFactory.js +20 -7
- package/dist/lib/factories/providerRegistry.d.ts +5 -0
- package/dist/lib/factories/providerRegistry.js +45 -26
- package/dist/lib/files/fileTools.d.ts +1 -1
- package/dist/lib/neurolink.d.ts +21 -0
- package/dist/lib/neurolink.js +91 -8
- package/dist/lib/providers/amazonBedrock.d.ts +6 -1
- package/dist/lib/providers/amazonBedrock.js +14 -2
- package/dist/lib/providers/amazonSagemaker.d.ts +7 -1
- package/dist/lib/providers/amazonSagemaker.js +21 -3
- package/dist/lib/providers/anthropic.d.ts +4 -1
- package/dist/lib/providers/anthropic.js +18 -5
- package/dist/lib/providers/azureOpenai.d.ts +2 -1
- package/dist/lib/providers/azureOpenai.js +10 -5
- package/dist/lib/providers/googleAiStudio.d.ts +4 -1
- package/dist/lib/providers/googleAiStudio.js +6 -7
- package/dist/lib/providers/googleVertex.d.ts +3 -1
- package/dist/lib/providers/googleVertex.js +96 -17
- package/dist/lib/providers/huggingFace.d.ts +2 -1
- package/dist/lib/providers/huggingFace.js +4 -4
- package/dist/lib/providers/litellm.d.ts +5 -1
- package/dist/lib/providers/litellm.js +16 -11
- package/dist/lib/providers/mistral.d.ts +2 -1
- package/dist/lib/providers/mistral.js +2 -2
- package/dist/lib/providers/ollama.d.ts +3 -1
- package/dist/lib/providers/ollama.js +2 -2
- package/dist/lib/providers/openAI.d.ts +5 -1
- package/dist/lib/providers/openAI.js +15 -5
- package/dist/lib/providers/openRouter.d.ts +5 -1
- package/dist/lib/providers/openRouter.js +19 -7
- package/dist/lib/providers/openaiCompatible.d.ts +4 -1
- package/dist/lib/providers/openaiCompatible.js +18 -4
- package/dist/lib/tasks/autoresearchTaskExecutor.d.ts +32 -0
- package/dist/lib/tasks/autoresearchTaskExecutor.js +303 -0
- package/dist/lib/tasks/errors.d.ts +3 -1
- package/dist/lib/tasks/errors.js +1 -0
- package/dist/lib/tasks/taskExecutor.d.ts +4 -2
- package/dist/lib/tasks/taskExecutor.js +8 -1
- package/dist/lib/tasks/taskManager.js +27 -3
- package/dist/lib/tasks/tools/taskTools.d.ts +1 -1
- package/dist/lib/telemetry/attributes.d.ts +15 -0
- package/dist/lib/telemetry/attributes.js +16 -0
- package/dist/lib/telemetry/tracers.d.ts +1 -0
- package/dist/lib/telemetry/tracers.js +1 -0
- package/dist/lib/types/autoresearchTypes.d.ts +194 -0
- package/dist/lib/types/autoresearchTypes.js +18 -0
- package/dist/lib/types/common.d.ts +11 -0
- package/dist/lib/types/configTypes.d.ts +7 -0
- package/dist/lib/types/generateTypes.d.ts +13 -0
- package/dist/lib/types/index.d.ts +16 -14
- package/dist/lib/types/index.js +21 -17
- package/dist/lib/types/providers.d.ts +75 -0
- package/dist/lib/types/streamTypes.d.ts +7 -1
- package/dist/lib/types/taskTypes.d.ts +38 -0
- package/dist/lib/workflow/config.d.ts +3 -3
- package/dist/neurolink.d.ts +21 -0
- package/dist/neurolink.js +91 -8
- package/dist/providers/amazonBedrock.d.ts +6 -1
- package/dist/providers/amazonBedrock.js +14 -2
- package/dist/providers/amazonSagemaker.d.ts +7 -1
- package/dist/providers/amazonSagemaker.js +21 -3
- package/dist/providers/anthropic.d.ts +4 -1
- package/dist/providers/anthropic.js +18 -5
- package/dist/providers/azureOpenai.d.ts +2 -1
- package/dist/providers/azureOpenai.js +10 -5
- package/dist/providers/googleAiStudio.d.ts +4 -1
- package/dist/providers/googleAiStudio.js +6 -7
- package/dist/providers/googleVertex.d.ts +3 -1
- package/dist/providers/googleVertex.js +96 -17
- package/dist/providers/huggingFace.d.ts +2 -1
- package/dist/providers/huggingFace.js +4 -4
- package/dist/providers/litellm.d.ts +5 -1
- package/dist/providers/litellm.js +16 -11
- package/dist/providers/mistral.d.ts +2 -1
- package/dist/providers/mistral.js +2 -2
- package/dist/providers/ollama.d.ts +3 -1
- package/dist/providers/ollama.js +2 -2
- package/dist/providers/openAI.d.ts +5 -1
- package/dist/providers/openAI.js +15 -5
- package/dist/providers/openRouter.d.ts +5 -1
- package/dist/providers/openRouter.js +19 -7
- package/dist/providers/openaiCompatible.d.ts +4 -1
- package/dist/providers/openaiCompatible.js +18 -4
- package/dist/rag/errors/RAGError.d.ts +1 -1
- package/dist/tasks/autoresearchTaskExecutor.d.ts +32 -0
- package/dist/tasks/autoresearchTaskExecutor.js +302 -0
- package/dist/tasks/errors.d.ts +3 -1
- package/dist/tasks/errors.js +1 -0
- package/dist/tasks/taskExecutor.d.ts +4 -2
- package/dist/tasks/taskExecutor.js +8 -1
- package/dist/tasks/taskManager.js +27 -3
- package/dist/tasks/tools/taskTools.d.ts +1 -1
- package/dist/telemetry/attributes.d.ts +15 -0
- package/dist/telemetry/attributes.js +16 -0
- package/dist/telemetry/tracers.d.ts +1 -0
- package/dist/telemetry/tracers.js +1 -0
- package/dist/types/autoresearchTypes.d.ts +194 -0
- package/dist/types/autoresearchTypes.js +17 -0
- package/dist/types/common.d.ts +11 -0
- package/dist/types/configTypes.d.ts +7 -0
- package/dist/types/generateTypes.d.ts +13 -0
- package/dist/types/index.d.ts +16 -14
- package/dist/types/index.js +21 -17
- package/dist/types/providers.d.ts +75 -0
- package/dist/types/streamTypes.d.ts +7 -1
- package/dist/types/taskTypes.d.ts +38 -0
- package/package.json +3 -2
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research state persistence — file-backed JSON store.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
7
|
+
import { AutoresearchError } from "./errors.js";
|
|
8
|
+
export class ResearchStateStore {
|
|
9
|
+
filePath;
|
|
10
|
+
constructor(repoPath, statePath) {
|
|
11
|
+
this.filePath = path.join(repoPath, statePath);
|
|
12
|
+
}
|
|
13
|
+
async load() {
|
|
14
|
+
if (!existsSync(this.filePath)) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const raw = readFileSync(this.filePath, "utf-8");
|
|
19
|
+
const parsed = JSON.parse(raw);
|
|
20
|
+
// Validate required fields
|
|
21
|
+
const requiredFields = [
|
|
22
|
+
"branch",
|
|
23
|
+
"currentPhase",
|
|
24
|
+
"runCount",
|
|
25
|
+
"keepCount",
|
|
26
|
+
"tag",
|
|
27
|
+
"startedAt",
|
|
28
|
+
"updatedAt",
|
|
29
|
+
];
|
|
30
|
+
for (const field of requiredFields) {
|
|
31
|
+
if (!(field in parsed)) {
|
|
32
|
+
throw AutoresearchError.create("STATE_CORRUPT", `State file missing required field: ${field}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!Number.isInteger(parsed.runCount) ||
|
|
36
|
+
parsed.runCount < 0 ||
|
|
37
|
+
!Number.isInteger(parsed.keepCount) ||
|
|
38
|
+
parsed.keepCount < 0) {
|
|
39
|
+
throw AutoresearchError.create("STATE_CORRUPT", `State file has invalid numeric fields: runCount=${parsed.runCount}, keepCount=${parsed.keepCount}`);
|
|
40
|
+
}
|
|
41
|
+
const validPhases = [
|
|
42
|
+
"bootstrap",
|
|
43
|
+
"baseline",
|
|
44
|
+
"propose",
|
|
45
|
+
"edit",
|
|
46
|
+
"commit",
|
|
47
|
+
"run",
|
|
48
|
+
"evaluate",
|
|
49
|
+
"record",
|
|
50
|
+
"accept_or_revert",
|
|
51
|
+
];
|
|
52
|
+
if (!validPhases.includes(parsed.currentPhase)) {
|
|
53
|
+
throw AutoresearchError.create("STATE_CORRUPT", `State file has invalid currentPhase: ${parsed.currentPhase}`);
|
|
54
|
+
}
|
|
55
|
+
if (isNaN(Date.parse(parsed.startedAt)) ||
|
|
56
|
+
isNaN(Date.parse(parsed.updatedAt))) {
|
|
57
|
+
throw AutoresearchError.create("STATE_CORRUPT", "State file has invalid timestamp fields");
|
|
58
|
+
}
|
|
59
|
+
return parsed;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Don't double-wrap our own validation errors
|
|
63
|
+
if (error instanceof Error && error.message.includes("AUTORESEARCH")) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
throw AutoresearchError.create("STATE_CORRUPT", `Failed to parse state file: ${this.filePath}`, {
|
|
67
|
+
cause: error instanceof Error ? error : undefined,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async save(state) {
|
|
72
|
+
const dir = path.dirname(this.filePath);
|
|
73
|
+
if (!existsSync(dir)) {
|
|
74
|
+
mkdirSync(dir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
// Strip rawTail from lastSummary before persisting (it's arbitrary stdout/stderr,
|
|
77
|
+
// kept in run.log; storing it in state.json risks leaking sensitive output)
|
|
78
|
+
const stateToPersist = { ...state };
|
|
79
|
+
if (stateToPersist.lastSummary?.rawTail) {
|
|
80
|
+
stateToPersist.lastSummary = {
|
|
81
|
+
...stateToPersist.lastSummary,
|
|
82
|
+
rawTail: "[see run.log]",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Atomic write: write to temp file, then rename
|
|
86
|
+
const tmpPath = `${this.filePath}.tmp`;
|
|
87
|
+
try {
|
|
88
|
+
writeFileSync(tmpPath, JSON.stringify(stateToPersist, null, 2), "utf-8");
|
|
89
|
+
renameSync(tmpPath, this.filePath);
|
|
90
|
+
logger.debug("[Autoresearch] State saved", {
|
|
91
|
+
phase: state.currentPhase,
|
|
92
|
+
runCount: state.runCount,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
throw AutoresearchError.create("STATE_CORRUPT", `Failed to write state file: ${this.filePath}`, {
|
|
97
|
+
cause: error instanceof Error ? error : undefined,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async initialize(tag, branch) {
|
|
102
|
+
const now = new Date().toISOString();
|
|
103
|
+
const state = {
|
|
104
|
+
branch,
|
|
105
|
+
acceptedCommit: null,
|
|
106
|
+
baselineMetric: null,
|
|
107
|
+
bestMetric: null,
|
|
108
|
+
candidateCommit: null,
|
|
109
|
+
runCount: 0,
|
|
110
|
+
keepCount: 0,
|
|
111
|
+
lastStatus: null,
|
|
112
|
+
currentPhase: "bootstrap",
|
|
113
|
+
tag,
|
|
114
|
+
startedAt: now,
|
|
115
|
+
updatedAt: now,
|
|
116
|
+
};
|
|
117
|
+
await this.save(state);
|
|
118
|
+
logger.info("[Autoresearch] State initialized", { tag, branch });
|
|
119
|
+
return state;
|
|
120
|
+
}
|
|
121
|
+
async update(patch) {
|
|
122
|
+
const current = await this.load();
|
|
123
|
+
if (!current) {
|
|
124
|
+
throw AutoresearchError.create("STATE_NOT_FOUND", "Cannot update: no state file found");
|
|
125
|
+
}
|
|
126
|
+
// Validate patch fields before merging
|
|
127
|
+
const VALID_PHASES = [
|
|
128
|
+
"bootstrap",
|
|
129
|
+
"baseline",
|
|
130
|
+
"propose",
|
|
131
|
+
"edit",
|
|
132
|
+
"commit",
|
|
133
|
+
"run",
|
|
134
|
+
"evaluate",
|
|
135
|
+
"record",
|
|
136
|
+
"accept_or_revert",
|
|
137
|
+
];
|
|
138
|
+
if (patch.runCount !== undefined &&
|
|
139
|
+
(!Number.isInteger(patch.runCount) || patch.runCount < 0)) {
|
|
140
|
+
throw AutoresearchError.create("STATE_CORRUPT", `Invalid runCount: ${patch.runCount}`);
|
|
141
|
+
}
|
|
142
|
+
if (patch.keepCount !== undefined &&
|
|
143
|
+
(!Number.isInteger(patch.keepCount) || patch.keepCount < 0)) {
|
|
144
|
+
throw AutoresearchError.create("STATE_CORRUPT", `Invalid keepCount: ${patch.keepCount}`);
|
|
145
|
+
}
|
|
146
|
+
if (patch.currentPhase !== undefined &&
|
|
147
|
+
!VALID_PHASES.includes(patch.currentPhase)) {
|
|
148
|
+
throw AutoresearchError.create("STATE_CORRUPT", `Invalid currentPhase: ${patch.currentPhase}`);
|
|
149
|
+
}
|
|
150
|
+
if (patch.bestMetric !== undefined &&
|
|
151
|
+
patch.bestMetric !== null &&
|
|
152
|
+
!Number.isFinite(patch.bestMetric)) {
|
|
153
|
+
throw AutoresearchError.create("STATE_CORRUPT", `Invalid bestMetric: ${patch.bestMetric}`);
|
|
154
|
+
}
|
|
155
|
+
const updated = {
|
|
156
|
+
...current,
|
|
157
|
+
...patch,
|
|
158
|
+
updatedAt: new Date().toISOString(),
|
|
159
|
+
};
|
|
160
|
+
await this.save(updated);
|
|
161
|
+
return updated;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=stateStore.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic experiment log parser.
|
|
3
|
+
*
|
|
4
|
+
* Extracts metrics from run.log output. Never throws — returns
|
|
5
|
+
* crashed/timedOut summary on parse failure.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExperimentSummary, MetricConfig, MemoryMetricConfig } from "../types/autoresearchTypes.js";
|
|
8
|
+
/**
|
|
9
|
+
* Parse experiment output into a structured summary.
|
|
10
|
+
*
|
|
11
|
+
* This function is deterministic and pure — no side effects, no throws.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseExperimentSummary(logContent: string, metricConfig: MetricConfig, memoryConfig?: MemoryMetricConfig, options?: {
|
|
14
|
+
timedOut?: boolean;
|
|
15
|
+
exitCode?: number;
|
|
16
|
+
}): ExperimentSummary;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic experiment log parser.
|
|
3
|
+
*
|
|
4
|
+
* Extracts metrics from run.log output. Never throws — returns
|
|
5
|
+
* crashed/timedOut summary on parse failure.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse experiment output into a structured summary.
|
|
9
|
+
*
|
|
10
|
+
* This function is deterministic and pure — no side effects, no throws.
|
|
11
|
+
*/
|
|
12
|
+
export function parseExperimentSummary(logContent, metricConfig, memoryConfig, options) {
|
|
13
|
+
const lines = logContent.split("\n");
|
|
14
|
+
const tailLines = lines.slice(-50);
|
|
15
|
+
const rawTail = tailLines.join("\n");
|
|
16
|
+
// Check for crash indicators (only if not already determined by exit code)
|
|
17
|
+
let crashed = options?.exitCode !== undefined &&
|
|
18
|
+
options.exitCode !== 0 &&
|
|
19
|
+
!options?.timedOut;
|
|
20
|
+
if (!crashed) {
|
|
21
|
+
const lastMeaningfulLine = [...lines]
|
|
22
|
+
.reverse()
|
|
23
|
+
.find((l) => l.trim().length > 0)
|
|
24
|
+
?.trim() ?? "";
|
|
25
|
+
crashed =
|
|
26
|
+
lastMeaningfulLine === "FAIL" ||
|
|
27
|
+
lastMeaningfulLine.toLowerCase().includes("traceback") ||
|
|
28
|
+
lastMeaningfulLine.toLowerCase().includes("error:");
|
|
29
|
+
}
|
|
30
|
+
// Parse primary metric
|
|
31
|
+
let metric = null;
|
|
32
|
+
try {
|
|
33
|
+
const regex = new RegExp(metricConfig.pattern, "m");
|
|
34
|
+
const match = regex.exec(logContent);
|
|
35
|
+
if (match && match[1]) {
|
|
36
|
+
const parsed = parseFloat(match[1]);
|
|
37
|
+
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
38
|
+
metric = parsed;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Invalid regex — treat as parse failure
|
|
44
|
+
}
|
|
45
|
+
// Parse memory metric
|
|
46
|
+
let memoryValue = null;
|
|
47
|
+
if (memoryConfig) {
|
|
48
|
+
try {
|
|
49
|
+
const regex = new RegExp(memoryConfig.pattern, "m");
|
|
50
|
+
const match = regex.exec(logContent);
|
|
51
|
+
if (match && match[1]) {
|
|
52
|
+
const parsed = parseFloat(match[1]);
|
|
53
|
+
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
54
|
+
memoryValue = parsed;
|
|
55
|
+
// Convert MB to GB if the name suggests MB.
|
|
56
|
+
// Uses binary divisor (1024 = MiB→GiB). For decimal MB→GB use 1000.
|
|
57
|
+
// The 1024 convention matches GPU monitoring tools (nvidia-smi, etc.).
|
|
58
|
+
const MIB_TO_GIB_DIVISOR = 1024;
|
|
59
|
+
if (memoryConfig.name.toLowerCase().includes("mb")) {
|
|
60
|
+
memoryValue =
|
|
61
|
+
Math.round((memoryValue / MIB_TO_GIB_DIVISOR) * 100) / 100;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Invalid regex — treat as parse failure
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Parse training time
|
|
71
|
+
let trainingSeconds = null;
|
|
72
|
+
try {
|
|
73
|
+
const timeRegex = /^training_seconds:\s+([\d.]+)/m;
|
|
74
|
+
const match = timeRegex.exec(logContent);
|
|
75
|
+
if (match && match[1]) {
|
|
76
|
+
trainingSeconds = parseFloat(match[1]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Ignore
|
|
81
|
+
}
|
|
82
|
+
// Only treat as timeout if explicitly signaled by the runner — don't infer from missing metric
|
|
83
|
+
const timedOut = options?.timedOut ?? false;
|
|
84
|
+
// Missing metric without explicit timeout is a crash (regex failure, spawn error, etc.)
|
|
85
|
+
const finalCrashed = crashed || (metric === null && !timedOut);
|
|
86
|
+
return {
|
|
87
|
+
crashed: finalCrashed,
|
|
88
|
+
timedOut,
|
|
89
|
+
metric,
|
|
90
|
+
memoryValue,
|
|
91
|
+
trainingSeconds,
|
|
92
|
+
rawTail,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=summaryParser.js.map
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research tools factory for AutoResearch system.
|
|
3
|
+
*
|
|
4
|
+
* These tools allow an AI agent to conduct autonomous experiments:
|
|
5
|
+
* reading/writing code, running experiments, recording results, and
|
|
6
|
+
* managing the research lifecycle (accept/revert/checkpoint).
|
|
7
|
+
*
|
|
8
|
+
* @module autoresearch/tools
|
|
9
|
+
*/
|
|
10
|
+
import type { ExperimentRecord, ResearchConfig } from "../types/autoresearchTypes.js";
|
|
11
|
+
import type { RepoPolicy } from "./repoPolicy.js";
|
|
12
|
+
import type { ResultRecorder } from "./resultRecorder.js";
|
|
13
|
+
import type { ExperimentRunner } from "./runner.js";
|
|
14
|
+
import type { ResearchStateStore } from "./stateStore.js";
|
|
15
|
+
/**
|
|
16
|
+
* Dependencies required to create research tools.
|
|
17
|
+
*/
|
|
18
|
+
export type ResearchToolsDeps = {
|
|
19
|
+
config: ResearchConfig;
|
|
20
|
+
stateStore: ResearchStateStore;
|
|
21
|
+
repoPolicy: RepoPolicy;
|
|
22
|
+
runner: ExperimentRunner;
|
|
23
|
+
recorder: ResultRecorder;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Create research management tools bound to a research session.
|
|
27
|
+
*
|
|
28
|
+
* These tools follow the same factory pattern as `createTaskTools()` in
|
|
29
|
+
* `src/lib/tasks/tools/taskTools.ts`. Dependencies are captured via closure,
|
|
30
|
+
* eliminating the need for module-level singleton state.
|
|
31
|
+
*
|
|
32
|
+
* @param deps - The research dependencies to bind to
|
|
33
|
+
* @returns Record of tool name to tool definition
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const tools = createResearchTools({ config, stateStore, repoPolicy, runner, recorder });
|
|
38
|
+
* // tools.research_get_context, tools.research_read_file, etc.
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function createResearchTools(deps: ResearchToolsDeps): {
|
|
42
|
+
/**
|
|
43
|
+
* Get current research context including state, config, and recent results.
|
|
44
|
+
*/
|
|
45
|
+
research_get_context: import("ai").Tool<Record<string, never>, {
|
|
46
|
+
success: boolean;
|
|
47
|
+
error: string;
|
|
48
|
+
branch?: undefined;
|
|
49
|
+
acceptedCommit?: undefined;
|
|
50
|
+
bestMetric?: undefined;
|
|
51
|
+
recentResults?: undefined;
|
|
52
|
+
mutablePaths?: undefined;
|
|
53
|
+
immutablePaths?: undefined;
|
|
54
|
+
currentPhase?: undefined;
|
|
55
|
+
runCount?: undefined;
|
|
56
|
+
tag?: undefined;
|
|
57
|
+
keepCount?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
success: boolean;
|
|
60
|
+
branch: string;
|
|
61
|
+
acceptedCommit: string | null;
|
|
62
|
+
bestMetric: number | null;
|
|
63
|
+
recentResults: ExperimentRecord[];
|
|
64
|
+
mutablePaths: string[];
|
|
65
|
+
immutablePaths: string[];
|
|
66
|
+
currentPhase: import("../types/autoresearchTypes.js").ExperimentPhase;
|
|
67
|
+
runCount: number;
|
|
68
|
+
tag: string;
|
|
69
|
+
keepCount: number;
|
|
70
|
+
error?: undefined;
|
|
71
|
+
}>;
|
|
72
|
+
/**
|
|
73
|
+
* Read a file from the repository if allowed by policy.
|
|
74
|
+
*/
|
|
75
|
+
research_read_file: import("ai").Tool<{
|
|
76
|
+
path: string;
|
|
77
|
+
}, {
|
|
78
|
+
success: boolean;
|
|
79
|
+
error: string;
|
|
80
|
+
path?: undefined;
|
|
81
|
+
content?: undefined;
|
|
82
|
+
} | {
|
|
83
|
+
success: boolean;
|
|
84
|
+
path: string;
|
|
85
|
+
content: string;
|
|
86
|
+
error?: undefined;
|
|
87
|
+
} | {
|
|
88
|
+
success: boolean;
|
|
89
|
+
error: string;
|
|
90
|
+
path: string;
|
|
91
|
+
content?: undefined;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* Write a candidate file to the repository if allowed by policy.
|
|
95
|
+
*/
|
|
96
|
+
research_write_candidate: import("ai").Tool<{
|
|
97
|
+
path: string;
|
|
98
|
+
content: string;
|
|
99
|
+
}, {
|
|
100
|
+
success: boolean;
|
|
101
|
+
error: string;
|
|
102
|
+
path?: undefined;
|
|
103
|
+
bytesWritten?: undefined;
|
|
104
|
+
} | {
|
|
105
|
+
success: boolean;
|
|
106
|
+
path: string;
|
|
107
|
+
bytesWritten: number;
|
|
108
|
+
error?: undefined;
|
|
109
|
+
} | {
|
|
110
|
+
success: boolean;
|
|
111
|
+
error: string;
|
|
112
|
+
path: string;
|
|
113
|
+
bytesWritten?: undefined;
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* Get git diff of mutable paths only.
|
|
117
|
+
*/
|
|
118
|
+
research_diff: import("ai").Tool<Record<string, never>, {
|
|
119
|
+
success: boolean;
|
|
120
|
+
diff: string;
|
|
121
|
+
hasChanges: boolean;
|
|
122
|
+
error?: undefined;
|
|
123
|
+
} | {
|
|
124
|
+
success: boolean;
|
|
125
|
+
error: string;
|
|
126
|
+
diff?: undefined;
|
|
127
|
+
hasChanges?: undefined;
|
|
128
|
+
}>;
|
|
129
|
+
/**
|
|
130
|
+
* Commit staged changes as a candidate.
|
|
131
|
+
*/
|
|
132
|
+
research_commit_candidate: import("ai").Tool<{
|
|
133
|
+
message: string;
|
|
134
|
+
}, {
|
|
135
|
+
success: boolean;
|
|
136
|
+
error: string;
|
|
137
|
+
violations?: undefined;
|
|
138
|
+
candidateCommit?: undefined;
|
|
139
|
+
message?: undefined;
|
|
140
|
+
} | {
|
|
141
|
+
success: boolean;
|
|
142
|
+
error: string;
|
|
143
|
+
violations: string[];
|
|
144
|
+
candidateCommit?: undefined;
|
|
145
|
+
message?: undefined;
|
|
146
|
+
} | {
|
|
147
|
+
success: boolean;
|
|
148
|
+
candidateCommit: string;
|
|
149
|
+
message: string;
|
|
150
|
+
error?: undefined;
|
|
151
|
+
violations?: undefined;
|
|
152
|
+
}>;
|
|
153
|
+
/**
|
|
154
|
+
* Run the experiment.
|
|
155
|
+
*/
|
|
156
|
+
research_run_experiment: import("ai").Tool<{
|
|
157
|
+
description: string;
|
|
158
|
+
}, {
|
|
159
|
+
success: boolean;
|
|
160
|
+
description: string;
|
|
161
|
+
summary: import("../types/autoresearchTypes.js").ExperimentSummary;
|
|
162
|
+
error?: undefined;
|
|
163
|
+
} | {
|
|
164
|
+
success: boolean;
|
|
165
|
+
error: string;
|
|
166
|
+
description?: undefined;
|
|
167
|
+
summary?: undefined;
|
|
168
|
+
}>;
|
|
169
|
+
/**
|
|
170
|
+
* Parse the experiment log file.
|
|
171
|
+
*/
|
|
172
|
+
research_parse_log: import("ai").Tool<Record<string, never>, {
|
|
173
|
+
success: boolean;
|
|
174
|
+
summary: import("../types/autoresearchTypes.js").ExperimentSummary;
|
|
175
|
+
error?: undefined;
|
|
176
|
+
} | {
|
|
177
|
+
success: boolean;
|
|
178
|
+
error: string;
|
|
179
|
+
summary?: undefined;
|
|
180
|
+
}>;
|
|
181
|
+
/**
|
|
182
|
+
* Record an experiment result.
|
|
183
|
+
*/
|
|
184
|
+
research_record: import("ai").Tool<{
|
|
185
|
+
description: string;
|
|
186
|
+
}, {
|
|
187
|
+
success: boolean;
|
|
188
|
+
error: string;
|
|
189
|
+
record?: undefined;
|
|
190
|
+
} | {
|
|
191
|
+
success: boolean;
|
|
192
|
+
record: ExperimentRecord;
|
|
193
|
+
error?: undefined;
|
|
194
|
+
}>;
|
|
195
|
+
/**
|
|
196
|
+
* Accept the candidate commit as the new baseline.
|
|
197
|
+
*/
|
|
198
|
+
research_accept: import("ai").Tool<Record<string, never>, {
|
|
199
|
+
success: boolean;
|
|
200
|
+
error: string;
|
|
201
|
+
acceptedCommit?: undefined;
|
|
202
|
+
bestMetric?: undefined;
|
|
203
|
+
keepCount?: undefined;
|
|
204
|
+
} | {
|
|
205
|
+
success: boolean;
|
|
206
|
+
acceptedCommit: string;
|
|
207
|
+
bestMetric: number;
|
|
208
|
+
keepCount: number;
|
|
209
|
+
error?: undefined;
|
|
210
|
+
}>;
|
|
211
|
+
/**
|
|
212
|
+
* Revert to the accepted commit.
|
|
213
|
+
*/
|
|
214
|
+
research_revert: import("ai").Tool<Record<string, never>, {
|
|
215
|
+
success: boolean;
|
|
216
|
+
error: string;
|
|
217
|
+
revertedTo?: undefined;
|
|
218
|
+
} | {
|
|
219
|
+
success: boolean;
|
|
220
|
+
revertedTo: string;
|
|
221
|
+
error?: undefined;
|
|
222
|
+
}>;
|
|
223
|
+
/**
|
|
224
|
+
* Inspect the last 50 lines of the run log for debugging.
|
|
225
|
+
*/
|
|
226
|
+
research_inspect_failure: import("ai").Tool<Record<string, never>, {
|
|
227
|
+
success: boolean;
|
|
228
|
+
tail: string;
|
|
229
|
+
totalLines: number;
|
|
230
|
+
error?: undefined;
|
|
231
|
+
} | {
|
|
232
|
+
success: boolean;
|
|
233
|
+
error: string;
|
|
234
|
+
tail?: undefined;
|
|
235
|
+
totalLines?: undefined;
|
|
236
|
+
}>;
|
|
237
|
+
/**
|
|
238
|
+
* Save the current state to disk.
|
|
239
|
+
*/
|
|
240
|
+
research_checkpoint: import("ai").Tool<Record<string, never>, {
|
|
241
|
+
success: boolean;
|
|
242
|
+
error: string;
|
|
243
|
+
checkpointedAt?: undefined;
|
|
244
|
+
phase?: undefined;
|
|
245
|
+
runCount?: undefined;
|
|
246
|
+
} | {
|
|
247
|
+
success: boolean;
|
|
248
|
+
checkpointedAt: string;
|
|
249
|
+
phase: import("../types/autoresearchTypes.js").ExperimentPhase;
|
|
250
|
+
runCount: number;
|
|
251
|
+
error?: undefined;
|
|
252
|
+
}>;
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Type for the research tools returned by createResearchTools
|
|
256
|
+
*/
|
|
257
|
+
export type ResearchTools = ReturnType<typeof createResearchTools>;
|