wave-agent-sdk 1.0.4 → 1.0.6
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 +23 -1
- package/dist/agent.js +34 -4
- package/dist/managers/aiManager.d.ts +36 -0
- package/dist/managers/aiManager.js +240 -8
- package/dist/managers/messageManager.d.ts +1 -3
- package/dist/managers/messageManager.js +19 -9
- package/dist/managers/slashCommandManager.js +28 -0
- package/dist/managers/subagentManager.d.ts +0 -2
- package/dist/services/session.js +2 -9
- package/dist/telemetry/instrumentation.d.ts +1 -1
- package/dist/telemetry/instrumentation.js +57 -28
- package/dist/tools/bashTool.js +16 -6
- package/dist/tools/grepTool.js +11 -3
- package/dist/types/index.d.ts +3 -0
- package/dist/types/messaging.d.ts +2 -0
- package/dist/utils/containerSetup.js +0 -3
- package/dist/utils/messageOperations.d.ts +10 -1
- package/dist/utils/messageOperations.js +19 -1
- package/dist/utils/notificationXml.js +5 -0
- package/dist/utils/ripgrep.d.ts +4 -4
- package/dist/utils/ripgrep.js +4 -27
- package/package.json +20 -8
- package/bin/rg +0 -79
- package/dist/managers/forkedAgentManager.d.ts +0 -50
- package/dist/managers/forkedAgentManager.js +0 -130
- package/scripts/install_ripgrep.js +0 -111
- package/scripts/postinstall.js +0 -38
- package/src/agent.ts +0 -1271
- package/src/constants/subagents.ts +0 -4
- package/src/constants/toolLimits.ts +0 -15
- package/src/constants/tools.ts +0 -24
- package/src/core/plugin.ts +0 -237
- package/src/core/session.ts +0 -9
- package/src/index.ts +0 -38
- package/src/managers/MemoryRuleManager.ts +0 -198
- package/src/managers/aiManager.ts +0 -2429
- package/src/managers/backgroundTaskManager.ts +0 -480
- package/src/managers/bangManager.ts +0 -119
- package/src/managers/cronManager.ts +0 -401
- package/src/managers/foregroundTaskManager.ts +0 -30
- package/src/managers/forkedAgentManager.ts +0 -216
- package/src/managers/hookManager.ts +0 -1089
- package/src/managers/liveConfigManager.ts +0 -445
- package/src/managers/lspManager.ts +0 -470
- package/src/managers/mcpManager.ts +0 -1010
- package/src/managers/messageManager.ts +0 -1180
- package/src/managers/messageQueue.ts +0 -157
- package/src/managers/permissionManager.ts +0 -1140
- package/src/managers/planManager.ts +0 -112
- package/src/managers/pluginManager.ts +0 -330
- package/src/managers/pluginScopeManager.ts +0 -124
- package/src/managers/reversionManager.ts +0 -178
- package/src/managers/skillManager.ts +0 -578
- package/src/managers/slashCommandManager.ts +0 -564
- package/src/managers/subagentManager.ts +0 -915
- package/src/managers/toolManager.ts +0 -489
- package/src/managers/workflowManager.ts +0 -493
- package/src/prompts/autoMemory.ts +0 -33
- package/src/prompts/autoMemoryExtraction.ts +0 -146
- package/src/prompts/index.ts +0 -506
- package/src/prompts/planModeReminders.ts +0 -126
- package/src/services/GitService.ts +0 -131
- package/src/services/MarketplaceService.ts +0 -1052
- package/src/services/MemoryRuleService.ts +0 -71
- package/src/services/aiService.ts +0 -919
- package/src/services/authService.ts +0 -565
- package/src/services/autoMemoryService.ts +0 -280
- package/src/services/configurationService.ts +0 -1520
- package/src/services/fileWatcher.ts +0 -319
- package/src/services/hook.ts +0 -348
- package/src/services/initializationService.ts +0 -357
- package/src/services/interactionService.ts +0 -229
- package/src/services/jsonlHandler.ts +0 -295
- package/src/services/memory.ts +0 -234
- package/src/services/pluginLoader.ts +0 -252
- package/src/services/remoteSettingsService.ts +0 -366
- package/src/services/reversionService.ts +0 -122
- package/src/services/session.ts +0 -922
- package/src/services/taskManager.ts +0 -321
- package/src/telemetry/events.ts +0 -65
- package/src/telemetry/instrumentation.ts +0 -499
- package/src/telemetry/sessionTracing.ts +0 -348
- package/src/tools/agentTool.ts +0 -322
- package/src/tools/askUserQuestion.ts +0 -160
- package/src/tools/bashTool.ts +0 -621
- package/src/tools/buildTool.ts +0 -61
- package/src/tools/cronCreateTool.ts +0 -161
- package/src/tools/cronDeleteTool.ts +0 -51
- package/src/tools/cronListTool.ts +0 -47
- package/src/tools/editTool.ts +0 -313
- package/src/tools/enterPlanMode.ts +0 -124
- package/src/tools/enterWorktreeTool.ts +0 -190
- package/src/tools/exitPlanMode.ts +0 -139
- package/src/tools/exitWorktreeTool.ts +0 -236
- package/src/tools/globTool.ts +0 -167
- package/src/tools/grepTool.ts +0 -399
- package/src/tools/lspTool.ts +0 -883
- package/src/tools/readTool.ts +0 -426
- package/src/tools/skillTool.ts +0 -248
- package/src/tools/taskManagementTools.ts +0 -574
- package/src/tools/taskStopTool.ts +0 -78
- package/src/tools/types.ts +0 -137
- package/src/tools/webFetchTool.ts +0 -373
- package/src/tools/workflowTool.ts +0 -205
- package/src/tools/writeTool.ts +0 -267
- package/src/types/agent.ts +0 -128
- package/src/types/auth.ts +0 -19
- package/src/types/commands.ts +0 -30
- package/src/types/config.ts +0 -43
- package/src/types/configuration.ts +0 -168
- package/src/types/core.ts +0 -105
- package/src/types/cron.ts +0 -13
- package/src/types/environment.ts +0 -106
- package/src/types/fileSearch.ts +0 -4
- package/src/types/history.ts +0 -7
- package/src/types/hooks.ts +0 -256
- package/src/types/index.ts +0 -41
- package/src/types/lsp.ts +0 -98
- package/src/types/marketplace.ts +0 -71
- package/src/types/mcp.ts +0 -43
- package/src/types/memoryRule.ts +0 -31
- package/src/types/messaging.ts +0 -114
- package/src/types/permissions.ts +0 -80
- package/src/types/plugins.ts +0 -39
- package/src/types/processes.ts +0 -99
- package/src/types/reversion.ts +0 -29
- package/src/types/session.ts +0 -12
- package/src/types/skills.ts +0 -108
- package/src/types/tasks.ts +0 -13
- package/src/types/telemetry.ts +0 -98
- package/src/types/tools.ts +0 -44
- package/src/types/workflow.ts +0 -6
- package/src/utils/abortUtils.ts +0 -118
- package/src/utils/atomicWrite.ts +0 -61
- package/src/utils/bashParser.ts +0 -899
- package/src/utils/cacheControlUtils.ts +0 -426
- package/src/utils/commandArgumentParser.ts +0 -161
- package/src/utils/commandPathResolver.ts +0 -88
- package/src/utils/configPaths.ts +0 -220
- package/src/utils/configValidator.ts +0 -100
- package/src/utils/constants.ts +0 -39
- package/src/utils/container.ts +0 -92
- package/src/utils/containerSetup.ts +0 -371
- package/src/utils/convertMessagesForAPI.ts +0 -326
- package/src/utils/cronTasks.ts +0 -128
- package/src/utils/cronTasksLock.ts +0 -182
- package/src/utils/cronToHuman.ts +0 -99
- package/src/utils/customCommands.ts +0 -95
- package/src/utils/editUtils.ts +0 -20
- package/src/utils/fileFormat.ts +0 -40
- package/src/utils/fileSearch.ts +0 -151
- package/src/utils/fileUtils.ts +0 -223
- package/src/utils/gitUtils.ts +0 -315
- package/src/utils/globalLogger.ts +0 -128
- package/src/utils/groupMessagesByApiRound.ts +0 -121
- package/src/utils/hookMatcher.ts +0 -176
- package/src/utils/markdownParser.ts +0 -317
- package/src/utils/mcpUtils.ts +0 -138
- package/src/utils/messageOperations.ts +0 -641
- package/src/utils/modelCapabilities.ts +0 -30
- package/src/utils/nameGenerator.ts +0 -99
- package/src/utils/notificationXml.ts +0 -57
- package/src/utils/openaiClient.ts +0 -251
- package/src/utils/parseCronExpression.ts +0 -78
- package/src/utils/path.ts +0 -72
- package/src/utils/pathEncoder.ts +0 -400
- package/src/utils/pathSafety.ts +0 -40
- package/src/utils/promptHistory.ts +0 -168
- package/src/utils/ripgrep.ts +0 -35
- package/src/utils/shellResolver.ts +0 -190
- package/src/utils/skillParser.ts +0 -246
- package/src/utils/stringUtils.ts +0 -156
- package/src/utils/subagentParser.ts +0 -279
- package/src/utils/taskReminder.ts +0 -96
- package/src/utils/tokenCalculation.ts +0 -43
- package/src/utils/tokenEstimate.ts +0 -34
- package/src/utils/toolResultStorage.ts +0 -117
- package/src/utils/worktreeSession.ts +0 -26
- package/src/utils/worktreeUtils.ts +0 -786
- package/src/workflow/budgetTracker.ts +0 -34
- package/src/workflow/concurrencyLimiter.ts +0 -47
- package/src/workflow/journal.ts +0 -95
- package/src/workflow/progressReporter.ts +0 -141
- package/src/workflow/runState.ts +0 -65
- package/src/workflow/scriptRuntime.ts +0 -274
- package/src/workflow/structuredOutput.ts +0 -123
- package/src/workflow/types.ts +0 -101
- package/src/workflow/workflowApis.ts +0 -410
- package/vendor/ripgrep/linux-aarch64/rg +0 -0
- package/vendor/ripgrep/linux-x86_64/rg +0 -0
- package/vendor/ripgrep/macos-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-x86_64/rg +0 -0
- package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
- package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Global Logger Registry for Agent SDK
|
|
3
|
-
*
|
|
4
|
-
* Provides zero-overhead logging access for utility functions and services
|
|
5
|
-
* without requiring parameter passing. Maintains singleton logger instance
|
|
6
|
-
* accessible across all SDK modules.
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Zero overhead when no logger configured (single null check)
|
|
10
|
-
* - Thread-safe in Node.js single-threaded environment
|
|
11
|
-
* - Maintains backward compatibility with existing Logger interface
|
|
12
|
-
* - Direct function delegation when configured
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import type { Logger } from "../types/core.js";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Module-level storage for the global logger instance
|
|
19
|
-
* null = unconfigured (logging calls are no-ops)
|
|
20
|
-
* Logger = configured (calls are forwarded)
|
|
21
|
-
*/
|
|
22
|
-
let globalLogger: Logger | null = null;
|
|
23
|
-
|
|
24
|
-
// =============================================================================
|
|
25
|
-
// Registry Management API
|
|
26
|
-
// =============================================================================
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Configure the global logger instance used by utility functions and services
|
|
30
|
-
*
|
|
31
|
-
* @param logger - Logger instance implementing the Logger interface, or null to disable logging
|
|
32
|
-
* @returns void
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```typescript
|
|
36
|
-
* import { setGlobalLogger } from './utils/globalLogger.js';
|
|
37
|
-
*
|
|
38
|
-
* // Configure logger
|
|
39
|
-
* setGlobalLogger(myLogger);
|
|
40
|
-
*
|
|
41
|
-
* // Disable logging
|
|
42
|
-
* setGlobalLogger(null);
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export function setGlobalLogger(logger: Logger | null): void {
|
|
46
|
-
globalLogger = logger;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Reset global logger to unconfigured state
|
|
51
|
-
* Equivalent to setGlobalLogger(null)
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```typescript
|
|
55
|
-
* clearGlobalLogger(); // All subsequent logging calls become no-ops
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export function clearGlobalLogger(): void {
|
|
59
|
-
globalLogger = null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Check if global logger is currently configured
|
|
64
|
-
*
|
|
65
|
-
* @returns true if logger configured, false otherwise
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```typescript
|
|
69
|
-
* if (isLoggerConfigured()) {
|
|
70
|
-
* // Perform expensive logging operation
|
|
71
|
-
* const debugInfo = generateDebugInfo();
|
|
72
|
-
* logger.debug(debugInfo);
|
|
73
|
-
* }
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
|
-
export function isLoggerConfigured(): boolean {
|
|
77
|
-
return globalLogger !== null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// =============================================================================
|
|
81
|
-
// Zero-Overhead Logging API
|
|
82
|
-
// =============================================================================
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Zero-overhead logging interface
|
|
86
|
-
*
|
|
87
|
-
* Performance characteristics:
|
|
88
|
-
* - Unconfigured: Single null check + early return (near-zero cost)
|
|
89
|
-
* - Configured: Null check + function delegation
|
|
90
|
-
* - No object creation or intermediate allocations
|
|
91
|
-
*/
|
|
92
|
-
export const logger = {
|
|
93
|
-
/**
|
|
94
|
-
* Log debug-level message through global logger
|
|
95
|
-
* No-op when global logger is null (zero overhead)
|
|
96
|
-
*/
|
|
97
|
-
debug: (...args: unknown[]): void => {
|
|
98
|
-
if (globalLogger === null) return;
|
|
99
|
-
globalLogger.debug(...args);
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Log info-level message through global logger
|
|
104
|
-
* No-op when global logger is null (zero overhead)
|
|
105
|
-
*/
|
|
106
|
-
info: (...args: unknown[]): void => {
|
|
107
|
-
if (globalLogger === null) return;
|
|
108
|
-
globalLogger.info(...args);
|
|
109
|
-
},
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Log warning-level message through global logger
|
|
113
|
-
* No-op when global logger is null (zero overhead)
|
|
114
|
-
*/
|
|
115
|
-
warn: (...args: unknown[]): void => {
|
|
116
|
-
if (globalLogger === null) return;
|
|
117
|
-
globalLogger.warn(...args);
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Log error-level message through global logger
|
|
122
|
-
* No-op when global logger is null (zero overhead)
|
|
123
|
-
*/
|
|
124
|
-
error: (...args: unknown[]): void => {
|
|
125
|
-
if (globalLogger === null) return;
|
|
126
|
-
globalLogger.error(...args);
|
|
127
|
-
},
|
|
128
|
-
} as const;
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import type { Message } from "../types/index.js";
|
|
2
|
-
import { estimateTokens as estimateStrTokens } from "./tokenEstimate.js";
|
|
3
|
-
|
|
4
|
-
export interface ApiRound {
|
|
5
|
-
messages: Message[];
|
|
6
|
-
estimatedTokens: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Groups messages into "API rounds" — each round corresponds to one API
|
|
11
|
-
* call-response cycle. This is critical because in agentic sessions with a
|
|
12
|
-
* single user prompt, Wave creates a new Message per API round (each recursive
|
|
13
|
-
* sendAIMessage call creates a new assistant message).
|
|
14
|
-
*
|
|
15
|
-
* Boundaries:
|
|
16
|
-
* - A new `role: "user"` message starts a new round.
|
|
17
|
-
* - A new `role: "assistant"` message with a different `id` starts a new round.
|
|
18
|
-
* - A message with a `compact` block is pushed as its own round and starts a
|
|
19
|
-
* new round after it.
|
|
20
|
-
*/
|
|
21
|
-
export function groupMessagesByApiRound(messages: Message[]): ApiRound[] {
|
|
22
|
-
const rounds: ApiRound[] = [];
|
|
23
|
-
let currentRound: Message[] = [];
|
|
24
|
-
let lastAssistantId: string | undefined;
|
|
25
|
-
|
|
26
|
-
for (const msg of messages) {
|
|
27
|
-
let startNewRound = false;
|
|
28
|
-
|
|
29
|
-
if (msg.role === "user") {
|
|
30
|
-
startNewRound = true;
|
|
31
|
-
} else if (msg.role === "assistant") {
|
|
32
|
-
// Compact block is always its own round
|
|
33
|
-
const hasCompact = msg.blocks.some((b) => b.type === "compact");
|
|
34
|
-
if (hasCompact) {
|
|
35
|
-
startNewRound = true;
|
|
36
|
-
} else if (msg.id !== lastAssistantId) {
|
|
37
|
-
// New assistant id starts a new round.
|
|
38
|
-
// Exception: if the current round is [user] (first assistant after a
|
|
39
|
-
// user prompt in a normal conversation), keep them together as one
|
|
40
|
-
// round. But if we already have assistant(s) in this round (agentic
|
|
41
|
-
// tool loop), the new id starts a new round.
|
|
42
|
-
const roundHasOtherAssistant = currentRound.some(
|
|
43
|
-
(m) => m.role === "assistant" && m.id !== msg.id,
|
|
44
|
-
);
|
|
45
|
-
if (roundHasOtherAssistant) {
|
|
46
|
-
startNewRound = true;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
lastAssistantId = msg.id;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (startNewRound && currentRound.length > 0) {
|
|
53
|
-
rounds.push({
|
|
54
|
-
messages: currentRound,
|
|
55
|
-
estimatedTokens: estimateTokens(currentRound),
|
|
56
|
-
});
|
|
57
|
-
currentRound = [];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
currentRound.push(msg);
|
|
61
|
-
|
|
62
|
-
// After pushing a compact message as its own round, flush immediately
|
|
63
|
-
if (
|
|
64
|
-
msg.role === "assistant" &&
|
|
65
|
-
msg.blocks.some((b) => b.type === "compact")
|
|
66
|
-
) {
|
|
67
|
-
rounds.push({
|
|
68
|
-
messages: currentRound,
|
|
69
|
-
estimatedTokens: estimateTokens(currentRound),
|
|
70
|
-
});
|
|
71
|
-
currentRound = [];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (currentRound.length > 0) {
|
|
76
|
-
rounds.push({
|
|
77
|
-
messages: currentRound,
|
|
78
|
-
estimatedTokens: estimateTokens(currentRound),
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return rounds;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Returns the last `roundCount` complete API rounds as a flat message array.
|
|
87
|
-
* Never splits a tool_use/tool_result pair. If fewer rounds exist, returns all.
|
|
88
|
-
*/
|
|
89
|
-
export function getLastApiRounds(
|
|
90
|
-
messages: Message[],
|
|
91
|
-
roundCount: number,
|
|
92
|
-
): Message[] {
|
|
93
|
-
const rounds = groupMessagesByApiRound(messages);
|
|
94
|
-
const lastRounds = rounds.slice(-roundCount);
|
|
95
|
-
return lastRounds.flatMap((r) => r.messages);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Estimate token count from message blocks using CJK-aware estimation.
|
|
100
|
-
*/
|
|
101
|
-
function estimateTokens(messages: Message[]): number {
|
|
102
|
-
let combined = "";
|
|
103
|
-
for (const msg of messages) {
|
|
104
|
-
for (const block of msg.blocks) {
|
|
105
|
-
if ("content" in block && typeof block.content === "string") {
|
|
106
|
-
combined += block.content;
|
|
107
|
-
}
|
|
108
|
-
if (
|
|
109
|
-
block.type === "tool" &&
|
|
110
|
-
block.parameters &&
|
|
111
|
-
typeof block.parameters === "string"
|
|
112
|
-
) {
|
|
113
|
-
combined += block.parameters;
|
|
114
|
-
}
|
|
115
|
-
if (block.type === "tool" && block.result) {
|
|
116
|
-
combined += block.result;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return estimateStrTokens(combined);
|
|
121
|
-
}
|
package/src/utils/hookMatcher.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook Pattern Matcher
|
|
3
|
-
*
|
|
4
|
-
* Provides pattern matching functionality for hook tool name matching.
|
|
5
|
-
* Supports exact matching, wildcard patterns, and pipe-separated alternatives.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { minimatch } from "minimatch";
|
|
9
|
-
|
|
10
|
-
export class HookMatcher {
|
|
11
|
-
/**
|
|
12
|
-
* Test if pattern matches tool name
|
|
13
|
-
* Supports multiple matching strategies:
|
|
14
|
-
* - Exact matching: "Edit" matches "Edit"
|
|
15
|
-
* - Pipe alternatives: "Edit|Write" matches "Edit" or "Write"
|
|
16
|
-
* - Glob patterns: "Edit*" matches "EditFile", "EditText", etc.
|
|
17
|
-
* - Case insensitive matching
|
|
18
|
-
*/
|
|
19
|
-
matches(pattern: string, toolName: string): boolean {
|
|
20
|
-
if (!pattern || !toolName) return false;
|
|
21
|
-
|
|
22
|
-
// Handle pipe-separated alternatives (e.g., "Edit|Write|Delete")
|
|
23
|
-
if (pattern.includes("|")) {
|
|
24
|
-
const alternatives = pattern.split("|").map((alt) => alt.trim());
|
|
25
|
-
return alternatives.some((alt) => this.matchesSingle(alt, toolName));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return this.matchesSingle(pattern, toolName);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Match a single pattern against tool name
|
|
33
|
-
*/
|
|
34
|
-
private matchesSingle(pattern: string, toolName: string): boolean {
|
|
35
|
-
// Exact match (case insensitive)
|
|
36
|
-
if (pattern.toLowerCase() === toolName.toLowerCase()) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Glob pattern matching using minimatch
|
|
41
|
-
try {
|
|
42
|
-
return minimatch(toolName, pattern, {
|
|
43
|
-
nocase: true, // Case insensitive
|
|
44
|
-
noglobstar: false, // Allow ** patterns
|
|
45
|
-
nonegate: true, // Disable negation for security
|
|
46
|
-
});
|
|
47
|
-
} catch {
|
|
48
|
-
// Invalid pattern, fall back to exact match
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Validate pattern syntax
|
|
55
|
-
*/
|
|
56
|
-
isValidPattern(pattern: string): boolean {
|
|
57
|
-
if (!pattern || typeof pattern !== "string") return false;
|
|
58
|
-
|
|
59
|
-
// Empty pattern is invalid
|
|
60
|
-
if (pattern.trim().length === 0) return false;
|
|
61
|
-
|
|
62
|
-
// Handle pipe-separated alternatives
|
|
63
|
-
if (pattern.includes("|")) {
|
|
64
|
-
const alternatives = pattern.split("|").map((alt) => alt.trim());
|
|
65
|
-
return (
|
|
66
|
-
alternatives.length > 0 &&
|
|
67
|
-
alternatives.every(
|
|
68
|
-
(alt) => alt.length > 0 && this.isValidSinglePattern(alt),
|
|
69
|
-
)
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return this.isValidSinglePattern(pattern);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Validate single pattern syntax
|
|
78
|
-
*/
|
|
79
|
-
private isValidSinglePattern(pattern: string): boolean {
|
|
80
|
-
// Basic validation - non-empty string
|
|
81
|
-
if (!pattern || pattern.trim().length === 0) return false;
|
|
82
|
-
|
|
83
|
-
// Check for dangerous characters that could be used for command injection
|
|
84
|
-
// Note: [ ] are allowed for glob patterns
|
|
85
|
-
const dangerousChars = /[;&|`$(){}><]/;
|
|
86
|
-
if (dangerousChars.test(pattern)) return false;
|
|
87
|
-
|
|
88
|
-
// Validate glob pattern syntax using minimatch
|
|
89
|
-
try {
|
|
90
|
-
// Test with a dummy string to validate pattern
|
|
91
|
-
minimatch("test", pattern, { nocase: true });
|
|
92
|
-
return true;
|
|
93
|
-
} catch {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Get pattern type for optimization
|
|
100
|
-
*/
|
|
101
|
-
getPatternType(pattern: string): "exact" | "glob" | "regex" | "alternatives" {
|
|
102
|
-
if (!pattern) return "exact";
|
|
103
|
-
|
|
104
|
-
// Check for pipe alternatives first
|
|
105
|
-
if (pattern.includes("|")) {
|
|
106
|
-
return "alternatives";
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check for regex patterns first (before glob check)
|
|
110
|
-
if (
|
|
111
|
-
pattern.startsWith("/") &&
|
|
112
|
-
pattern.endsWith("/") &&
|
|
113
|
-
pattern.length > 2
|
|
114
|
-
) {
|
|
115
|
-
return "regex";
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Check for glob patterns
|
|
119
|
-
if (
|
|
120
|
-
pattern.includes("*") ||
|
|
121
|
-
pattern.includes("?") ||
|
|
122
|
-
pattern.includes("[")
|
|
123
|
-
) {
|
|
124
|
-
return "glob";
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return "exact";
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Get all tool names that would match this pattern from a given list
|
|
132
|
-
* Useful for testing and validation
|
|
133
|
-
*/
|
|
134
|
-
getMatches(pattern: string, tools: string[]): string[] {
|
|
135
|
-
return tools.filter((toolName) => this.matches(pattern, toolName));
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Optimize pattern for repeated matching
|
|
140
|
-
* Returns a compiled matcher function for performance
|
|
141
|
-
*/
|
|
142
|
-
compile(pattern: string): (toolName: string) => boolean {
|
|
143
|
-
if (!this.isValidPattern(pattern)) {
|
|
144
|
-
return () => false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const patternType = this.getPatternType(pattern);
|
|
148
|
-
|
|
149
|
-
switch (patternType) {
|
|
150
|
-
case "exact": {
|
|
151
|
-
const lowerPattern = pattern.toLowerCase();
|
|
152
|
-
return (toolName: string) => toolName.toLowerCase() === lowerPattern;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
case "alternatives": {
|
|
156
|
-
const alternatives = pattern
|
|
157
|
-
.split("|")
|
|
158
|
-
.map((alt) => alt.trim().toLowerCase());
|
|
159
|
-
return (toolName: string) => {
|
|
160
|
-
const lowerTool = toolName.toLowerCase();
|
|
161
|
-
return alternatives.some(
|
|
162
|
-
(alt) =>
|
|
163
|
-
lowerTool === alt || minimatch(toolName, alt, { nocase: true }),
|
|
164
|
-
);
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
case "glob":
|
|
169
|
-
return (toolName: string) =>
|
|
170
|
-
minimatch(toolName, pattern, { nocase: true });
|
|
171
|
-
|
|
172
|
-
default:
|
|
173
|
-
return (toolName: string) => this.matches(pattern, toolName);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|