wave-agent-sdk 0.0.1 → 0.0.2
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.d.ts +32 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +36 -3
- package/dist/managers/aiManager.d.ts +7 -1
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +18 -9
- package/dist/services/aiService.d.ts +5 -0
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +18 -14
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +4 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +16 -0
- package/dist/utils/configResolver.d.ts +38 -0
- package/dist/utils/configResolver.d.ts.map +1 -0
- package/dist/utils/configResolver.js +106 -0
- package/dist/utils/configValidator.d.ts +36 -0
- package/dist/utils/configValidator.d.ts.map +1 -0
- package/dist/utils/configValidator.js +78 -0
- package/dist/utils/constants.d.ts +10 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +10 -0
- package/package.json +11 -15
- package/src/agent.ts +77 -6
- package/src/managers/aiManager.ts +29 -14
- package/src/services/aiService.ts +49 -21
- package/src/services/session.ts +5 -0
- package/src/types.ts +75 -0
- package/src/utils/configResolver.ts +142 -0
- package/src/utils/configValidator.ts +133 -0
- package/src/utils/constants.ts +10 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration validator utilities for Agent Constructor Configuration
|
|
3
|
+
* Validates configuration values for correctness and security
|
|
4
|
+
*/
|
|
5
|
+
import { GatewayConfig } from "../types.js";
|
|
6
|
+
export declare class ConfigValidator {
|
|
7
|
+
/**
|
|
8
|
+
* Validates gateway configuration
|
|
9
|
+
* @param config - Configuration to validate
|
|
10
|
+
* @throws ConfigurationError with descriptive message if invalid
|
|
11
|
+
*/
|
|
12
|
+
static validateGatewayConfig(config: GatewayConfig): void;
|
|
13
|
+
/**
|
|
14
|
+
* Validates token limit value
|
|
15
|
+
* @param tokenLimit - Token limit to validate
|
|
16
|
+
* @throws ConfigurationError if invalid
|
|
17
|
+
*/
|
|
18
|
+
static validateTokenLimit(tokenLimit: number): void;
|
|
19
|
+
/**
|
|
20
|
+
* Validates model configuration (basic validation)
|
|
21
|
+
* @param agentModel - Agent model string
|
|
22
|
+
* @param fastModel - Fast model string
|
|
23
|
+
* @throws ConfigurationError if invalid
|
|
24
|
+
*/
|
|
25
|
+
static validateModelConfig(agentModel: string, fastModel: string): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Static configuration validator instance
|
|
29
|
+
* Implements ConfigurationValidator interface from types.ts
|
|
30
|
+
*/
|
|
31
|
+
export declare const configValidator: {
|
|
32
|
+
validateGatewayConfig: typeof ConfigValidator.validateGatewayConfig;
|
|
33
|
+
validateTokenLimit: typeof ConfigValidator.validateTokenLimit;
|
|
34
|
+
validateModelConfig: typeof ConfigValidator.validateModelConfig;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=configValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configValidator.d.ts","sourceRoot":"","sources":["../../src/utils/configValidator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAqC,MAAM,aAAa,CAAC;AAE/E,qBAAa,eAAe;IAC1B;;;;OAIG;IACH,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IA+CzD;;;;OAIG;IACH,MAAM,CAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IA0BnD;;;;;OAKG;IACH,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;CAyBxE;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;CAI3B,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration validator utilities for Agent Constructor Configuration
|
|
3
|
+
* Validates configuration values for correctness and security
|
|
4
|
+
*/
|
|
5
|
+
import { ConfigurationError, CONFIG_ERRORS } from "../types.js";
|
|
6
|
+
export class ConfigValidator {
|
|
7
|
+
/**
|
|
8
|
+
* Validates gateway configuration
|
|
9
|
+
* @param config - Configuration to validate
|
|
10
|
+
* @throws ConfigurationError with descriptive message if invalid
|
|
11
|
+
*/
|
|
12
|
+
static validateGatewayConfig(config) {
|
|
13
|
+
// Validate API key
|
|
14
|
+
if (!config.apiKey || typeof config.apiKey !== "string") {
|
|
15
|
+
throw new ConfigurationError(CONFIG_ERRORS.EMPTY_API_KEY, "apiKey", config.apiKey);
|
|
16
|
+
}
|
|
17
|
+
if (config.apiKey.trim() === "") {
|
|
18
|
+
throw new ConfigurationError(CONFIG_ERRORS.EMPTY_API_KEY, "apiKey", config.apiKey);
|
|
19
|
+
}
|
|
20
|
+
// Validate base URL
|
|
21
|
+
if (!config.baseURL || typeof config.baseURL !== "string") {
|
|
22
|
+
throw new ConfigurationError(CONFIG_ERRORS.EMPTY_BASE_URL, "baseURL", config.baseURL);
|
|
23
|
+
}
|
|
24
|
+
if (config.baseURL.trim() === "") {
|
|
25
|
+
throw new ConfigurationError(CONFIG_ERRORS.EMPTY_BASE_URL, "baseURL", config.baseURL);
|
|
26
|
+
}
|
|
27
|
+
// Basic URL format validation
|
|
28
|
+
try {
|
|
29
|
+
new URL(config.baseURL);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new ConfigurationError(`Base URL must be a valid URL format. Received: ${config.baseURL}`, "baseURL", config.baseURL);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validates token limit value
|
|
37
|
+
* @param tokenLimit - Token limit to validate
|
|
38
|
+
* @throws ConfigurationError if invalid
|
|
39
|
+
*/
|
|
40
|
+
static validateTokenLimit(tokenLimit) {
|
|
41
|
+
if (typeof tokenLimit !== "number") {
|
|
42
|
+
throw new ConfigurationError(CONFIG_ERRORS.INVALID_TOKEN_LIMIT, "tokenLimit", tokenLimit);
|
|
43
|
+
}
|
|
44
|
+
if (!Number.isInteger(tokenLimit)) {
|
|
45
|
+
throw new ConfigurationError(CONFIG_ERRORS.INVALID_TOKEN_LIMIT, "tokenLimit", tokenLimit);
|
|
46
|
+
}
|
|
47
|
+
if (tokenLimit <= 0) {
|
|
48
|
+
throw new ConfigurationError(CONFIG_ERRORS.INVALID_TOKEN_LIMIT, "tokenLimit", tokenLimit);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validates model configuration (basic validation)
|
|
53
|
+
* @param agentModel - Agent model string
|
|
54
|
+
* @param fastModel - Fast model string
|
|
55
|
+
* @throws ConfigurationError if invalid
|
|
56
|
+
*/
|
|
57
|
+
static validateModelConfig(agentModel, fastModel) {
|
|
58
|
+
if (!agentModel ||
|
|
59
|
+
typeof agentModel !== "string" ||
|
|
60
|
+
agentModel.trim() === "") {
|
|
61
|
+
throw new ConfigurationError("Agent model must be a non-empty string.", "agentModel", agentModel);
|
|
62
|
+
}
|
|
63
|
+
if (!fastModel ||
|
|
64
|
+
typeof fastModel !== "string" ||
|
|
65
|
+
fastModel.trim() === "") {
|
|
66
|
+
throw new ConfigurationError("Fast model must be a non-empty string.", "fastModel", fastModel);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Static configuration validator instance
|
|
72
|
+
* Implements ConfigurationValidator interface from types.ts
|
|
73
|
+
*/
|
|
74
|
+
export const configValidator = {
|
|
75
|
+
validateGatewayConfig: ConfigValidator.validateGatewayConfig,
|
|
76
|
+
validateTokenLimit: ConfigValidator.validateTokenLimit,
|
|
77
|
+
validateModelConfig: ConfigValidator.validateModelConfig,
|
|
78
|
+
};
|
|
@@ -22,6 +22,16 @@ export declare const USER_MEMORY_FILE: string;
|
|
|
22
22
|
* AI related constants
|
|
23
23
|
*/
|
|
24
24
|
export declare const DEFAULT_TOKEN_LIMIT = 64000;
|
|
25
|
+
/**
|
|
26
|
+
* @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
|
|
27
|
+
* They are maintained for backward compatibility with existing code that might still reference them,
|
|
28
|
+
* but the actual AI services now use configuration injection.
|
|
29
|
+
*/
|
|
25
30
|
export declare const FAST_MODEL_ID: string;
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
|
|
33
|
+
* They are maintained for backward compatibility with existing code that might still reference them,
|
|
34
|
+
* but the actual AI services now use configuration injection.
|
|
35
|
+
*/
|
|
26
36
|
export declare const AGENT_MODEL_ID: string;
|
|
27
37
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAmC,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAA0C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAA8C,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,eAAO,MAAM,aAAa,QAAoD,CAAC;AAE/E,eAAO,MAAM,cAAc,QAC2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAmC,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAA0C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAA8C,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAoD,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAC2B,CAAC"}
|
package/dist/utils/constants.js
CHANGED
|
@@ -24,5 +24,15 @@ export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "user-memory.md");
|
|
|
24
24
|
* AI related constants
|
|
25
25
|
*/
|
|
26
26
|
export const DEFAULT_TOKEN_LIMIT = 64000; // Default token limit
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
|
|
29
|
+
* They are maintained for backward compatibility with existing code that might still reference them,
|
|
30
|
+
* but the actual AI services now use configuration injection.
|
|
31
|
+
*/
|
|
27
32
|
export const FAST_MODEL_ID = process.env.AIGW_FAST_MODEL || "gemini-2.5-flash";
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
|
|
35
|
+
* They are maintained for backward compatibility with existing code that might still reference them,
|
|
36
|
+
* but the actual AI services now use configuration injection.
|
|
37
|
+
*/
|
|
28
38
|
export const AGENT_MODEL_ID = process.env.AIGW_MODEL || "claude-sonnet-4-20250514";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-agent-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "SDK for building AI-powered development tools and agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -18,18 +18,6 @@
|
|
|
18
18
|
"src",
|
|
19
19
|
"README.md"
|
|
20
20
|
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
23
|
-
"type-check": "tsc --noEmit --incremental",
|
|
24
|
-
"dev": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"lint": "eslint --cache",
|
|
27
|
-
"format": "prettier --write .",
|
|
28
|
-
"release:patch": "pnpm version patch && npm publish",
|
|
29
|
-
"release:minor": "pnpm version minor && npm publish",
|
|
30
|
-
"release:major": "pnpm version major && npm publish",
|
|
31
|
-
"prepublishOnly": "npm run build"
|
|
32
|
-
},
|
|
33
21
|
"dependencies": {
|
|
34
22
|
"@modelcontextprotocol/sdk": "^1.18.2",
|
|
35
23
|
"@vscode/ripgrep": "^1.15.14",
|
|
@@ -47,5 +35,13 @@
|
|
|
47
35
|
"engines": {
|
|
48
36
|
"node": ">=16.0.0"
|
|
49
37
|
},
|
|
50
|
-
"license": "MIT"
|
|
51
|
-
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
41
|
+
"type-check": "tsc --noEmit --incremental",
|
|
42
|
+
"dev": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"lint": "eslint --cache",
|
|
45
|
+
"format": "prettier --write ."
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/agent.ts
CHANGED
|
@@ -13,10 +13,32 @@ import {
|
|
|
13
13
|
} from "./managers/backgroundBashManager.js";
|
|
14
14
|
import { SlashCommandManager } from "./managers/slashCommandManager.js";
|
|
15
15
|
import type { SlashCommand, CustomSlashCommand } from "./types.js";
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
Message,
|
|
18
|
+
Logger,
|
|
19
|
+
McpServerStatus,
|
|
20
|
+
GatewayConfig,
|
|
21
|
+
ModelConfig,
|
|
22
|
+
} from "./types.js";
|
|
17
23
|
import { HookManager } from "./hooks/index.js";
|
|
18
|
-
|
|
24
|
+
import { configResolver } from "./utils/configResolver.js";
|
|
25
|
+
import { configValidator } from "./utils/configValidator.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Configuration options for Agent instances
|
|
29
|
+
*
|
|
30
|
+
* IMPORTANT: This interface is used by both Agent constructor and Agent.create()
|
|
31
|
+
* Any changes to this interface must be compatible with both methods.
|
|
32
|
+
*/
|
|
19
33
|
export interface AgentOptions {
|
|
34
|
+
// Optional configuration with environment fallbacks
|
|
35
|
+
apiKey?: string;
|
|
36
|
+
baseURL?: string;
|
|
37
|
+
agentModel?: string;
|
|
38
|
+
fastModel?: string;
|
|
39
|
+
tokenLimit?: number;
|
|
40
|
+
|
|
41
|
+
// Existing options (preserved)
|
|
20
42
|
callbacks?: AgentCallbacks;
|
|
21
43
|
restoreSessionId?: string;
|
|
22
44
|
continueLastSession?: boolean;
|
|
@@ -49,14 +71,51 @@ export class Agent {
|
|
|
49
71
|
private workdir: string; // Working directory
|
|
50
72
|
private systemPrompt?: string; // Custom system prompt
|
|
51
73
|
|
|
52
|
-
//
|
|
53
|
-
private
|
|
74
|
+
// Configuration properties
|
|
75
|
+
private gatewayConfig: GatewayConfig;
|
|
76
|
+
private modelConfig: ModelConfig;
|
|
77
|
+
private tokenLimit: number;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Agent constructor - handles configuration resolution and validation
|
|
81
|
+
*
|
|
82
|
+
* IMPORTANT: Keep this constructor's signature exactly the same as Agent.create()
|
|
83
|
+
* to maintain API consistency. Both methods should accept the same AgentOptions.
|
|
84
|
+
*
|
|
85
|
+
* @param options - Configuration options for the Agent instance
|
|
86
|
+
*/
|
|
87
|
+
constructor(options: AgentOptions) {
|
|
54
88
|
const { callbacks = {}, logger, workdir, systemPrompt } = options;
|
|
55
89
|
|
|
90
|
+
// Resolve configuration from constructor args and environment variables
|
|
91
|
+
const gatewayConfig = configResolver.resolveGatewayConfig(
|
|
92
|
+
options.apiKey,
|
|
93
|
+
options.baseURL,
|
|
94
|
+
);
|
|
95
|
+
const modelConfig = configResolver.resolveModelConfig(
|
|
96
|
+
options.agentModel,
|
|
97
|
+
options.fastModel,
|
|
98
|
+
);
|
|
99
|
+
const tokenLimit = configResolver.resolveTokenLimit(options.tokenLimit);
|
|
100
|
+
|
|
101
|
+
// Validate resolved configuration
|
|
102
|
+
configValidator.validateGatewayConfig(gatewayConfig);
|
|
103
|
+
configValidator.validateTokenLimit(tokenLimit);
|
|
104
|
+
configValidator.validateModelConfig(
|
|
105
|
+
modelConfig.agentModel,
|
|
106
|
+
modelConfig.fastModel,
|
|
107
|
+
);
|
|
108
|
+
|
|
56
109
|
this.callbacks = callbacks;
|
|
57
110
|
this.logger = logger; // Save the passed logger
|
|
58
111
|
this.workdir = workdir || process.cwd(); // Set working directory, default to current working directory
|
|
59
112
|
this.systemPrompt = systemPrompt; // Save custom system prompt
|
|
113
|
+
|
|
114
|
+
// Store resolved configuration
|
|
115
|
+
this.gatewayConfig = gatewayConfig;
|
|
116
|
+
this.modelConfig = modelConfig;
|
|
117
|
+
this.tokenLimit = tokenLimit;
|
|
118
|
+
|
|
60
119
|
this.backgroundBashManager = new BackgroundBashManager({
|
|
61
120
|
callbacks,
|
|
62
121
|
workdir: this.workdir,
|
|
@@ -77,7 +136,7 @@ export class Agent {
|
|
|
77
136
|
logger: this.logger,
|
|
78
137
|
});
|
|
79
138
|
|
|
80
|
-
// Initialize AI manager
|
|
139
|
+
// Initialize AI manager with resolved configuration
|
|
81
140
|
this.aiManager = new AIManager({
|
|
82
141
|
messageManager: this.messageManager,
|
|
83
142
|
toolManager: this.toolManager,
|
|
@@ -87,6 +146,9 @@ export class Agent {
|
|
|
87
146
|
callbacks,
|
|
88
147
|
workdir: this.workdir,
|
|
89
148
|
systemPrompt: this.systemPrompt,
|
|
149
|
+
gatewayConfig: this.gatewayConfig,
|
|
150
|
+
modelConfig: this.modelConfig,
|
|
151
|
+
tokenLimit: this.tokenLimit,
|
|
90
152
|
});
|
|
91
153
|
|
|
92
154
|
// Initialize command manager
|
|
@@ -154,8 +216,17 @@ export class Agent {
|
|
|
154
216
|
return this.backgroundBashManager.killShell(id);
|
|
155
217
|
}
|
|
156
218
|
|
|
157
|
-
/**
|
|
219
|
+
/**
|
|
220
|
+
* Static async factory method for creating Agent instances
|
|
221
|
+
*
|
|
222
|
+
* IMPORTANT: Keep this method's signature exactly the same as the constructor
|
|
223
|
+
* to maintain consistency and avoid confusion for users of the API.
|
|
224
|
+
*
|
|
225
|
+
* @param options - Same AgentOptions interface used by constructor
|
|
226
|
+
* @returns Promise<Agent> - Fully initialized Agent instance
|
|
227
|
+
*/
|
|
158
228
|
static async create(options: AgentOptions): Promise<Agent> {
|
|
229
|
+
// Create Agent instance - configuration resolution and validation now happens in constructor
|
|
159
230
|
const instance = new Agent(options);
|
|
160
231
|
await instance.initialize({
|
|
161
232
|
restoreSessionId: options.restoreSessionId,
|
|
@@ -2,12 +2,11 @@ import { callAgent, compressMessages } from "../services/aiService.js";
|
|
|
2
2
|
import { getMessagesToCompress } from "../utils/messageOperations.js";
|
|
3
3
|
import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
|
|
4
4
|
import * as memory from "../services/memory.js";
|
|
5
|
-
import type { Logger } from "../types.js";
|
|
5
|
+
import type { Logger, GatewayConfig, ModelConfig } from "../types.js";
|
|
6
6
|
import type { ToolManager } from "./toolManager.js";
|
|
7
7
|
import type { ToolContext, ToolResult } from "../tools/types.js";
|
|
8
8
|
import type { MessageManager } from "./messageManager.js";
|
|
9
9
|
import type { BackgroundBashManager } from "./backgroundBashManager.js";
|
|
10
|
-
import { DEFAULT_TOKEN_LIMIT } from "../utils/constants.js";
|
|
11
10
|
import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
|
|
12
11
|
import type { HookManager } from "../hooks/index.js";
|
|
13
12
|
import type { ExtendedHookExecutionContext } from "../hooks/types.js";
|
|
@@ -25,6 +24,10 @@ export interface AIManagerOptions {
|
|
|
25
24
|
callbacks?: AIManagerCallbacks;
|
|
26
25
|
workdir: string;
|
|
27
26
|
systemPrompt?: string;
|
|
27
|
+
// Resolved configuration
|
|
28
|
+
gatewayConfig: GatewayConfig;
|
|
29
|
+
modelConfig: ModelConfig;
|
|
30
|
+
tokenLimit: number;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export class AIManager {
|
|
@@ -39,6 +42,11 @@ export class AIManager {
|
|
|
39
42
|
private workdir: string;
|
|
40
43
|
private systemPrompt?: string;
|
|
41
44
|
|
|
45
|
+
// Configuration properties
|
|
46
|
+
private gatewayConfig: GatewayConfig;
|
|
47
|
+
private modelConfig: ModelConfig;
|
|
48
|
+
private tokenLimit: number;
|
|
49
|
+
|
|
42
50
|
constructor(options: AIManagerOptions) {
|
|
43
51
|
this.messageManager = options.messageManager;
|
|
44
52
|
this.toolManager = options.toolManager;
|
|
@@ -48,6 +56,11 @@ export class AIManager {
|
|
|
48
56
|
this.workdir = options.workdir;
|
|
49
57
|
this.systemPrompt = options.systemPrompt;
|
|
50
58
|
this.callbacks = options.callbacks ?? {};
|
|
59
|
+
|
|
60
|
+
// Store resolved configuration
|
|
61
|
+
this.gatewayConfig = options.gatewayConfig;
|
|
62
|
+
this.modelConfig = options.modelConfig;
|
|
63
|
+
this.tokenLimit = options.tokenLimit;
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
private isCompressing: boolean = false;
|
|
@@ -125,15 +138,10 @@ export class AIManager {
|
|
|
125
138
|
// Update token statistics - display latest token usage
|
|
126
139
|
this.messageManager.setlatestTotalTokens(usage.total_tokens);
|
|
127
140
|
|
|
128
|
-
// Check if token limit exceeded
|
|
129
|
-
|
|
130
|
-
process.env.TOKEN_LIMIT || `${DEFAULT_TOKEN_LIMIT}`,
|
|
131
|
-
10,
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
if (usage.total_tokens > tokenLimit) {
|
|
141
|
+
// Check if token limit exceeded - use injected configuration
|
|
142
|
+
if (usage.total_tokens > this.tokenLimit) {
|
|
135
143
|
this.logger?.info(
|
|
136
|
-
`Token usage exceeded ${tokenLimit}, compressing messages...`,
|
|
144
|
+
`Token usage exceeded ${this.tokenLimit}, compressing messages...`,
|
|
137
145
|
);
|
|
138
146
|
|
|
139
147
|
// Check if messages need compression
|
|
@@ -149,6 +157,8 @@ export class AIManager {
|
|
|
149
157
|
this.setIsCompressing(true);
|
|
150
158
|
try {
|
|
151
159
|
const compressedContent = await compressMessages({
|
|
160
|
+
gatewayConfig: this.gatewayConfig,
|
|
161
|
+
modelConfig: this.modelConfig,
|
|
152
162
|
messages: recentChatMessages,
|
|
153
163
|
abortSignal: abortController.signal,
|
|
154
164
|
});
|
|
@@ -221,6 +231,8 @@ export class AIManager {
|
|
|
221
231
|
|
|
222
232
|
// Call AI service (non-streaming)
|
|
223
233
|
const result = await callAgent({
|
|
234
|
+
gatewayConfig: this.gatewayConfig,
|
|
235
|
+
modelConfig: this.modelConfig,
|
|
224
236
|
messages: recentMessages,
|
|
225
237
|
sessionId: this.messageManager.getSessionId(),
|
|
226
238
|
abortSignal: abortController.signal,
|
|
@@ -432,11 +444,14 @@ export class AIManager {
|
|
|
432
444
|
if (recursionDepth === 0) {
|
|
433
445
|
this.setIsLoading(false);
|
|
434
446
|
|
|
435
|
-
// Save session
|
|
436
|
-
|
|
447
|
+
// Save session and execute Stop hooks in parallel but maintain order
|
|
448
|
+
(async () => {
|
|
449
|
+
// Save session before executing Stop hooks
|
|
450
|
+
await this.messageManager.saveSession();
|
|
437
451
|
|
|
438
|
-
|
|
439
|
-
|
|
452
|
+
// Execute Stop hooks when AI response cycle completes
|
|
453
|
+
await this.executeStopHooks();
|
|
454
|
+
})();
|
|
440
455
|
}
|
|
441
456
|
}
|
|
442
457
|
}
|
|
@@ -5,12 +5,15 @@ import {
|
|
|
5
5
|
ChatCompletionMessageParam,
|
|
6
6
|
ChatCompletionFunctionTool,
|
|
7
7
|
} from "openai/resources.js";
|
|
8
|
-
import {
|
|
8
|
+
import type { GatewayConfig, ModelConfig } from "../types.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* OpenAI model configuration type, based on OpenAI parameters but excluding messages
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
13
|
+
type OpenAIModelConfig = Omit<
|
|
14
|
+
ChatCompletionCreateParamsNonStreaming,
|
|
15
|
+
"messages"
|
|
16
|
+
>;
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Get specific configuration parameters based on model name
|
|
@@ -20,9 +23,9 @@ type ModelConfig = Omit<ChatCompletionCreateParamsNonStreaming, "messages">;
|
|
|
20
23
|
*/
|
|
21
24
|
function getModelConfig(
|
|
22
25
|
modelName: string,
|
|
23
|
-
baseConfig: Partial<
|
|
24
|
-
):
|
|
25
|
-
const config:
|
|
26
|
+
baseConfig: Partial<OpenAIModelConfig> = {},
|
|
27
|
+
): OpenAIModelConfig {
|
|
28
|
+
const config: OpenAIModelConfig = {
|
|
26
29
|
model: modelName,
|
|
27
30
|
stream: false,
|
|
28
31
|
...baseConfig,
|
|
@@ -37,13 +40,12 @@ function getModelConfig(
|
|
|
37
40
|
return config;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
// Initialize OpenAI client with environment variables
|
|
41
|
-
const openai = new OpenAI({
|
|
42
|
-
apiKey: process.env.AIGW_TOKEN,
|
|
43
|
-
baseURL: process.env.AIGW_URL,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
43
|
export interface CallAgentOptions {
|
|
44
|
+
// Resolved configuration
|
|
45
|
+
gatewayConfig: GatewayConfig;
|
|
46
|
+
modelConfig: ModelConfig;
|
|
47
|
+
|
|
48
|
+
// Existing parameters (preserved)
|
|
47
49
|
messages: ChatCompletionMessageParam[];
|
|
48
50
|
sessionId?: string;
|
|
49
51
|
abortSignal?: AbortSignal;
|
|
@@ -67,10 +69,25 @@ export interface CallAgentResult {
|
|
|
67
69
|
export async function callAgent(
|
|
68
70
|
options: CallAgentOptions,
|
|
69
71
|
): Promise<CallAgentResult> {
|
|
70
|
-
const {
|
|
71
|
-
|
|
72
|
+
const {
|
|
73
|
+
gatewayConfig,
|
|
74
|
+
modelConfig,
|
|
75
|
+
messages,
|
|
76
|
+
abortSignal,
|
|
77
|
+
memory,
|
|
78
|
+
workdir,
|
|
79
|
+
tools,
|
|
80
|
+
model,
|
|
81
|
+
systemPrompt,
|
|
82
|
+
} = options;
|
|
72
83
|
|
|
73
84
|
try {
|
|
85
|
+
// Create OpenAI client with injected configuration
|
|
86
|
+
const openai = new OpenAI({
|
|
87
|
+
apiKey: gatewayConfig.apiKey,
|
|
88
|
+
baseURL: gatewayConfig.baseURL,
|
|
89
|
+
});
|
|
90
|
+
|
|
74
91
|
// Build system prompt content
|
|
75
92
|
let systemContent: string;
|
|
76
93
|
|
|
@@ -101,15 +118,15 @@ ${workdir}
|
|
|
101
118
|
const openaiMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] =
|
|
102
119
|
[systemMessage, ...messages];
|
|
103
120
|
|
|
104
|
-
// Get model configuration
|
|
105
|
-
const
|
|
121
|
+
// Get model configuration - use injected modelConfig with optional override
|
|
122
|
+
const openaiModelConfig = getModelConfig(model || modelConfig.agentModel, {
|
|
106
123
|
temperature: 0,
|
|
107
124
|
max_completion_tokens: 32768,
|
|
108
125
|
});
|
|
109
126
|
|
|
110
127
|
// Prepare API call parameters
|
|
111
128
|
const createParams: ChatCompletionCreateParamsNonStreaming = {
|
|
112
|
-
...
|
|
129
|
+
...openaiModelConfig,
|
|
113
130
|
messages: openaiMessages,
|
|
114
131
|
};
|
|
115
132
|
|
|
@@ -160,6 +177,11 @@ ${workdir}
|
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
export interface CompressMessagesOptions {
|
|
180
|
+
// Resolved configuration
|
|
181
|
+
gatewayConfig: GatewayConfig;
|
|
182
|
+
modelConfig: ModelConfig;
|
|
183
|
+
|
|
184
|
+
// Existing parameters
|
|
163
185
|
messages: ChatCompletionMessageParam[];
|
|
164
186
|
abortSignal?: AbortSignal;
|
|
165
187
|
}
|
|
@@ -167,10 +189,16 @@ export interface CompressMessagesOptions {
|
|
|
167
189
|
export async function compressMessages(
|
|
168
190
|
options: CompressMessagesOptions,
|
|
169
191
|
): Promise<string> {
|
|
170
|
-
const { messages, abortSignal } = options;
|
|
192
|
+
const { gatewayConfig, modelConfig, messages, abortSignal } = options;
|
|
193
|
+
|
|
194
|
+
// Create OpenAI client with injected configuration
|
|
195
|
+
const openai = new OpenAI({
|
|
196
|
+
apiKey: gatewayConfig.apiKey,
|
|
197
|
+
baseURL: gatewayConfig.baseURL,
|
|
198
|
+
});
|
|
171
199
|
|
|
172
|
-
// Get model configuration
|
|
173
|
-
const
|
|
200
|
+
// Get model configuration - use injected fast model
|
|
201
|
+
const openaiModelConfig = getModelConfig(modelConfig.fastModel, {
|
|
174
202
|
temperature: 0.1,
|
|
175
203
|
max_tokens: 1500,
|
|
176
204
|
});
|
|
@@ -178,7 +206,7 @@ export async function compressMessages(
|
|
|
178
206
|
try {
|
|
179
207
|
const response = await openai.chat.completions.create(
|
|
180
208
|
{
|
|
181
|
-
...
|
|
209
|
+
...openaiModelConfig,
|
|
182
210
|
messages: [
|
|
183
211
|
{
|
|
184
212
|
role: "system",
|
package/src/services/session.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -258,3 +258,78 @@ export const SKILL_DEFAULTS = {
|
|
|
258
258
|
SCAN_TIMEOUT: 5000,
|
|
259
259
|
LOAD_TIMEOUT: 2000,
|
|
260
260
|
} as const;
|
|
261
|
+
|
|
262
|
+
// Configuration types for Agent Constructor Configuration feature
|
|
263
|
+
export interface GatewayConfig {
|
|
264
|
+
apiKey: string;
|
|
265
|
+
baseURL: string;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface ModelConfig {
|
|
269
|
+
agentModel: string;
|
|
270
|
+
fastModel: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface ConfigurationResolver {
|
|
274
|
+
/**
|
|
275
|
+
* Resolves gateway configuration from constructor args and environment
|
|
276
|
+
* @param apiKey - API key from constructor (optional)
|
|
277
|
+
* @param baseURL - Base URL from constructor (optional)
|
|
278
|
+
* @returns Resolved gateway configuration
|
|
279
|
+
* @throws Error if required configuration is missing after fallbacks
|
|
280
|
+
*/
|
|
281
|
+
resolveGatewayConfig(apiKey?: string, baseURL?: string): GatewayConfig;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Resolves model configuration with fallbacks
|
|
285
|
+
* @param agentModel - Agent model from constructor (optional)
|
|
286
|
+
* @param fastModel - Fast model from constructor (optional)
|
|
287
|
+
* @returns Resolved model configuration with defaults
|
|
288
|
+
*/
|
|
289
|
+
resolveModelConfig(agentModel?: string, fastModel?: string): ModelConfig;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Resolves token limit with fallbacks
|
|
293
|
+
* @param constructorLimit - Token limit from constructor (optional)
|
|
294
|
+
* @returns Resolved token limit
|
|
295
|
+
*/
|
|
296
|
+
resolveTokenLimit(constructorLimit?: number): number;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export interface ConfigurationValidator {
|
|
300
|
+
/**
|
|
301
|
+
* Validates gateway configuration
|
|
302
|
+
* @param config - Configuration to validate
|
|
303
|
+
* @throws Error with descriptive message if invalid
|
|
304
|
+
*/
|
|
305
|
+
validateGatewayConfig(config: GatewayConfig): void;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Validates token limit value
|
|
309
|
+
* @param tokenLimit - Token limit to validate
|
|
310
|
+
* @throws Error if invalid
|
|
311
|
+
*/
|
|
312
|
+
validateTokenLimit(tokenLimit: number): void;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export class ConfigurationError extends Error {
|
|
316
|
+
constructor(
|
|
317
|
+
message: string,
|
|
318
|
+
public readonly field: string,
|
|
319
|
+
public readonly provided?: unknown,
|
|
320
|
+
) {
|
|
321
|
+
super(message);
|
|
322
|
+
this.name = "ConfigurationError";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Standard error messages
|
|
327
|
+
export const CONFIG_ERRORS = {
|
|
328
|
+
MISSING_API_KEY:
|
|
329
|
+
"Gateway configuration requires apiKey. Provide via constructor or AIGW_TOKEN environment variable.",
|
|
330
|
+
MISSING_BASE_URL:
|
|
331
|
+
"Gateway configuration requires baseURL. Provide via constructor or AIGW_URL environment variable.",
|
|
332
|
+
INVALID_TOKEN_LIMIT: "Token limit must be a positive integer.",
|
|
333
|
+
EMPTY_API_KEY: "API key cannot be empty string.",
|
|
334
|
+
EMPTY_BASE_URL: "Base URL cannot be empty string.",
|
|
335
|
+
} as const;
|