@juspay/neurolink 9.52.0 → 9.54.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/adapters/tts/cartesiaHandler.d.ts +12 -0
- package/dist/adapters/tts/cartesiaHandler.js +130 -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 -326
- 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/commands/voiceServer.d.ts +6 -0
- package/dist/cli/commands/voiceServer.js +17 -0
- package/dist/cli/parser.js +7 -1
- package/dist/core/baseProvider.js +18 -0
- package/dist/evaluation/errors/EvaluationError.d.ts +1 -1
- package/dist/lib/adapters/tts/cartesiaHandler.d.ts +12 -0
- package/dist/lib/adapters/tts/cartesiaHandler.js +131 -0
- 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/evaluation/errors/EvaluationError.d.ts +1 -1
- package/dist/lib/files/fileTools.d.ts +1 -1
- package/dist/lib/neurolink.js +22 -2
- package/dist/lib/providers/azureOpenai.d.ts +4 -1
- package/dist/lib/providers/azureOpenai.js +9 -3
- package/dist/lib/providers/litellm.js +2 -2
- package/dist/lib/providers/openRouter.js +2 -2
- package/dist/lib/providers/openaiCompatible.js +3 -1
- package/dist/lib/server/voice/frameBus.d.ts +8 -0
- package/dist/lib/server/voice/frameBus.js +25 -0
- package/dist/lib/server/voice/turnManager.d.ts +15 -0
- package/dist/lib/server/voice/turnManager.js +36 -0
- package/dist/lib/server/voice/types.d.ts +20 -0
- package/dist/lib/server/voice/types.js +2 -0
- package/dist/lib/server/voice/voiceServerApp.d.ts +1 -0
- package/dist/lib/server/voice/voiceServerApp.js +118 -0
- package/dist/lib/server/voice/voiceWebSocketHandler.d.ts +11 -0
- package/dist/lib/server/voice/voiceWebSocketHandler.js +536 -0
- 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/index.d.ts +16 -14
- package/dist/lib/types/index.js +21 -17
- package/dist/lib/types/taskTypes.d.ts +38 -0
- package/dist/lib/workflow/config.d.ts +3 -3
- package/dist/neurolink.js +22 -2
- package/dist/providers/azureOpenai.d.ts +4 -1
- package/dist/providers/azureOpenai.js +9 -3
- package/dist/providers/litellm.js +2 -2
- package/dist/providers/openRouter.js +2 -2
- package/dist/providers/openaiCompatible.js +3 -1
- package/dist/rag/errors/RAGError.d.ts +1 -1
- package/dist/server/voice/frameBus.d.ts +8 -0
- package/dist/server/voice/frameBus.js +24 -0
- package/dist/server/voice/public/app.js +275 -0
- package/dist/server/voice/public/index.html +18 -0
- package/dist/server/voice/public/pcm-worklet.js +67 -0
- package/dist/server/voice/public/styles.css +102 -0
- package/dist/server/voice/turnManager.d.ts +15 -0
- package/dist/server/voice/turnManager.js +35 -0
- package/dist/server/voice/types.d.ts +20 -0
- package/dist/server/voice/types.js +1 -0
- package/dist/server/voice/voiceServerApp.d.ts +1 -0
- package/dist/server/voice/voiceServerApp.js +117 -0
- package/dist/server/voice/voiceWebSocketHandler.d.ts +11 -0
- package/dist/server/voice/voiceWebSocketHandler.js +535 -0
- 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/index.d.ts +16 -14
- package/dist/types/index.js +21 -17
- package/dist/types/taskTypes.d.ts +38 -0
- package/package.json +2 -1
|
@@ -776,6 +776,24 @@ export class BaseProvider {
|
|
|
776
776
|
},
|
|
777
777
|
responseTime: 0, // BaseProvider doesn't track response time directly
|
|
778
778
|
toolsUsed: result.toolsUsed || [],
|
|
779
|
+
// Map toolExecutions from EnhancedGenerateResult shape to TextGenerationResult shape
|
|
780
|
+
// Preserve original timing/status fields when present, fall back to safe defaults
|
|
781
|
+
toolExecutions: result.toolExecutions?.map((te) => {
|
|
782
|
+
const t = te;
|
|
783
|
+
return {
|
|
784
|
+
// Spread original fields first so normalized fields take precedence
|
|
785
|
+
...te,
|
|
786
|
+
toolName: te.name,
|
|
787
|
+
executionTime: typeof t.executionTime === "number"
|
|
788
|
+
? t.executionTime
|
|
789
|
+
: typeof t.duration === "number"
|
|
790
|
+
? t.duration
|
|
791
|
+
: 0,
|
|
792
|
+
success: typeof t.success === "boolean"
|
|
793
|
+
? t.success
|
|
794
|
+
: t.status === undefined || t.status === "success",
|
|
795
|
+
};
|
|
796
|
+
}),
|
|
779
797
|
enhancedWithTools: !!(result.toolsUsed && result.toolsUsed.length > 0),
|
|
780
798
|
analytics: result.analytics,
|
|
781
799
|
evaluation: result.evaluation,
|
|
@@ -69,7 +69,7 @@ export declare const evaluationErrors: {
|
|
|
69
69
|
/** Rate limit hit during evaluation */
|
|
70
70
|
readonly RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR";
|
|
71
71
|
};
|
|
72
|
-
create: (code: "
|
|
72
|
+
create: (code: "EVALUATION_FAILED" | "PARSE_ERROR" | "STRATEGY_NOT_FOUND" | "PROVIDER_ERROR" | "CONFIGURATION_ERROR" | "CUSTOM_EVALUATOR_ERROR" | "BATCH_EVALUATION_ERROR" | "AGGREGATION_ERROR" | "REGISTRY_ERROR" | "MAX_RETRIES_EXCEEDED" | "TIMEOUT_ERROR" | "RATE_LIMIT_ERROR", message: string, options?: {
|
|
73
73
|
retryable?: boolean;
|
|
74
74
|
details?: Record<string, unknown>;
|
|
75
75
|
cause?: Error;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
export declare function getCartesiaWsUrl(): string;
|
|
3
|
+
export declare class CartesiaStream extends EventEmitter {
|
|
4
|
+
private ws;
|
|
5
|
+
private contextId;
|
|
6
|
+
private isReady;
|
|
7
|
+
constructor(contextId: string);
|
|
8
|
+
ready(): Promise<void>;
|
|
9
|
+
send(text: string, cont?: boolean): void;
|
|
10
|
+
flush(): void;
|
|
11
|
+
close(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import WebSocket from "ws";
|
|
2
|
+
import { EventEmitter } from "events";
|
|
3
|
+
import { logger } from "../../utils/logger.js";
|
|
4
|
+
import { withTimeout } from "../../utils/async/withTimeout.js";
|
|
5
|
+
export function getCartesiaWsUrl() {
|
|
6
|
+
const baseUrl = process.env.CARTESIA_WS_BASE_URL ?? "wss://api.cartesia.ai/tts/websocket";
|
|
7
|
+
const cartesiaVersion = process.env.CARTESIA_API_VERSION ?? "2025-04-16";
|
|
8
|
+
const wsUrl = new URL(baseUrl);
|
|
9
|
+
wsUrl.searchParams.set("cartesia_version", cartesiaVersion);
|
|
10
|
+
return wsUrl.toString();
|
|
11
|
+
}
|
|
12
|
+
export class CartesiaStream extends EventEmitter {
|
|
13
|
+
ws = null;
|
|
14
|
+
contextId;
|
|
15
|
+
isReady = false;
|
|
16
|
+
constructor(contextId) {
|
|
17
|
+
super();
|
|
18
|
+
this.contextId = contextId;
|
|
19
|
+
const apiKey = process.env.CARTESIA_API_KEY;
|
|
20
|
+
if (!apiKey) {
|
|
21
|
+
throw new Error("CARTESIA_API_KEY is not set in environment");
|
|
22
|
+
}
|
|
23
|
+
this.ws = new WebSocket(getCartesiaWsUrl(), {
|
|
24
|
+
headers: { "X-API-Key": apiKey },
|
|
25
|
+
});
|
|
26
|
+
this.ws.on("open", () => {
|
|
27
|
+
this.isReady = true;
|
|
28
|
+
logger.info("[CARTESIA] WS connected");
|
|
29
|
+
this.emit("ready");
|
|
30
|
+
});
|
|
31
|
+
this.ws.on("message", (data) => {
|
|
32
|
+
let msg;
|
|
33
|
+
try {
|
|
34
|
+
msg = JSON.parse(data.toString());
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
logger.error("[CARTESIA] Failed to parse message");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Handle error first so it always surfaces, even mid-stream
|
|
41
|
+
if (msg.error) {
|
|
42
|
+
const err = new Error(msg.error);
|
|
43
|
+
if (this.listenerCount("error") > 0) {
|
|
44
|
+
this.emit("error", err);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
logger.error("[CARTESIA] Unhandled error:", msg.error);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (msg.data) {
|
|
52
|
+
const audio = Buffer.from(msg.data, "base64");
|
|
53
|
+
this.emit("audio", audio);
|
|
54
|
+
}
|
|
55
|
+
if (msg.done) {
|
|
56
|
+
this.emit("done");
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
this.ws.on("error", (err) => {
|
|
60
|
+
if (this.listenerCount("error") > 0) {
|
|
61
|
+
this.emit("error", err);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
logger.error("[CARTESIA] Unhandled WebSocket error:", err.message);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
this.ws.on("close", () => {
|
|
68
|
+
this.isReady = false;
|
|
69
|
+
this.emit("close");
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async ready() {
|
|
73
|
+
if (this.isReady) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const connectPromise = new Promise((resolve, reject) => {
|
|
77
|
+
if (!this.ws) {
|
|
78
|
+
reject(new Error("Cartesia WebSocket is not initialized"));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.ws.once("open", resolve);
|
|
82
|
+
this.ws.once("error", reject);
|
|
83
|
+
this.ws.once("close", () => reject(new Error("Cartesia WebSocket closed before ready")));
|
|
84
|
+
});
|
|
85
|
+
return withTimeout(connectPromise, 5000, "Cartesia WS connect timed out");
|
|
86
|
+
}
|
|
87
|
+
send(text, cont = true) {
|
|
88
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.ws.send(JSON.stringify({
|
|
92
|
+
context_id: this.contextId,
|
|
93
|
+
model_id: "sonic-3",
|
|
94
|
+
transcript: text,
|
|
95
|
+
voice: {
|
|
96
|
+
mode: "id",
|
|
97
|
+
id: "694f9389-aac1-45b6-b726-9d9369183238",
|
|
98
|
+
},
|
|
99
|
+
output_format: {
|
|
100
|
+
container: "raw",
|
|
101
|
+
encoding: "pcm_s16le",
|
|
102
|
+
sample_rate: 24000,
|
|
103
|
+
},
|
|
104
|
+
continue: cont,
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
flush() {
|
|
108
|
+
this.send("", false);
|
|
109
|
+
}
|
|
110
|
+
close() {
|
|
111
|
+
if (!this.ws) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const ws = this.ws;
|
|
115
|
+
this.ws = null;
|
|
116
|
+
this.isReady = false;
|
|
117
|
+
if (ws.readyState === WebSocket.OPEN ||
|
|
118
|
+
ws.readyState === WebSocket.CONNECTING) {
|
|
119
|
+
try {
|
|
120
|
+
ws.close();
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
logger.warn("[CARTESIA] Failed to close WebSocket cleanly", error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
ws.once("close", () => {
|
|
127
|
+
ws.removeAllListeners();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=cartesiaHandler.js.map
|
|
@@ -101,7 +101,7 @@ export declare const directAgentTools: {
|
|
|
101
101
|
writeFile: import("ai").Tool<{
|
|
102
102
|
path: string;
|
|
103
103
|
content: string;
|
|
104
|
-
mode: "
|
|
104
|
+
mode: "append" | "create" | "overwrite";
|
|
105
105
|
}, {
|
|
106
106
|
success: boolean;
|
|
107
107
|
error: string;
|
|
@@ -112,7 +112,7 @@ export declare const directAgentTools: {
|
|
|
112
112
|
} | {
|
|
113
113
|
success: boolean;
|
|
114
114
|
path: string;
|
|
115
|
-
mode: "
|
|
115
|
+
mode: "append" | "create" | "overwrite";
|
|
116
116
|
size: number;
|
|
117
117
|
written: number;
|
|
118
118
|
error?: undefined;
|
|
@@ -55,7 +55,7 @@ export declare const AuthError: {
|
|
|
55
55
|
readonly JWKS_FETCH_FAILED: "AUTH-070";
|
|
56
56
|
readonly JWKS_KEY_NOT_FOUND: "AUTH-071";
|
|
57
57
|
};
|
|
58
|
-
create: (code: "SESSION_NOT_FOUND" | "
|
|
58
|
+
create: (code: "SESSION_NOT_FOUND" | "CONFIGURATION_ERROR" | "RATE_LIMITED" | "PROVIDER_ERROR" | "MIDDLEWARE_ERROR" | "INVALID_TOKEN" | "EXPIRED_TOKEN" | "MISSING_TOKEN" | "TOKEN_DECODE_FAILED" | "INVALID_SIGNATURE" | "SESSION_EXPIRED" | "SESSION_REVOKED" | "INSUFFICIENT_PERMISSIONS" | "INSUFFICIENT_ROLES" | "ACCESS_DENIED" | "USER_NOT_FOUND" | "USER_DISABLED" | "EMAIL_NOT_VERIFIED" | "MFA_REQUIRED" | "PROVIDER_NOT_FOUND" | "PROVIDER_INIT_FAILED" | "CREATION_FAILED" | "REGISTRATION_FAILED" | "DUPLICATE_REGISTRATION" | "JWKS_FETCH_FAILED" | "JWKS_KEY_NOT_FOUND", message: string, options?: {
|
|
59
59
|
retryable?: boolean;
|
|
60
60
|
details?: Record<string, unknown>;
|
|
61
61
|
cause?: Error;
|
|
@@ -31,7 +31,7 @@ export declare const AuthMiddlewareError: {
|
|
|
31
31
|
readonly PROVIDER_ERROR: "AUTH_MIDDLEWARE-005";
|
|
32
32
|
readonly CONFIGURATION_ERROR: "AUTH_MIDDLEWARE-006";
|
|
33
33
|
};
|
|
34
|
-
create: (code: "
|
|
34
|
+
create: (code: "CONFIGURATION_ERROR" | "UNAUTHORIZED" | "FORBIDDEN" | "PROVIDER_ERROR" | "INVALID_TOKEN" | "MISSING_TOKEN", message: string, options?: {
|
|
35
35
|
retryable?: boolean;
|
|
36
36
|
details?: Record<string, unknown>;
|
|
37
37
|
cause?: Error;
|
|
@@ -44,7 +44,7 @@ export declare const AuthProviderError: {
|
|
|
44
44
|
readonly JWKS_FETCH_FAILED: "AUTH-070";
|
|
45
45
|
readonly JWKS_KEY_NOT_FOUND: "AUTH-071";
|
|
46
46
|
};
|
|
47
|
-
create: (code: "SESSION_NOT_FOUND" | "
|
|
47
|
+
create: (code: "SESSION_NOT_FOUND" | "CONFIGURATION_ERROR" | "RATE_LIMITED" | "PROVIDER_ERROR" | "MIDDLEWARE_ERROR" | "INVALID_TOKEN" | "EXPIRED_TOKEN" | "MISSING_TOKEN" | "TOKEN_DECODE_FAILED" | "INVALID_SIGNATURE" | "SESSION_EXPIRED" | "SESSION_REVOKED" | "INSUFFICIENT_PERMISSIONS" | "INSUFFICIENT_ROLES" | "ACCESS_DENIED" | "USER_NOT_FOUND" | "USER_DISABLED" | "EMAIL_NOT_VERIFIED" | "MFA_REQUIRED" | "PROVIDER_NOT_FOUND" | "PROVIDER_INIT_FAILED" | "CREATION_FAILED" | "REGISTRATION_FAILED" | "DUPLICATE_REGISTRATION" | "JWKS_FETCH_FAILED" | "JWKS_KEY_NOT_FOUND", message: string, options?: {
|
|
48
48
|
retryable?: boolean;
|
|
49
49
|
details?: Record<string, unknown>;
|
|
50
50
|
cause?: Error;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research configuration validation and resolution.
|
|
3
|
+
*/
|
|
4
|
+
import type { ResearchConfig } from "../types/autoresearchTypes.js";
|
|
5
|
+
export declare function resolveConfig(partial: Partial<ResearchConfig> & {
|
|
6
|
+
repoPath: string;
|
|
7
|
+
mutablePaths: string[];
|
|
8
|
+
runCommand: string;
|
|
9
|
+
metric: ResearchConfig["metric"];
|
|
10
|
+
}): ResearchConfig;
|
|
11
|
+
export declare function validateConfig(config: ResearchConfig): void;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research configuration validation and resolution.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, statSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
7
|
+
import { AutoresearchError } from "./errors.js";
|
|
8
|
+
import { AUTORESEARCH_DEFAULTS } from "../types/autoresearchTypes.js";
|
|
9
|
+
export function resolveConfig(partial) {
|
|
10
|
+
const config = {
|
|
11
|
+
repoPath: path.resolve(partial.repoPath),
|
|
12
|
+
programPath: partial.programPath ?? AUTORESEARCH_DEFAULTS.programPath,
|
|
13
|
+
mutablePaths: partial.mutablePaths,
|
|
14
|
+
immutablePaths: partial.immutablePaths ?? [],
|
|
15
|
+
resultsPath: partial.resultsPath ?? AUTORESEARCH_DEFAULTS.resultsPath,
|
|
16
|
+
statePath: partial.statePath ?? AUTORESEARCH_DEFAULTS.statePath,
|
|
17
|
+
runCommand: partial.runCommand,
|
|
18
|
+
logPath: partial.logPath ?? AUTORESEARCH_DEFAULTS.logPath,
|
|
19
|
+
metric: partial.metric,
|
|
20
|
+
memoryMetric: partial.memoryMetric,
|
|
21
|
+
timeoutMs: partial.timeoutMs ?? AUTORESEARCH_DEFAULTS.timeoutMs,
|
|
22
|
+
branchPrefix: partial.branchPrefix ?? AUTORESEARCH_DEFAULTS.branchPrefix,
|
|
23
|
+
provider: partial.provider,
|
|
24
|
+
model: partial.model,
|
|
25
|
+
maxExperiments: partial.maxExperiments,
|
|
26
|
+
thinkingLevel: partial.thinkingLevel ?? AUTORESEARCH_DEFAULTS.thinkingLevel,
|
|
27
|
+
};
|
|
28
|
+
return config;
|
|
29
|
+
}
|
|
30
|
+
export function validateConfig(config) {
|
|
31
|
+
// Verify repoPath exists and is a directory
|
|
32
|
+
if (!existsSync(config.repoPath) ||
|
|
33
|
+
!statSync(config.repoPath).isDirectory()) {
|
|
34
|
+
throw AutoresearchError.create("CONFIG_INVALID", `repoPath does not exist or is not a directory: ${config.repoPath}`);
|
|
35
|
+
}
|
|
36
|
+
// Verify it's a git repo
|
|
37
|
+
if (!existsSync(path.join(config.repoPath, ".git"))) {
|
|
38
|
+
throw AutoresearchError.create("REPO_NOT_FOUND", `repoPath is not a git repository: ${config.repoPath}`);
|
|
39
|
+
}
|
|
40
|
+
// Verify mutablePaths is non-empty
|
|
41
|
+
if (config.mutablePaths.length === 0) {
|
|
42
|
+
throw AutoresearchError.create("CONFIG_INVALID", "mutablePaths must contain at least one path");
|
|
43
|
+
}
|
|
44
|
+
// Verify mutable and immutable don't overlap (normalize paths first)
|
|
45
|
+
const normMutable = config.mutablePaths.map((p) => path.normalize(p).replace(/\/+$/, ""));
|
|
46
|
+
const normImmutable = config.immutablePaths.map((p) => path.normalize(p).replace(/\/+$/, ""));
|
|
47
|
+
const overlap = normMutable.filter((p) => normImmutable.includes(p));
|
|
48
|
+
if (overlap.length > 0) {
|
|
49
|
+
throw AutoresearchError.create("CONFIG_INVALID", `mutablePaths and immutablePaths overlap: ${overlap.join(", ")}`);
|
|
50
|
+
}
|
|
51
|
+
// Verify metric pattern — length limit and basic ReDoS safety
|
|
52
|
+
const MAX_PATTERN_LENGTH = 200;
|
|
53
|
+
if (config.metric.pattern.length > MAX_PATTERN_LENGTH) {
|
|
54
|
+
throw AutoresearchError.create("CONFIG_INVALID", `metric.pattern exceeds ${MAX_PATTERN_LENGTH} characters: ${config.metric.pattern.slice(0, 50)}...`);
|
|
55
|
+
}
|
|
56
|
+
// Reject patterns with obvious catastrophic backtracking (nested quantifiers)
|
|
57
|
+
if (/(\+|\*|\{)\s*(\+|\*|\{)/.test(config.metric.pattern) ||
|
|
58
|
+
/\(\?[^)]*\)\+\+/.test(config.metric.pattern)) {
|
|
59
|
+
throw AutoresearchError.create("CONFIG_INVALID", `metric.pattern contains nested quantifiers (potential ReDoS): ${config.metric.pattern}`);
|
|
60
|
+
}
|
|
61
|
+
// Verify metric pattern is valid regex with exactly one capture group
|
|
62
|
+
try {
|
|
63
|
+
const _regex = new RegExp(config.metric.pattern);
|
|
64
|
+
const match = new RegExp(config.metric.pattern + "|").exec("");
|
|
65
|
+
const groupCount = (match?.length ?? 1) - 1;
|
|
66
|
+
if (groupCount !== 1) {
|
|
67
|
+
throw AutoresearchError.create("CONFIG_INVALID", `metric.pattern must have exactly one capture group, found ${groupCount}: ${config.metric.pattern}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error instanceof Error &&
|
|
72
|
+
"code" in error &&
|
|
73
|
+
typeof error.code === "string") {
|
|
74
|
+
throw error; // Rethrow structured AutoresearchError
|
|
75
|
+
}
|
|
76
|
+
throw AutoresearchError.create("CONFIG_INVALID", `metric.pattern is not a valid regex: ${config.metric.pattern}`);
|
|
77
|
+
}
|
|
78
|
+
// Validate memoryMetric.pattern with the same checks if present
|
|
79
|
+
if (config.memoryMetric) {
|
|
80
|
+
if (config.memoryMetric.pattern.length > MAX_PATTERN_LENGTH) {
|
|
81
|
+
throw AutoresearchError.create("CONFIG_INVALID", `memoryMetric.pattern exceeds ${MAX_PATTERN_LENGTH} characters`);
|
|
82
|
+
}
|
|
83
|
+
if (/(\+|\*|\{)\s*(\+|\*|\{)/.test(config.memoryMetric.pattern) ||
|
|
84
|
+
/\(\?[^)]*\)\+\+/.test(config.memoryMetric.pattern)) {
|
|
85
|
+
throw AutoresearchError.create("CONFIG_INVALID", `memoryMetric.pattern contains nested quantifiers (potential ReDoS)`);
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const _memRegex = new RegExp(config.memoryMetric.pattern);
|
|
89
|
+
const memMatch = new RegExp(config.memoryMetric.pattern + "|").exec("");
|
|
90
|
+
const memGroupCount = (memMatch?.length ?? 1) - 1;
|
|
91
|
+
if (memGroupCount !== 1) {
|
|
92
|
+
throw AutoresearchError.create("CONFIG_INVALID", `memoryMetric.pattern must have exactly one capture group, found ${memGroupCount}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error instanceof Error &&
|
|
97
|
+
"code" in error &&
|
|
98
|
+
typeof error.code === "string") {
|
|
99
|
+
throw error; // Rethrow structured AutoresearchError
|
|
100
|
+
}
|
|
101
|
+
throw AutoresearchError.create("CONFIG_INVALID", `memoryMetric.pattern is not a valid regex: ${config.memoryMetric.pattern}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
logger.info("[Autoresearch] Config validated", {
|
|
105
|
+
repoPath: config.repoPath,
|
|
106
|
+
mutablePaths: config.mutablePaths,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error definitions for the NeuroLink AutoResearch system.
|
|
3
|
+
*/
|
|
4
|
+
export declare const AutoresearchErrorCodes: {
|
|
5
|
+
readonly CONFIG_INVALID: "AUTORESEARCH-001";
|
|
6
|
+
readonly STATE_CORRUPT: "AUTORESEARCH-002";
|
|
7
|
+
readonly STATE_NOT_FOUND: "AUTORESEARCH-003";
|
|
8
|
+
readonly REPO_NOT_FOUND: "AUTORESEARCH-004";
|
|
9
|
+
readonly BRANCH_ERROR: "AUTORESEARCH-005";
|
|
10
|
+
readonly PATH_VIOLATION: "AUTORESEARCH-006";
|
|
11
|
+
readonly COMMIT_REJECTED: "AUTORESEARCH-007";
|
|
12
|
+
readonly EXPERIMENT_TIMEOUT: "AUTORESEARCH-008";
|
|
13
|
+
readonly EXPERIMENT_FAILED: "AUTORESEARCH-009";
|
|
14
|
+
readonly PARSE_FAILED: "AUTORESEARCH-010";
|
|
15
|
+
readonly RESULTS_WRITE_FAILED: "AUTORESEARCH-011";
|
|
16
|
+
readonly REVERT_FAILED: "AUTORESEARCH-012";
|
|
17
|
+
readonly WORKER_NOT_INITIALIZED: "AUTORESEARCH-013";
|
|
18
|
+
};
|
|
19
|
+
export declare const AutoresearchError: {
|
|
20
|
+
codes: {
|
|
21
|
+
readonly CONFIG_INVALID: "AUTORESEARCH-001";
|
|
22
|
+
readonly STATE_CORRUPT: "AUTORESEARCH-002";
|
|
23
|
+
readonly STATE_NOT_FOUND: "AUTORESEARCH-003";
|
|
24
|
+
readonly REPO_NOT_FOUND: "AUTORESEARCH-004";
|
|
25
|
+
readonly BRANCH_ERROR: "AUTORESEARCH-005";
|
|
26
|
+
readonly PATH_VIOLATION: "AUTORESEARCH-006";
|
|
27
|
+
readonly COMMIT_REJECTED: "AUTORESEARCH-007";
|
|
28
|
+
readonly EXPERIMENT_TIMEOUT: "AUTORESEARCH-008";
|
|
29
|
+
readonly EXPERIMENT_FAILED: "AUTORESEARCH-009";
|
|
30
|
+
readonly PARSE_FAILED: "AUTORESEARCH-010";
|
|
31
|
+
readonly RESULTS_WRITE_FAILED: "AUTORESEARCH-011";
|
|
32
|
+
readonly REVERT_FAILED: "AUTORESEARCH-012";
|
|
33
|
+
readonly WORKER_NOT_INITIALIZED: "AUTORESEARCH-013";
|
|
34
|
+
};
|
|
35
|
+
create: (code: "CONFIG_INVALID" | "STATE_CORRUPT" | "STATE_NOT_FOUND" | "REPO_NOT_FOUND" | "BRANCH_ERROR" | "PATH_VIOLATION" | "COMMIT_REJECTED" | "EXPERIMENT_TIMEOUT" | "EXPERIMENT_FAILED" | "PARSE_FAILED" | "RESULTS_WRITE_FAILED" | "REVERT_FAILED" | "WORKER_NOT_INITIALIZED", message: string, options?: {
|
|
36
|
+
retryable?: boolean;
|
|
37
|
+
details?: Record<string, unknown>;
|
|
38
|
+
cause?: Error;
|
|
39
|
+
} | undefined) => import("../core/infrastructure/baseError.js").NeuroLinkFeatureError;
|
|
40
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error definitions for the NeuroLink AutoResearch system.
|
|
3
|
+
*/
|
|
4
|
+
import { createErrorFactory } from "../core/infrastructure/baseError.js";
|
|
5
|
+
export const AutoresearchErrorCodes = {
|
|
6
|
+
CONFIG_INVALID: "AUTORESEARCH-001",
|
|
7
|
+
STATE_CORRUPT: "AUTORESEARCH-002",
|
|
8
|
+
STATE_NOT_FOUND: "AUTORESEARCH-003",
|
|
9
|
+
REPO_NOT_FOUND: "AUTORESEARCH-004",
|
|
10
|
+
BRANCH_ERROR: "AUTORESEARCH-005",
|
|
11
|
+
PATH_VIOLATION: "AUTORESEARCH-006",
|
|
12
|
+
COMMIT_REJECTED: "AUTORESEARCH-007",
|
|
13
|
+
EXPERIMENT_TIMEOUT: "AUTORESEARCH-008",
|
|
14
|
+
EXPERIMENT_FAILED: "AUTORESEARCH-009",
|
|
15
|
+
PARSE_FAILED: "AUTORESEARCH-010",
|
|
16
|
+
RESULTS_WRITE_FAILED: "AUTORESEARCH-011",
|
|
17
|
+
REVERT_FAILED: "AUTORESEARCH-012",
|
|
18
|
+
WORKER_NOT_INITIALIZED: "AUTORESEARCH-013",
|
|
19
|
+
};
|
|
20
|
+
export const AutoresearchError = createErrorFactory("Autoresearch", AutoresearchErrorCodes);
|
|
21
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink AutoResearch — Autonomous Experiment Engine
|
|
3
|
+
*
|
|
4
|
+
* An autonomous experiment loop that proposes code changes, executes
|
|
5
|
+
* experiments, evaluates results against a deterministic metric, and
|
|
6
|
+
* keeps or discards each change — running unattended for hours.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { resolveConfig, validateConfig, ResearchStateStore, RepoPolicy, ExperimentRunner, ResultRecorder } from "@juspay/neurolink/autoresearch";
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export { resolveConfig, validateConfig } from "./config.js";
|
|
14
|
+
export { ResearchStateStore } from "./stateStore.js";
|
|
15
|
+
export { RepoPolicy } from "./repoPolicy.js";
|
|
16
|
+
export { ExperimentRunner } from "./runner.js";
|
|
17
|
+
export { ResultRecorder } from "./resultRecorder.js";
|
|
18
|
+
export { parseExperimentSummary } from "./summaryParser.js";
|
|
19
|
+
export { getPhaseToolPolicy, getAllResearchToolNames } from "./phasePolicy.js";
|
|
20
|
+
export { PromptCompiler } from "./promptCompiler.js";
|
|
21
|
+
export { createResearchTools } from "./tools.js";
|
|
22
|
+
export { ResearchWorker } from "./worker.js";
|
|
23
|
+
export { AutoresearchError, AutoresearchErrorCodes } from "./errors.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink AutoResearch — Autonomous Experiment Engine
|
|
3
|
+
*
|
|
4
|
+
* An autonomous experiment loop that proposes code changes, executes
|
|
5
|
+
* experiments, evaluates results against a deterministic metric, and
|
|
6
|
+
* keeps or discards each change — running unattended for hours.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { resolveConfig, validateConfig, ResearchStateStore, RepoPolicy, ExperimentRunner, ResultRecorder } from "@juspay/neurolink/autoresearch";
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
// Configuration
|
|
14
|
+
export { resolveConfig, validateConfig } from "./config.js";
|
|
15
|
+
// State management
|
|
16
|
+
export { ResearchStateStore } from "./stateStore.js";
|
|
17
|
+
// Policy enforcement
|
|
18
|
+
export { RepoPolicy } from "./repoPolicy.js";
|
|
19
|
+
// Experiment execution
|
|
20
|
+
export { ExperimentRunner } from "./runner.js";
|
|
21
|
+
// Result tracking
|
|
22
|
+
export { ResultRecorder } from "./resultRecorder.js";
|
|
23
|
+
// Log parsing
|
|
24
|
+
export { parseExperimentSummary } from "./summaryParser.js";
|
|
25
|
+
// Phase policy
|
|
26
|
+
export { getPhaseToolPolicy, getAllResearchToolNames } from "./phasePolicy.js";
|
|
27
|
+
// Prompt compilation
|
|
28
|
+
export { PromptCompiler } from "./promptCompiler.js";
|
|
29
|
+
// Research tools
|
|
30
|
+
export { createResearchTools } from "./tools.js";
|
|
31
|
+
// Worker orchestrator
|
|
32
|
+
export { ResearchWorker } from "./worker.js";
|
|
33
|
+
// Errors
|
|
34
|
+
export { AutoresearchError, AutoresearchErrorCodes } from "./errors.js";
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase-based tool access policy for the autoresearch experiment loop.
|
|
3
|
+
*/
|
|
4
|
+
import type { ExperimentPhase, PhaseToolPolicy } from "../types/autoresearchTypes.js";
|
|
5
|
+
export declare function getPhaseToolPolicy(phase: ExperimentPhase): PhaseToolPolicy;
|
|
6
|
+
/**
|
|
7
|
+
* Returns all research tool names across all phases.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getAllResearchToolNames(): string[];
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase-based tool access policy for the autoresearch experiment loop.
|
|
3
|
+
*/
|
|
4
|
+
const PHASE_POLICIES = {
|
|
5
|
+
bootstrap: {
|
|
6
|
+
activeTools: [
|
|
7
|
+
"research_get_context",
|
|
8
|
+
"research_read_file",
|
|
9
|
+
"research_checkpoint",
|
|
10
|
+
],
|
|
11
|
+
forcedTool: "research_get_context",
|
|
12
|
+
},
|
|
13
|
+
baseline: {
|
|
14
|
+
activeTools: [
|
|
15
|
+
"research_run_experiment",
|
|
16
|
+
"research_parse_log",
|
|
17
|
+
"research_record",
|
|
18
|
+
"research_accept",
|
|
19
|
+
"research_checkpoint",
|
|
20
|
+
],
|
|
21
|
+
forcedTool: "research_run_experiment",
|
|
22
|
+
},
|
|
23
|
+
propose: {
|
|
24
|
+
activeTools: ["research_get_context", "research_read_file"],
|
|
25
|
+
forcedTool: "research_get_context",
|
|
26
|
+
},
|
|
27
|
+
edit: {
|
|
28
|
+
activeTools: [
|
|
29
|
+
"research_read_file",
|
|
30
|
+
"research_write_candidate",
|
|
31
|
+
"research_diff",
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
commit: {
|
|
35
|
+
activeTools: ["research_commit_candidate"],
|
|
36
|
+
forcedTool: "research_commit_candidate",
|
|
37
|
+
},
|
|
38
|
+
run: {
|
|
39
|
+
activeTools: ["research_run_experiment"],
|
|
40
|
+
forcedTool: "research_run_experiment",
|
|
41
|
+
},
|
|
42
|
+
evaluate: {
|
|
43
|
+
activeTools: ["research_parse_log", "research_inspect_failure"],
|
|
44
|
+
forcedTool: "research_parse_log",
|
|
45
|
+
},
|
|
46
|
+
record: {
|
|
47
|
+
activeTools: ["research_record", "research_checkpoint"],
|
|
48
|
+
forcedTool: "research_record",
|
|
49
|
+
},
|
|
50
|
+
accept_or_revert: {
|
|
51
|
+
activeTools: ["research_accept", "research_revert", "research_checkpoint"],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
export function getPhaseToolPolicy(phase) {
|
|
55
|
+
const p = PHASE_POLICIES[phase];
|
|
56
|
+
return { activeTools: [...p.activeTools], forcedTool: p.forcedTool };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns all research tool names across all phases.
|
|
60
|
+
*/
|
|
61
|
+
export function getAllResearchToolNames() {
|
|
62
|
+
const names = new Set();
|
|
63
|
+
for (const policy of Object.values(PHASE_POLICIES)) {
|
|
64
|
+
for (const tool of policy.activeTools) {
|
|
65
|
+
names.add(tool);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return [...names];
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=phasePolicy.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt compilation for the autoresearch worker.
|
|
3
|
+
*
|
|
4
|
+
* Reads program.md and combines it with current state and recent
|
|
5
|
+
* results to build the system prompt and per-cycle prompt.
|
|
6
|
+
*/
|
|
7
|
+
import type { ResearchConfig, ResearchState, ExperimentRecord } from "../types/autoresearchTypes.js";
|
|
8
|
+
export declare class PromptCompiler {
|
|
9
|
+
private config;
|
|
10
|
+
constructor(config: ResearchConfig);
|
|
11
|
+
/** Reads program.md and builds the system prompt */
|
|
12
|
+
buildSystemPrompt(): Promise<string>;
|
|
13
|
+
/** Builds the per-cycle prompt with current state + recent results */
|
|
14
|
+
buildCyclePrompt(state: ResearchState, recentResults: ExperimentRecord[]): Promise<string>;
|
|
15
|
+
}
|