wave-agent-sdk 0.18.6 → 0.19.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/builtin/skills/settings/ENV.md +0 -1
- package/builtin/skills/settings/HOOKS.md +10 -0
- package/builtin/skills/settings/MODELS.md +37 -0
- package/builtin/skills/settings/SKILLS.md +6 -4
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +12 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +31 -8
- package/dist/managers/cronManager.d.ts.map +1 -1
- package/dist/managers/cronManager.js +2 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/liveConfigManager.js +0 -9
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +13 -3
- package/dist/managers/messageManager.d.ts +4 -6
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +27 -81
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +11 -2
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +2 -0
- package/dist/prompts/index.d.ts +3 -2
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +5 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +13 -9
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +24 -9
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +6 -0
- package/dist/services/initializationService.d.ts.map +1 -1
- package/dist/services/initializationService.js +1 -1
- package/dist/services/interactionService.js +1 -1
- package/dist/services/reversionService.d.ts +5 -1
- package/dist/services/reversionService.d.ts.map +1 -1
- package/dist/services/reversionService.js +50 -22
- package/dist/services/session.d.ts +4 -13
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +59 -215
- package/dist/telemetry/sessionTracing.d.ts +31 -20
- package/dist/telemetry/sessionTracing.d.ts.map +1 -1
- package/dist/telemetry/sessionTracing.js +192 -62
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +16 -1
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +6 -7
- package/dist/types/config.d.ts +7 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +1 -0
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +0 -1
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +16 -1
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/utils/atomicWrite.d.ts +15 -0
- package/dist/utils/atomicWrite.d.ts.map +1 -0
- package/dist/utils/atomicWrite.js +59 -0
- package/dist/utils/cacheControlUtils.d.ts +3 -15
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +4 -35
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +5 -1
- package/dist/utils/convertMessagesForAPI.d.ts +9 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +74 -55
- package/dist/utils/fileUtils.d.ts +0 -6
- package/dist/utils/fileUtils.d.ts.map +1 -1
- package/dist/utils/fileUtils.js +0 -43
- package/dist/utils/gitUtils.d.ts +11 -0
- package/dist/utils/gitUtils.d.ts.map +1 -1
- package/dist/utils/gitUtils.js +51 -0
- package/dist/utils/groupMessagesByApiRound.d.ts.map +1 -1
- package/dist/utils/groupMessagesByApiRound.js +7 -6
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +2 -1
- package/dist/utils/modelCapabilities.d.ts +22 -0
- package/dist/utils/modelCapabilities.d.ts.map +1 -0
- package/dist/utils/modelCapabilities.js +24 -0
- package/dist/utils/skillParser.d.ts.map +1 -1
- package/dist/utils/skillParser.js +3 -1
- package/dist/utils/tokenEstimate.d.ts +24 -0
- package/dist/utils/tokenEstimate.d.ts.map +1 -0
- package/dist/utils/tokenEstimate.js +30 -0
- package/dist/utils/worktreeUtils.d.ts.map +1 -1
- package/dist/utils/worktreeUtils.js +3 -1
- package/package.json +1 -1
- package/src/agent.ts +11 -5
- package/src/index.ts +1 -0
- package/src/managers/aiManager.ts +36 -7
- package/src/managers/cronManager.ts +2 -0
- package/src/managers/liveConfigManager.ts +0 -12
- package/src/managers/mcpManager.ts +16 -3
- package/src/managers/messageManager.ts +32 -109
- package/src/managers/skillManager.ts +16 -2
- package/src/managers/toolManager.ts +2 -0
- package/src/prompts/index.ts +6 -1
- package/src/services/aiService.ts +12 -5
- package/src/services/configurationService.ts +26 -24
- package/src/services/hook.ts +7 -0
- package/src/services/initializationService.ts +1 -3
- package/src/services/interactionService.ts +1 -1
- package/src/services/reversionService.ts +50 -27
- package/src/services/session.ts +63 -262
- package/src/telemetry/sessionTracing.ts +225 -73
- package/src/tools/bashTool.ts +23 -1
- package/src/tools/readTool.ts +6 -12
- package/src/types/config.ts +8 -0
- package/src/types/hooks.ts +1 -0
- package/src/types/messaging.ts +0 -1
- package/src/types/skills.ts +1 -0
- package/src/types/telemetry.ts +19 -1
- package/src/utils/atomicWrite.ts +61 -0
- package/src/utils/cacheControlUtils.ts +5 -38
- package/src/utils/containerSetup.ts +5 -1
- package/src/utils/convertMessagesForAPI.ts +87 -57
- package/src/utils/fileUtils.ts +0 -46
- package/src/utils/gitUtils.ts +54 -0
- package/src/utils/groupMessagesByApiRound.ts +7 -6
- package/src/utils/mcpUtils.ts +2 -1
- package/src/utils/modelCapabilities.ts +30 -0
- package/src/utils/skillParser.ts +3 -1
- package/src/utils/tokenEstimate.ts +34 -0
- package/src/utils/worktreeUtils.ts +8 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomically write `data` to `filePath` (async).
|
|
3
|
+
*
|
|
4
|
+
* Writes to a temp file then renames it into place. On any failure the temp
|
|
5
|
+
* file is removed and the error is re-thrown so callers can handle it.
|
|
6
|
+
*/
|
|
7
|
+
export declare function atomicWriteFile(filePath: string, data: string): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Atomically write `data` to `filePath` (sync).
|
|
10
|
+
*
|
|
11
|
+
* Sync variant for callers that cannot await. Same temp-file-then-rename
|
|
12
|
+
* strategy as {@link atomicWriteFile}.
|
|
13
|
+
*/
|
|
14
|
+
export declare function atomicWriteFileSync(filePath: string, data: string): void;
|
|
15
|
+
//# sourceMappingURL=atomicWrite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomicWrite.d.ts","sourceRoot":"","sources":["../../src/utils/atomicWrite.ts"],"names":[],"mappings":"AAiBA;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAaxE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic file write utilities.
|
|
3
|
+
*
|
|
4
|
+
* Writes data to a temporary file first, then renames it to the target path.
|
|
5
|
+
* This prevents readers from observing a partially-written (truncated) file,
|
|
6
|
+
* which is critical for config files that may be read concurrently.
|
|
7
|
+
*
|
|
8
|
+
* Temp file naming: `${targetPath}.tmp.${process.pid}.${randomUUID()}`
|
|
9
|
+
* — avoids collisions when multiple processes write the same file.
|
|
10
|
+
*/
|
|
11
|
+
import { writeFileSync, renameSync, unlinkSync, promises as fsp } from "fs";
|
|
12
|
+
import { randomUUID } from "crypto";
|
|
13
|
+
function tmpPathFor(targetPath) {
|
|
14
|
+
return `${targetPath}.tmp.${process.pid}.${randomUUID()}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Atomically write `data` to `filePath` (async).
|
|
18
|
+
*
|
|
19
|
+
* Writes to a temp file then renames it into place. On any failure the temp
|
|
20
|
+
* file is removed and the error is re-thrown so callers can handle it.
|
|
21
|
+
*/
|
|
22
|
+
export async function atomicWriteFile(filePath, data) {
|
|
23
|
+
const tmpPath = tmpPathFor(filePath);
|
|
24
|
+
try {
|
|
25
|
+
await fsp.writeFile(tmpPath, data, "utf-8");
|
|
26
|
+
await fsp.rename(tmpPath, filePath);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
try {
|
|
30
|
+
await fsp.unlink(tmpPath);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Ignore cleanup errors — the original error is more important
|
|
34
|
+
}
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Atomically write `data` to `filePath` (sync).
|
|
40
|
+
*
|
|
41
|
+
* Sync variant for callers that cannot await. Same temp-file-then-rename
|
|
42
|
+
* strategy as {@link atomicWriteFile}.
|
|
43
|
+
*/
|
|
44
|
+
export function atomicWriteFileSync(filePath, data) {
|
|
45
|
+
const tmpPath = tmpPathFor(filePath);
|
|
46
|
+
try {
|
|
47
|
+
writeFileSync(tmpPath, data, "utf-8");
|
|
48
|
+
renameSync(tmpPath, filePath);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
try {
|
|
52
|
+
unlinkSync(tmpPath);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Ignore cleanup errors — the original error is more important
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* models and preserves backward compatibility with existing message formats.
|
|
7
7
|
*/
|
|
8
8
|
import type { ChatCompletionMessageParam, ChatCompletionContentPart, ChatCompletionContentPartText, CompletionUsage } from "openai/resources";
|
|
9
|
+
import type { ModelCapabilities } from "../types/config.js";
|
|
9
10
|
/**
|
|
10
11
|
* Cache control directive for Claude models
|
|
11
12
|
*/
|
|
@@ -43,19 +44,6 @@ export interface ClaudeUsage extends CompletionUsage {
|
|
|
43
44
|
};
|
|
44
45
|
prompt_tokens_details?: ExtendedPromptTokensDetails;
|
|
45
46
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Determines if a model supports prompt caching
|
|
48
|
-
* @param modelName - Model identifier
|
|
49
|
-
* @returns True if model name matches the cache pattern (default: contains 'claude')
|
|
50
|
-
*/
|
|
51
|
-
export declare function supportsPromptCaching(modelName: string): boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Determines if a model supports cache control
|
|
54
|
-
* @param modelName - Model identifier
|
|
55
|
-
* @returns True if model name contains 'claude' (case-insensitive)
|
|
56
|
-
* @deprecated Use supportsPromptCaching instead
|
|
57
|
-
*/
|
|
58
|
-
export declare const isClaudeModel: typeof supportsPromptCaching;
|
|
59
47
|
/**
|
|
60
48
|
* Validates cache control structure
|
|
61
49
|
* @param control - Object to validate
|
|
@@ -91,10 +79,10 @@ export declare function countContentBlocks(messages: ChatCompletionMessageParam[
|
|
|
91
79
|
* Tools are marked separately via addCacheControlToLastTool (called by aiService).
|
|
92
80
|
*
|
|
93
81
|
* @param messages - Original OpenAI message array
|
|
94
|
-
* @param
|
|
82
|
+
* @param capabilities - Declarative model capabilities for cache detection
|
|
95
83
|
* @returns Messages with cache control markers applied
|
|
96
84
|
*/
|
|
97
|
-
export declare function transformMessagesForExplicitCache(messages: ChatCompletionMessageParam[],
|
|
85
|
+
export declare function transformMessagesForExplicitCache(messages: ChatCompletionMessageParam[], capabilities?: ModelCapabilities): ChatCompletionMessageParam[];
|
|
98
86
|
/**
|
|
99
87
|
* Extends standard usage with cache metrics
|
|
100
88
|
* Extracts cache tokens from both Claude-specific top-level fields and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cacheControlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/cacheControlUtils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,eAAe,EAChB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"cacheControlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/cacheControlUtils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAM5D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,mCACf,SAAQ,6BAA6B;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,2BACf,SAAQ,eAAe,CAAC,mBAAmB;IAC3C,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IAGrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE;QACf,yBAAyB,EAAE,MAAM,CAAC;QAClC,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IAGF,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;CACrD;AAUD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,YAAY,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,yBAAyB,EAAE,EAC7C,WAAW,EAAE,OAAO,GACnB,mCAAmC,EAAE,CAmFvC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,0BAA0B,EAAE,GACrC,MAAM,CAYR;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,0BAA0B,EAAE,EACtC,YAAY,CAAC,EAAE,iBAAiB,GAC/B,0BAA0B,EAAE,CAsF9B;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,eAAe,EAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAClC,WAAW,CAiDb;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAyCvE"}
|
|
@@ -6,44 +6,13 @@
|
|
|
6
6
|
* models and preserves backward compatibility with existing message formats.
|
|
7
7
|
*/
|
|
8
8
|
import { logger } from "./globalLogger.js";
|
|
9
|
+
import { supportsPromptCaching } from "./modelCapabilities.js";
|
|
9
10
|
// ============================================================================
|
|
10
11
|
// Default Configuration
|
|
11
12
|
// ============================================================================
|
|
12
13
|
// ============================================================================
|
|
13
14
|
// Utility Functions (Basic Structure - to be implemented)
|
|
14
15
|
// ============================================================================
|
|
15
|
-
/**
|
|
16
|
-
* Determines if a model supports prompt caching
|
|
17
|
-
* @param modelName - Model identifier
|
|
18
|
-
* @returns True if model name matches the cache pattern (default: contains 'claude')
|
|
19
|
-
*/
|
|
20
|
-
export function supportsPromptCaching(modelName) {
|
|
21
|
-
// Handle null, undefined, and non-string inputs
|
|
22
|
-
if (!modelName || typeof modelName !== "string") {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
// Handle empty strings and whitespace-only strings
|
|
26
|
-
const trimmed = modelName.trim();
|
|
27
|
-
if (trimmed.length === 0) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
const cachePattern = process.env.WAVE_PROMPT_CACHE_REGEX || "claude";
|
|
31
|
-
try {
|
|
32
|
-
const regex = new RegExp(cachePattern, "i");
|
|
33
|
-
return regex.test(trimmed);
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
// If regex is invalid, fall back to simple includes check with default
|
|
37
|
-
return trimmed.toLowerCase().includes("claude");
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Determines if a model supports cache control
|
|
42
|
-
* @param modelName - Model identifier
|
|
43
|
-
* @returns True if model name contains 'claude' (case-insensitive)
|
|
44
|
-
* @deprecated Use supportsPromptCaching instead
|
|
45
|
-
*/
|
|
46
|
-
export const isClaudeModel = supportsPromptCaching;
|
|
47
16
|
/**
|
|
48
17
|
* Validates cache control structure
|
|
49
18
|
* @param control - Object to validate
|
|
@@ -165,10 +134,10 @@ export function countContentBlocks(messages) {
|
|
|
165
134
|
* Tools are marked separately via addCacheControlToLastTool (called by aiService).
|
|
166
135
|
*
|
|
167
136
|
* @param messages - Original OpenAI message array
|
|
168
|
-
* @param
|
|
137
|
+
* @param capabilities - Declarative model capabilities for cache detection
|
|
169
138
|
* @returns Messages with cache control markers applied
|
|
170
139
|
*/
|
|
171
|
-
export function transformMessagesForExplicitCache(messages,
|
|
140
|
+
export function transformMessagesForExplicitCache(messages, capabilities) {
|
|
172
141
|
// Validate inputs
|
|
173
142
|
if (!messages || !Array.isArray(messages)) {
|
|
174
143
|
logger.warn("Invalid messages array provided to transformMessagesForExplicitCache");
|
|
@@ -178,7 +147,7 @@ export function transformMessagesForExplicitCache(messages, modelName) {
|
|
|
178
147
|
return [];
|
|
179
148
|
}
|
|
180
149
|
// Only apply cache control for models that support prompt caching
|
|
181
|
-
if (!supportsPromptCaching(
|
|
150
|
+
if (!supportsPromptCaching(capabilities)) {
|
|
182
151
|
return messages;
|
|
183
152
|
}
|
|
184
153
|
// Find first system message index
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,
|
|
1
|
+
{"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAkTX"}
|
|
@@ -139,7 +139,11 @@ export function setupAgentContainer(setupOptions) {
|
|
|
139
139
|
});
|
|
140
140
|
container.register("SkillManager", skillManager);
|
|
141
141
|
const rootSessionId = messageManager.getRootSessionId();
|
|
142
|
-
|
|
142
|
+
const reversionService = new ReversionService(rootSessionId);
|
|
143
|
+
container.register("ReversionService", reversionService);
|
|
144
|
+
reversionService.cleanupOldSessions(30).catch((error) => {
|
|
145
|
+
logger.error("Failed to cleanup old file history:", error);
|
|
146
|
+
});
|
|
143
147
|
const reversionManager = new ReversionManager(container);
|
|
144
148
|
container.register("ReversionManager", reversionManager);
|
|
145
149
|
const canUseToolWithPermissionRequest = options.canUseTool
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { Message } from "../types/index.js";
|
|
2
2
|
import { ChatCompletionMessageParam } from "openai/resources.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options for converting messages to API format.
|
|
5
|
+
*/
|
|
6
|
+
export interface ConvertMessagesOptions {
|
|
7
|
+
/** When false, images are stripped and replaced with text placeholders. */
|
|
8
|
+
supportsVision?: boolean;
|
|
9
|
+
}
|
|
3
10
|
/**
|
|
4
11
|
* Convert message format to API call format, stopping when a compacted message is encountered.
|
|
5
12
|
* Messages with no meaningful content or tool calls are filtered out.
|
|
6
13
|
* @param messages Message list
|
|
14
|
+
* @param options Optional conversion options (e.g. supportsVision)
|
|
7
15
|
* @returns Converted API message format list
|
|
8
16
|
*/
|
|
9
|
-
export declare function convertMessagesForAPI(messages: Message[]): ChatCompletionMessageParam[];
|
|
17
|
+
export declare function convertMessagesForAPI(messages: Message[], options?: ConvertMessagesOptions): ChatCompletionMessageParam[];
|
|
10
18
|
//# sourceMappingURL=convertMessagesForAPI.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessagesForAPI.d.ts","sourceRoot":"","sources":["../../src/utils/convertMessagesForAPI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAKjD,OAAO,EAEL,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAiC7B
|
|
1
|
+
{"version":3,"file":"convertMessagesForAPI.d.ts","sourceRoot":"","sources":["../../src/utils/convertMessagesForAPI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAKjD,OAAO,EAEL,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAiC7B;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,0BAA0B,EAAE,CA0Q9B"}
|
|
@@ -36,9 +36,11 @@ function safeToolArguments(args) {
|
|
|
36
36
|
* Convert message format to API call format, stopping when a compacted message is encountered.
|
|
37
37
|
* Messages with no meaningful content or tool calls are filtered out.
|
|
38
38
|
* @param messages Message list
|
|
39
|
+
* @param options Optional conversion options (e.g. supportsVision)
|
|
39
40
|
* @returns Converted API message format list
|
|
40
41
|
*/
|
|
41
|
-
export function convertMessagesForAPI(messages) {
|
|
42
|
+
export function convertMessagesForAPI(messages, options) {
|
|
43
|
+
const supportsVision = options?.supportsVision !== false;
|
|
42
44
|
const recentMessages = [];
|
|
43
45
|
const startIndex = messages.length - 1;
|
|
44
46
|
for (let i = startIndex; i >= 0; i--) {
|
|
@@ -66,49 +68,57 @@ export function convertMessagesForAPI(messages) {
|
|
|
66
68
|
const toolBlocks = message.blocks.filter((block) => block.type === "tool");
|
|
67
69
|
const completedToolIds = new Set(); // Record completed tool IDs
|
|
68
70
|
if (toolBlocks.length > 0) {
|
|
71
|
+
// Collect image user messages to place after all tool messages
|
|
72
|
+
const imageUserMessages = [];
|
|
69
73
|
toolBlocks.forEach((toolBlock) => {
|
|
70
74
|
// Only add completed tool blocks (i.e., stage is 'end')
|
|
71
75
|
if (toolBlock.id && toolBlock.stage === "end") {
|
|
72
76
|
completedToolIds.add(toolBlock.id);
|
|
73
|
-
//
|
|
77
|
+
// Always add a proper tool message to satisfy tool_call_id pairing
|
|
78
|
+
recentMessages.unshift({
|
|
79
|
+
tool_call_id: toolBlock.id,
|
|
80
|
+
role: "tool",
|
|
81
|
+
content: stripAnsiColors(toolBlock.result || ""),
|
|
82
|
+
});
|
|
83
|
+
// If there are images, also prepare a user message with image content
|
|
74
84
|
if (toolBlock.images && toolBlock.images.length > 0) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
contentParts.push({
|
|
89
|
-
type: "image_url",
|
|
90
|
-
image_url: {
|
|
91
|
-
url: imageUrl,
|
|
92
|
-
detail: "auto",
|
|
93
|
-
},
|
|
85
|
+
if (supportsVision) {
|
|
86
|
+
const contentParts = [];
|
|
87
|
+
toolBlock.images.forEach((image) => {
|
|
88
|
+
const imageUrl = image.data.startsWith("data:")
|
|
89
|
+
? image.data
|
|
90
|
+
: `data:${image.mediaType || "image/png"};base64,${image.data}`;
|
|
91
|
+
contentParts.push({
|
|
92
|
+
type: "image_url",
|
|
93
|
+
image_url: {
|
|
94
|
+
url: imageUrl,
|
|
95
|
+
detail: "auto",
|
|
96
|
+
},
|
|
97
|
+
});
|
|
94
98
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
content: stripAnsiColors(toolBlock.result || ""),
|
|
108
|
-
});
|
|
99
|
+
imageUserMessages.push({
|
|
100
|
+
role: "user",
|
|
101
|
+
content: contentParts,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// Non-vision model: replace images with a text placeholder
|
|
106
|
+
imageUserMessages.push({
|
|
107
|
+
role: "user",
|
|
108
|
+
content: "[Tool returned an image, but the current model does not support image recognition]",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
113
|
});
|
|
114
|
+
// Insert image user messages after all tool messages but before the
|
|
115
|
+
// assistant message (which will be unshifted next). Since tool messages
|
|
116
|
+
// were unshifted to the front, we splice images right after them.
|
|
117
|
+
if (imageUserMessages.length > 0) {
|
|
118
|
+
// Tool messages are at indices 0..N-1, existing messages start at N
|
|
119
|
+
const toolMsgCount = completedToolIds.size;
|
|
120
|
+
recentMessages.splice(toolMsgCount, 0, ...imageUserMessages);
|
|
121
|
+
}
|
|
112
122
|
}
|
|
113
123
|
// Construct the content of the assistant message
|
|
114
124
|
let content = "";
|
|
@@ -180,28 +190,37 @@ export function convertMessagesForAPI(messages) {
|
|
|
180
190
|
if (block.type === "image" &&
|
|
181
191
|
block.imageUrls &&
|
|
182
192
|
block.imageUrls.length > 0) {
|
|
183
|
-
|
|
184
|
-
//
|
|
185
|
-
let finalImageUrl = imageUrl;
|
|
186
|
-
if (!imageUrl.startsWith("data:image/")) {
|
|
187
|
-
// If it's a file path, it needs to be converted to base64
|
|
188
|
-
try {
|
|
189
|
-
finalImageUrl = convertImageToBase64(imageUrl);
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
logger.error("Failed to convert image path to base64:", imageUrl, error);
|
|
193
|
-
// Skip this image, do not add to content
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
193
|
+
if (!supportsVision) {
|
|
194
|
+
// Non-vision model: replace images with a text placeholder
|
|
197
195
|
contentParts.push({
|
|
198
|
-
type: "
|
|
199
|
-
|
|
200
|
-
url: finalImageUrl,
|
|
201
|
-
detail: "auto",
|
|
202
|
-
},
|
|
196
|
+
type: "text",
|
|
197
|
+
text: "[User shared an image, but the current model does not support image recognition]",
|
|
203
198
|
});
|
|
204
|
-
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
block.imageUrls.forEach((imageUrl) => {
|
|
202
|
+
// Check if it's already base64, convert if not
|
|
203
|
+
let finalImageUrl = imageUrl;
|
|
204
|
+
if (!imageUrl.startsWith("data:image/")) {
|
|
205
|
+
// If it's a file path, it needs to be converted to base64
|
|
206
|
+
try {
|
|
207
|
+
finalImageUrl = convertImageToBase64(imageUrl);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
logger.error("Failed to convert image path to base64:", imageUrl, error);
|
|
211
|
+
// Skip this image, do not add to content
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
contentParts.push({
|
|
216
|
+
type: "image_url",
|
|
217
|
+
image_url: {
|
|
218
|
+
url: finalImageUrl,
|
|
219
|
+
detail: "auto",
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
205
224
|
}
|
|
206
225
|
// If there is a tool block in user message, add its result
|
|
207
226
|
if (block.type === "tool" && block.stage === "end" && block.result) {
|
|
@@ -26,12 +26,6 @@ export declare function readFirstNLines(filePath: string, maxLines: number): Pro
|
|
|
26
26
|
* @return {Promise<string>} - The last non-empty line of the file, or an empty string if no non-empty lines found.
|
|
27
27
|
*/
|
|
28
28
|
export declare function getLastLine(filePath: string, minLength?: number): Promise<string>;
|
|
29
|
-
/**
|
|
30
|
-
* Ensures that a pattern is present in the global git ignore file.
|
|
31
|
-
*
|
|
32
|
-
* @param {string} pattern - The pattern to add to global git ignore.
|
|
33
|
-
*/
|
|
34
|
-
export declare function ensureGlobalGitIgnore(pattern: string): Promise<void>;
|
|
35
29
|
/**
|
|
36
30
|
* Suggests similar paths if a file is not found.
|
|
37
31
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBrE;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAI,GACZ,OAAO,CAAC,MAAM,CAAC,CA8DjB;AA2BD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBnB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB"}
|
package/dist/utils/fileUtils.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import { createReadStream } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { execSync } from "node:child_process";
|
|
5
|
-
import { homedir } from "node:os";
|
|
6
4
|
import { glob } from "glob";
|
|
7
5
|
/**
|
|
8
6
|
* Reads the first line of a file efficiently using Node.js readline.
|
|
@@ -138,47 +136,6 @@ export async function getLastLine(filePath, minLength = 1) {
|
|
|
138
136
|
}
|
|
139
137
|
}
|
|
140
138
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Ensures that a pattern is present in the global git ignore file.
|
|
143
|
-
*
|
|
144
|
-
* @param {string} pattern - The pattern to add to global git ignore.
|
|
145
|
-
*/
|
|
146
|
-
export async function ensureGlobalGitIgnore(pattern) {
|
|
147
|
-
try {
|
|
148
|
-
let globalIgnorePath;
|
|
149
|
-
try {
|
|
150
|
-
globalIgnorePath = execSync("git config --get core.excludesfile", {
|
|
151
|
-
encoding: "utf8",
|
|
152
|
-
}).trim();
|
|
153
|
-
}
|
|
154
|
-
catch {
|
|
155
|
-
// If not set, use default paths
|
|
156
|
-
const xdgConfigHome = process.env.XDG_CONFIG_HOME || path.join(homedir(), ".config");
|
|
157
|
-
globalIgnorePath = path.join(xdgConfigHome, "git", "ignore");
|
|
158
|
-
}
|
|
159
|
-
if (!globalIgnorePath)
|
|
160
|
-
return;
|
|
161
|
-
// Ensure directory exists
|
|
162
|
-
await fs.mkdir(path.dirname(globalIgnorePath), { recursive: true });
|
|
163
|
-
let content = "";
|
|
164
|
-
try {
|
|
165
|
-
content = await fs.readFile(globalIgnorePath, "utf8");
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
// File doesn't exist
|
|
169
|
-
}
|
|
170
|
-
const lines = content.split("\n").map((line) => line.trim());
|
|
171
|
-
if (!lines.includes(pattern)) {
|
|
172
|
-
const newContent = content.endsWith("\n") || content === ""
|
|
173
|
-
? `${content}${pattern}\n`
|
|
174
|
-
: `${content}\n${pattern}\n`;
|
|
175
|
-
await fs.writeFile(globalIgnorePath, newContent, "utf8");
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
catch {
|
|
179
|
-
// Ignore errors
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
139
|
/**
|
|
183
140
|
* Simple Levenshtein distance implementation
|
|
184
141
|
*/
|
package/dist/utils/gitUtils.d.ts
CHANGED
|
@@ -45,6 +45,17 @@ export declare function resolveGitDir(cwd: string): string | null;
|
|
|
45
45
|
* @returns Default remote branch name
|
|
46
46
|
*/
|
|
47
47
|
export declare function getDefaultRemoteBranch(cwd: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Ensure that Wave runtime files are excluded from git status by writing
|
|
50
|
+
* patterns to `.git/info/exclude` (per-repo, not global).
|
|
51
|
+
*
|
|
52
|
+
* Idempotent: if the marker `# wave-runtime` is already present in the
|
|
53
|
+
* exclude file, it skips writing. A module-level Set provides additional
|
|
54
|
+
* per-process dedup to avoid redundant file reads.
|
|
55
|
+
*
|
|
56
|
+
* @param cwd Working directory to start searching from
|
|
57
|
+
*/
|
|
58
|
+
export declare function ensureWaveRuntimeFilesExcluded(cwd: string): void;
|
|
48
59
|
/**
|
|
49
60
|
* Check if there are uncommitted changes in the working directory
|
|
50
61
|
* @param cwd Working directory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitUtils.d.ts","sourceRoot":"","sources":["../../src/utils/gitUtils.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAevD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWnD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAetD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCxD;AAwDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4B1D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAW1D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAYvE"}
|
|
1
|
+
{"version":3,"file":"gitUtils.d.ts","sourceRoot":"","sources":["../../src/utils/gitUtils.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAevD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWnD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAetD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCxD;AAwDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4B1D;AAQD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAoChE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAW1D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAYvE"}
|
package/dist/utils/gitUtils.js
CHANGED
|
@@ -216,6 +216,57 @@ export function getDefaultRemoteBranch(cwd) {
|
|
|
216
216
|
// 4. Hardcoded fallback
|
|
217
217
|
return "main";
|
|
218
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Module-level set tracking git dirs already processed in this process,
|
|
221
|
+
* to avoid redundant I/O.
|
|
222
|
+
*/
|
|
223
|
+
const excludedGitDirs = new Set();
|
|
224
|
+
/**
|
|
225
|
+
* Ensure that Wave runtime files are excluded from git status by writing
|
|
226
|
+
* patterns to `.git/info/exclude` (per-repo, not global).
|
|
227
|
+
*
|
|
228
|
+
* Idempotent: if the marker `# wave-runtime` is already present in the
|
|
229
|
+
* exclude file, it skips writing. A module-level Set provides additional
|
|
230
|
+
* per-process dedup to avoid redundant file reads.
|
|
231
|
+
*
|
|
232
|
+
* @param cwd Working directory to start searching from
|
|
233
|
+
*/
|
|
234
|
+
export function ensureWaveRuntimeFilesExcluded(cwd) {
|
|
235
|
+
try {
|
|
236
|
+
const gitDir = resolveGitDir(cwd);
|
|
237
|
+
if (!gitDir)
|
|
238
|
+
return;
|
|
239
|
+
if (excludedGitDirs.has(gitDir))
|
|
240
|
+
return;
|
|
241
|
+
const excludePath = path.join(gitDir, "info", "exclude");
|
|
242
|
+
let content = "";
|
|
243
|
+
try {
|
|
244
|
+
content = fsSync.readFileSync(excludePath, "utf8");
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// File doesn't exist yet
|
|
248
|
+
}
|
|
249
|
+
const marker = "# wave-runtime";
|
|
250
|
+
if (content.includes(marker)) {
|
|
251
|
+
excludedGitDirs.add(gitDir);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const block = [
|
|
255
|
+
marker,
|
|
256
|
+
"**/.wave/scheduled_tasks.lock",
|
|
257
|
+
"**/.wave/scheduled_tasks.json",
|
|
258
|
+
"**/.wave/worktrees/",
|
|
259
|
+
"**/.wave/settings.local.json",
|
|
260
|
+
"",
|
|
261
|
+
].join("\n");
|
|
262
|
+
fsSync.mkdirSync(path.join(gitDir, "info"), { recursive: true });
|
|
263
|
+
fsSync.appendFileSync(excludePath, block);
|
|
264
|
+
excludedGitDirs.add(gitDir);
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Best-effort: ignore all errors
|
|
268
|
+
}
|
|
269
|
+
}
|
|
219
270
|
/**
|
|
220
271
|
* Check if there are uncommitted changes in the working directory
|
|
221
272
|
* @param cwd Working directory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groupMessagesByApiRound.d.ts","sourceRoot":"","sources":["../../src/utils/groupMessagesByApiRound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"groupMessagesByApiRound.d.ts","sourceRoot":"","sources":["../../src/utils/groupMessagesByApiRound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CA8DvE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,EAAE,CAIX"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { estimateTokens as estimateStrTokens } from "./tokenEstimate.js";
|
|
1
2
|
/**
|
|
2
3
|
* Groups messages into "API rounds" — each round corresponds to one API
|
|
3
4
|
* call-response cycle. This is critical because in agentic sessions with a
|
|
@@ -74,24 +75,24 @@ export function getLastApiRounds(messages, roundCount) {
|
|
|
74
75
|
return lastRounds.flatMap((r) => r.messages);
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
|
-
*
|
|
78
|
+
* Estimate token count from message blocks using CJK-aware estimation.
|
|
78
79
|
*/
|
|
79
80
|
function estimateTokens(messages) {
|
|
80
|
-
let
|
|
81
|
+
let combined = "";
|
|
81
82
|
for (const msg of messages) {
|
|
82
83
|
for (const block of msg.blocks) {
|
|
83
84
|
if ("content" in block && typeof block.content === "string") {
|
|
84
|
-
|
|
85
|
+
combined += block.content;
|
|
85
86
|
}
|
|
86
87
|
if (block.type === "tool" &&
|
|
87
88
|
block.parameters &&
|
|
88
89
|
typeof block.parameters === "string") {
|
|
89
|
-
|
|
90
|
+
combined += block.parameters;
|
|
90
91
|
}
|
|
91
92
|
if (block.type === "tool" && block.result) {
|
|
92
|
-
|
|
93
|
+
combined += block.result;
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
|
-
return
|
|
97
|
+
return estimateStrTokens(combined);
|
|
97
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpUtils.d.ts","sourceRoot":"","sources":["../../src/utils/mcpUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAgDlE;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,0BAA0B,CAgB5B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,WAAW,KAClB,OAAO,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC,GACD,UAAU,CAiCZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,EAAE,GACzB,eAAe,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"mcpUtils.d.ts","sourceRoot":"","sources":["../../src/utils/mcpUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAgDlE;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,0BAA0B,CAgB5B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,WAAW,KAClB,OAAO,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC,GACD,UAAU,CAiCZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,EAAE,GACzB,eAAe,GAAG,SAAS,CAM7B"}
|
package/dist/utils/mcpUtils.js
CHANGED
|
@@ -84,5 +84,6 @@ export function createMcpToolPlugin(mcpTool, serverName, executeTool) {
|
|
|
84
84
|
* Find which server a tool belongs to
|
|
85
85
|
*/
|
|
86
86
|
export function findToolServer(toolName, servers) {
|
|
87
|
-
return servers.find((s) => s.status === "connected"
|
|
87
|
+
return servers.find((s) => (s.status === "connected" || s.status === "reconnecting") &&
|
|
88
|
+
s.tools?.some((t) => t.name === toolName));
|
|
88
89
|
}
|