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,357 +0,0 @@
|
|
|
1
|
-
import { handleSessionRestoration } from "./session.js";
|
|
2
|
-
import { setGlobalLogger } from "../utils/globalLogger.js";
|
|
3
|
-
import { LspManager } from "../managers/lspManager.js";
|
|
4
|
-
import { USER_MEMORY_FILE } from "../utils/constants.js";
|
|
5
|
-
import type {
|
|
6
|
-
Message,
|
|
7
|
-
Logger,
|
|
8
|
-
AgentOptions,
|
|
9
|
-
ILspManager,
|
|
10
|
-
} from "../types/index.js";
|
|
11
|
-
import type { SkillManager } from "../managers/skillManager.js";
|
|
12
|
-
import type { SubagentManager } from "../managers/subagentManager.js";
|
|
13
|
-
import type { Container } from "../utils/container.js";
|
|
14
|
-
import type { ToolManager } from "../managers/toolManager.js";
|
|
15
|
-
import type { PluginManager } from "../managers/pluginManager.js";
|
|
16
|
-
import type { SlashCommandManager } from "../managers/slashCommandManager.js";
|
|
17
|
-
import type { McpManager } from "../managers/mcpManager.js";
|
|
18
|
-
import type { ConfigurationService } from "./configurationService.js";
|
|
19
|
-
import type { HookManager } from "../managers/hookManager.js";
|
|
20
|
-
import type { MessageManager } from "../managers/messageManager.js";
|
|
21
|
-
import type { MemoryRuleManager } from "../managers/MemoryRuleManager.js";
|
|
22
|
-
import type { LiveConfigManager } from "../managers/liveConfigManager.js";
|
|
23
|
-
import type { TaskManager } from "./taskManager.js";
|
|
24
|
-
import type { PermissionManager } from "../managers/permissionManager.js";
|
|
25
|
-
import { remoteSettingsService } from "./remoteSettingsService.js";
|
|
26
|
-
|
|
27
|
-
export interface InitializationContext {
|
|
28
|
-
skillManager: SkillManager;
|
|
29
|
-
subagentManager: SubagentManager;
|
|
30
|
-
container: Container;
|
|
31
|
-
toolManager: ToolManager;
|
|
32
|
-
pluginManager: PluginManager;
|
|
33
|
-
options: AgentOptions;
|
|
34
|
-
slashCommandManager: SlashCommandManager;
|
|
35
|
-
logger?: Logger;
|
|
36
|
-
mcpManager: McpManager;
|
|
37
|
-
workdir: string;
|
|
38
|
-
lspManager: ILspManager;
|
|
39
|
-
configurationService: ConfigurationService;
|
|
40
|
-
hookManager: HookManager;
|
|
41
|
-
messageManager: MessageManager;
|
|
42
|
-
memoryRuleManager: MemoryRuleManager;
|
|
43
|
-
liveConfigManager: LiveConfigManager;
|
|
44
|
-
taskManager: TaskManager;
|
|
45
|
-
resolveAndValidateConfig: () => void;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export class InitializationService {
|
|
49
|
-
public static async initialize(
|
|
50
|
-
context: InitializationContext,
|
|
51
|
-
options?: {
|
|
52
|
-
restoreSessionId?: string;
|
|
53
|
-
continueLastSession?: boolean;
|
|
54
|
-
messages?: Message[];
|
|
55
|
-
},
|
|
56
|
-
): Promise<void> {
|
|
57
|
-
const {
|
|
58
|
-
skillManager,
|
|
59
|
-
subagentManager,
|
|
60
|
-
container,
|
|
61
|
-
toolManager,
|
|
62
|
-
pluginManager,
|
|
63
|
-
options: agentOptions,
|
|
64
|
-
slashCommandManager,
|
|
65
|
-
logger,
|
|
66
|
-
mcpManager,
|
|
67
|
-
workdir,
|
|
68
|
-
lspManager,
|
|
69
|
-
configurationService,
|
|
70
|
-
hookManager,
|
|
71
|
-
messageManager,
|
|
72
|
-
memoryRuleManager,
|
|
73
|
-
liveConfigManager,
|
|
74
|
-
taskManager,
|
|
75
|
-
resolveAndValidateConfig,
|
|
76
|
-
} = context;
|
|
77
|
-
|
|
78
|
-
const startTime = performance.now();
|
|
79
|
-
|
|
80
|
-
// Set global logger early so managers can use it during initialization
|
|
81
|
-
setGlobalLogger(logger || null);
|
|
82
|
-
|
|
83
|
-
// Initialize managers first
|
|
84
|
-
try {
|
|
85
|
-
const phaseStart = performance.now();
|
|
86
|
-
// Initialize SkillManager
|
|
87
|
-
await skillManager.initialize();
|
|
88
|
-
|
|
89
|
-
// Initialize SubagentManager (load and cache configurations)
|
|
90
|
-
await subagentManager.initialize();
|
|
91
|
-
|
|
92
|
-
// Register managers in container for tool access
|
|
93
|
-
container.register("SubagentManager", subagentManager);
|
|
94
|
-
container.register("SkillManager", skillManager);
|
|
95
|
-
|
|
96
|
-
// Initialize built-in tools
|
|
97
|
-
toolManager.initializeBuiltInTools();
|
|
98
|
-
|
|
99
|
-
// Initialize plugins
|
|
100
|
-
await pluginManager.loadPlugins(agentOptions.plugins || []);
|
|
101
|
-
|
|
102
|
-
// Register skill commands
|
|
103
|
-
slashCommandManager.registerSkillCommands(
|
|
104
|
-
skillManager.getAvailableSkills(),
|
|
105
|
-
);
|
|
106
|
-
logger?.debug(
|
|
107
|
-
`Initialization Phase [Managers and Tools] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
108
|
-
);
|
|
109
|
-
} catch (error) {
|
|
110
|
-
logger?.error("Failed to initialize managers and tools:", error);
|
|
111
|
-
// Don't throw error to prevent app startup failure
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Initialize MCP servers with auto-connect
|
|
115
|
-
try {
|
|
116
|
-
const phaseStart = performance.now();
|
|
117
|
-
await mcpManager.initialize(workdir, true);
|
|
118
|
-
if (lspManager instanceof LspManager) {
|
|
119
|
-
await lspManager.initialize(workdir);
|
|
120
|
-
}
|
|
121
|
-
logger?.debug(
|
|
122
|
-
`Initialization Phase [MCP and LSP] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
123
|
-
);
|
|
124
|
-
} catch (error) {
|
|
125
|
-
logger?.error("Failed to initialize MCP servers:", error);
|
|
126
|
-
// Don't throw error to prevent app startup failure
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Load remote settings disk cache synchronously.
|
|
130
|
-
// Must happen BEFORE loadMergedConfiguration so cached managed settings
|
|
131
|
-
// (env, model, disallowedTools) are merged into the config. Settings `env`
|
|
132
|
-
// is stored in the per-session env snapshot (NOT process.env), except
|
|
133
|
-
// WAVE_SERVER_URL which is mirrored to process.env so the network fetch
|
|
134
|
-
// (below) can read it via authService.getServerUrl(); no race.
|
|
135
|
-
try {
|
|
136
|
-
const phaseStart = performance.now();
|
|
137
|
-
await remoteSettingsService.initialize();
|
|
138
|
-
logger?.debug(
|
|
139
|
-
`Initialization Phase [Remote Settings Cache] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
140
|
-
);
|
|
141
|
-
} catch (error) {
|
|
142
|
-
logger?.error("Failed to initialize remote settings:", error);
|
|
143
|
-
// Don't throw error to prevent app startup failure - continue without remote settings
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Initialize hooks configuration
|
|
147
|
-
try {
|
|
148
|
-
const phaseStart = performance.now();
|
|
149
|
-
// Load hooks configuration using ConfigurationService
|
|
150
|
-
const configResult =
|
|
151
|
-
await configurationService.loadMergedConfiguration(workdir);
|
|
152
|
-
|
|
153
|
-
hookManager.loadConfigurationFromWaveConfig(configResult.configuration);
|
|
154
|
-
|
|
155
|
-
// Update plugin manager with enabled plugins configuration
|
|
156
|
-
if (configResult.configuration?.enabledPlugins) {
|
|
157
|
-
pluginManager.updateEnabledPlugins(
|
|
158
|
-
configResult.configuration.enabledPlugins,
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Initialize permission manager with loaded rules
|
|
163
|
-
if (configResult.configuration?.permissions) {
|
|
164
|
-
const permissionManager =
|
|
165
|
-
context.container.get<PermissionManager>("PermissionManager");
|
|
166
|
-
if (permissionManager) {
|
|
167
|
-
if (configResult.configuration.permissions.allow) {
|
|
168
|
-
permissionManager.updateAllowedRules(
|
|
169
|
-
configResult.configuration.permissions.allow,
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
if (configResult.configuration.permissions.deny) {
|
|
173
|
-
permissionManager.updateDeniedRules(
|
|
174
|
-
configResult.configuration.permissions.deny,
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
if (configResult.configuration.permissions.permissionMode) {
|
|
178
|
-
permissionManager.updateConfiguredPermissionMode(
|
|
179
|
-
configResult.configuration.permissions.permissionMode,
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
if (configResult.configuration.permissions.additionalDirectories) {
|
|
183
|
-
permissionManager.updateAdditionalDirectories(
|
|
184
|
-
configResult.configuration.permissions.additionalDirectories,
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
logger?.debug(
|
|
190
|
-
`Initialization Phase [Hooks Configuration] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
191
|
-
);
|
|
192
|
-
} catch (error) {
|
|
193
|
-
logger?.error("Failed to initialize hooks system:", error);
|
|
194
|
-
// Don't throw error to prevent app startup failure
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Start remote settings network fetch + polling now that the config is
|
|
198
|
-
// merged. Settings `env` WAVE_SERVER_URL was mirrored to process.env by
|
|
199
|
-
// loadMergedConfiguration → setEnvironmentVars, so the fetch reads it via
|
|
200
|
-
// authService.getServerUrl(); fire-and-forget, failures fall back to the
|
|
201
|
-
// cached/merged settings.
|
|
202
|
-
remoteSettingsService.startBackgroundFetch();
|
|
203
|
-
|
|
204
|
-
// Execute SessionStart hooks
|
|
205
|
-
try {
|
|
206
|
-
const phaseStart = performance.now();
|
|
207
|
-
const sessionStartResult = await hookManager.executeSessionStartHooks(
|
|
208
|
-
"startup",
|
|
209
|
-
messageManager.getSessionId(),
|
|
210
|
-
messageManager.getTranscriptPath(),
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
// Inject additionalContext as a meta user message (matches Claude Code)
|
|
214
|
-
if (sessionStartResult.additionalContext) {
|
|
215
|
-
messageManager.addUserMessage({
|
|
216
|
-
content: `<system-reminder>\nSessionStart hook additional context: ${sessionStartResult.additionalContext}\n</system-reminder>`,
|
|
217
|
-
isMeta: true,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Inject initialUserMessage as a meta user message
|
|
222
|
-
if (sessionStartResult.initialUserMessage) {
|
|
223
|
-
messageManager.addUserMessage({
|
|
224
|
-
content: sessionStartResult.initialUserMessage,
|
|
225
|
-
isMeta: true,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
logger?.debug(
|
|
230
|
-
`Initialization Phase [SessionStart Hooks] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
231
|
-
);
|
|
232
|
-
} catch (error) {
|
|
233
|
-
logger?.warn("SessionStart hooks execution failed:", error);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Trigger WorktreeCreate hook if this is a new worktree
|
|
237
|
-
if (agentOptions.isNewWorktree && hookManager) {
|
|
238
|
-
try {
|
|
239
|
-
logger?.info(
|
|
240
|
-
`Triggering WorktreeCreate hook for ${agentOptions.worktreeName}...`,
|
|
241
|
-
);
|
|
242
|
-
const hookResults = await hookManager.executeHooks("WorktreeCreate", {
|
|
243
|
-
event: "WorktreeCreate",
|
|
244
|
-
projectDir: workdir,
|
|
245
|
-
timestamp: new Date(),
|
|
246
|
-
sessionId: messageManager.getSessionId(),
|
|
247
|
-
transcriptPath: messageManager.getTranscriptPath(),
|
|
248
|
-
cwd: workdir,
|
|
249
|
-
worktreeName: agentOptions.worktreeName,
|
|
250
|
-
env: Object.fromEntries(
|
|
251
|
-
Object.entries(configurationService.getMergedEnv()).filter(
|
|
252
|
-
(e) => e[1] !== undefined,
|
|
253
|
-
),
|
|
254
|
-
) as Record<string, string>,
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// Process hook results
|
|
258
|
-
hookManager.processHookResults(
|
|
259
|
-
"WorktreeCreate",
|
|
260
|
-
hookResults,
|
|
261
|
-
messageManager,
|
|
262
|
-
);
|
|
263
|
-
} catch (error) {
|
|
264
|
-
logger?.warn("WorktreeCreate hooks execution failed:", error);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Resolve and validate configuration after loading settings.json
|
|
269
|
-
resolveAndValidateConfig();
|
|
270
|
-
|
|
271
|
-
// Initialize auto-memory directory
|
|
272
|
-
try {
|
|
273
|
-
const phaseStart = performance.now();
|
|
274
|
-
if (configurationService.resolveAutoMemoryEnabled()) {
|
|
275
|
-
const memoryService =
|
|
276
|
-
container.get<import("./memory.js").MemoryService>("MemoryService");
|
|
277
|
-
if (memoryService) {
|
|
278
|
-
await memoryService.ensureAutoMemoryDirectory(workdir);
|
|
279
|
-
const permissionManager =
|
|
280
|
-
container.get<PermissionManager>("PermissionManager");
|
|
281
|
-
if (permissionManager) {
|
|
282
|
-
const autoMemoryDir = memoryService.getAutoMemoryDirectory(workdir);
|
|
283
|
-
permissionManager.addSystemAdditionalDirectory(autoMemoryDir);
|
|
284
|
-
permissionManager.addSystemAdditionalDirectory(USER_MEMORY_FILE);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
logger?.debug(
|
|
289
|
-
`Initialization Phase [Auto-memory Initialization] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
290
|
-
);
|
|
291
|
-
} catch (error) {
|
|
292
|
-
logger?.error("Failed to initialize auto-memory directory:", error);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Discover modular memory rules
|
|
296
|
-
try {
|
|
297
|
-
const phaseStart = performance.now();
|
|
298
|
-
await memoryRuleManager.discoverRules();
|
|
299
|
-
logger?.debug(
|
|
300
|
-
`Initialization Phase [Memory Rules Discovery] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
301
|
-
);
|
|
302
|
-
} catch (error) {
|
|
303
|
-
logger?.error("Failed to discover memory rules:", error);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Initialize live configuration reload
|
|
307
|
-
try {
|
|
308
|
-
const phaseStart = performance.now();
|
|
309
|
-
await liveConfigManager.initialize();
|
|
310
|
-
logger?.debug(
|
|
311
|
-
`Initialization Phase [Live Config Initialization] took ${(performance.now() - phaseStart).toFixed(2)}ms`,
|
|
312
|
-
);
|
|
313
|
-
} catch (error) {
|
|
314
|
-
logger?.error("Failed to initialize live configuration reload:", error);
|
|
315
|
-
// Don't throw error to prevent app startup failure - continue without live reload
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Memory is lazy-cached on first getCombinedMemoryContent call
|
|
319
|
-
// No explicit loading needed during initialization
|
|
320
|
-
|
|
321
|
-
// Handle session restoration or set provided messages
|
|
322
|
-
const sessionPhaseStart = performance.now();
|
|
323
|
-
if (options?.messages) {
|
|
324
|
-
// If messages are provided, use them directly (useful for testing)
|
|
325
|
-
messageManager.setMessages(options.messages);
|
|
326
|
-
// Rebuild usage array from restored messages
|
|
327
|
-
messageManager.rebuildUsageFromMessages(options.messages);
|
|
328
|
-
} else {
|
|
329
|
-
// Otherwise, handle session restoration
|
|
330
|
-
const sessionToRestore = await handleSessionRestoration(
|
|
331
|
-
options?.restoreSessionId,
|
|
332
|
-
options?.continueLastSession,
|
|
333
|
-
messageManager.getWorkdir(),
|
|
334
|
-
);
|
|
335
|
-
// Rebuild usage array from restored messages
|
|
336
|
-
messageManager.rebuildUsageFromMessages(sessionToRestore?.messages || []);
|
|
337
|
-
|
|
338
|
-
if (sessionToRestore) {
|
|
339
|
-
messageManager.initializeFromSession(sessionToRestore);
|
|
340
|
-
|
|
341
|
-
// Update task manager with the root session ID to ensure continuity across compactions
|
|
342
|
-
taskManager.setTaskListId(sessionToRestore.id);
|
|
343
|
-
|
|
344
|
-
// After session is initialized, load tasks for the session
|
|
345
|
-
const tasks = await taskManager.listTasks();
|
|
346
|
-
agentOptions.callbacks?.onTasksChange?.(tasks);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
logger?.debug(
|
|
350
|
-
`Initialization Phase [Session Restoration] took ${(performance.now() - sessionPhaseStart).toFixed(2)}ms`,
|
|
351
|
-
);
|
|
352
|
-
|
|
353
|
-
logger?.debug(
|
|
354
|
-
`Total Initialization took ${(performance.now() - startTime).toFixed(2)}ms`,
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import { loadSessionFromJsonl } from "./session.js";
|
|
2
|
-
import type { Logger, AgentOptions } from "../types/index.js";
|
|
3
|
-
import type { MessageManager } from "../managers/messageManager.js";
|
|
4
|
-
import type { SlashCommandManager } from "../managers/slashCommandManager.js";
|
|
5
|
-
import type { HookManager } from "../managers/hookManager.js";
|
|
6
|
-
import type { ConfigurationService } from "./configurationService.js";
|
|
7
|
-
import type { AIManager } from "../managers/aiManager.js";
|
|
8
|
-
import type { SubagentManager } from "../managers/subagentManager.js";
|
|
9
|
-
import type { TaskManager } from "./taskManager.js";
|
|
10
|
-
|
|
11
|
-
export interface InteractionContext {
|
|
12
|
-
messageManager: MessageManager;
|
|
13
|
-
slashCommandManager: SlashCommandManager;
|
|
14
|
-
hookManager: HookManager;
|
|
15
|
-
workdir: string;
|
|
16
|
-
configurationService: ConfigurationService;
|
|
17
|
-
logger?: Logger;
|
|
18
|
-
aiManager: AIManager;
|
|
19
|
-
subagentManager: SubagentManager;
|
|
20
|
-
taskManager: TaskManager;
|
|
21
|
-
options: AgentOptions;
|
|
22
|
-
abortMessage: () => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class InteractionService {
|
|
26
|
-
public static async sendMessage(
|
|
27
|
-
context: InteractionContext,
|
|
28
|
-
content: string,
|
|
29
|
-
images?: Array<{ path: string; mimeType: string }>,
|
|
30
|
-
): Promise<void> {
|
|
31
|
-
const {
|
|
32
|
-
messageManager,
|
|
33
|
-
slashCommandManager,
|
|
34
|
-
hookManager,
|
|
35
|
-
workdir,
|
|
36
|
-
logger,
|
|
37
|
-
aiManager,
|
|
38
|
-
} = context;
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
// Handle slash command - check if it's a slash command (starts with /)
|
|
42
|
-
if (content.startsWith("/")) {
|
|
43
|
-
const command = content.trim();
|
|
44
|
-
if (!command || command === "/") return;
|
|
45
|
-
|
|
46
|
-
// Parse and validate slash command
|
|
47
|
-
const { isValid, commandId, args } =
|
|
48
|
-
slashCommandManager.parseAndValidateSlashCommand(command);
|
|
49
|
-
|
|
50
|
-
if (isValid && commandId !== undefined) {
|
|
51
|
-
// Execute valid slash command
|
|
52
|
-
// Note: executeCommand sets isLoading early (e.g., custom commands set it
|
|
53
|
-
// before bash execution). sendAIMessage() no longer guards against isLoading,
|
|
54
|
-
// so callers can safely set it early without blocking subsequent AI calls.
|
|
55
|
-
await slashCommandManager.executeCommand(commandId, args);
|
|
56
|
-
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// If command doesn't exist, continue as normal message processing
|
|
61
|
-
// Don't add to history, let normal message processing logic below handle it
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Handle normal AI message
|
|
65
|
-
// Add user message first, will automatically sync to UI
|
|
66
|
-
messageManager.addUserMessage({
|
|
67
|
-
content,
|
|
68
|
-
images: images?.map((img) => ({
|
|
69
|
-
path: img.path,
|
|
70
|
-
mimeType: img.mimeType,
|
|
71
|
-
})),
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Reserve loading state synchronously before any async work (hooks).
|
|
75
|
-
// This closes the race window where a concurrent notification/message
|
|
76
|
-
// could see isLoading=false during the await below and start a second
|
|
77
|
-
// sendAIMessage. sendAIMessage's generation guard is the backstop, but
|
|
78
|
-
// reserving here prevents the race at its source.
|
|
79
|
-
aiManager.setIsLoading(true);
|
|
80
|
-
|
|
81
|
-
// Execute UserPromptSubmit hooks after adding the user message
|
|
82
|
-
if (hookManager) {
|
|
83
|
-
try {
|
|
84
|
-
const hookResults = await hookManager.executeHooks(
|
|
85
|
-
"UserPromptSubmit",
|
|
86
|
-
{
|
|
87
|
-
event: "UserPromptSubmit",
|
|
88
|
-
projectDir: workdir,
|
|
89
|
-
timestamp: new Date(),
|
|
90
|
-
// UserPromptSubmit doesn't need toolName
|
|
91
|
-
sessionId: messageManager.getSessionId(),
|
|
92
|
-
transcriptPath: messageManager.getTranscriptPath(),
|
|
93
|
-
cwd: workdir,
|
|
94
|
-
userPrompt: content,
|
|
95
|
-
env: Object.fromEntries(
|
|
96
|
-
Object.entries(
|
|
97
|
-
context.configurationService.getMergedEnv(),
|
|
98
|
-
).filter((e) => e[1] !== undefined),
|
|
99
|
-
) as Record<string, string>, // Include environment variables
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// Process hook results and determine if we should continue
|
|
104
|
-
const processResult = hookManager.processHookResults(
|
|
105
|
-
"UserPromptSubmit",
|
|
106
|
-
hookResults,
|
|
107
|
-
messageManager,
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
// If hook processing indicates we should block (exit code 2), stop here
|
|
111
|
-
if (processResult.shouldBlock) {
|
|
112
|
-
logger?.info(
|
|
113
|
-
"UserPromptSubmit hook blocked prompt processing with error:",
|
|
114
|
-
processResult.errorMessage,
|
|
115
|
-
);
|
|
116
|
-
// Release the loading state we reserved above
|
|
117
|
-
aiManager.setIsLoading(false);
|
|
118
|
-
return; // Don't send to AI
|
|
119
|
-
}
|
|
120
|
-
} catch (error) {
|
|
121
|
-
logger?.warn("UserPromptSubmit hooks execution failed:", error);
|
|
122
|
-
// Continue processing even if hooks fail
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Send AI message
|
|
127
|
-
await aiManager.sendAIMessage();
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.error("Failed to add user message:", error);
|
|
130
|
-
// Ensure loading state is released on error
|
|
131
|
-
aiManager.setIsLoading(false);
|
|
132
|
-
// Loading state will be automatically updated by the useEffect that watches messages
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
public static async restoreSession(
|
|
137
|
-
context: InteractionContext,
|
|
138
|
-
sessionId: string,
|
|
139
|
-
): Promise<void> {
|
|
140
|
-
const {
|
|
141
|
-
messageManager,
|
|
142
|
-
hookManager,
|
|
143
|
-
logger,
|
|
144
|
-
subagentManager,
|
|
145
|
-
taskManager,
|
|
146
|
-
options,
|
|
147
|
-
abortMessage,
|
|
148
|
-
} = context;
|
|
149
|
-
|
|
150
|
-
// 1. Validation
|
|
151
|
-
if (!sessionId || sessionId === messageManager.getSessionId()) {
|
|
152
|
-
return; // No-op if session ID is invalid or already current
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// 2. Auto-save current session
|
|
156
|
-
try {
|
|
157
|
-
await messageManager.saveSession();
|
|
158
|
-
} catch (error) {
|
|
159
|
-
logger?.warn("Failed to save current session before restore:", error);
|
|
160
|
-
// Continue with restoration even if save fails
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// 3. Run SessionEnd hooks for the current session (cleanup before switching)
|
|
164
|
-
const currentSessionId = messageManager.getSessionId();
|
|
165
|
-
const currentTranscriptPath = messageManager.getTranscriptPath();
|
|
166
|
-
if (hookManager) {
|
|
167
|
-
try {
|
|
168
|
-
await hookManager.executeSessionEndHooks(
|
|
169
|
-
"resume",
|
|
170
|
-
currentSessionId,
|
|
171
|
-
currentTranscriptPath,
|
|
172
|
-
);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
logger?.warn(
|
|
175
|
-
`SessionEnd hooks on restore failed: ${(error as Error).message}`,
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// 4. Load target session
|
|
181
|
-
const sessionData = await loadSessionFromJsonl(
|
|
182
|
-
sessionId,
|
|
183
|
-
messageManager.getWorkdir(),
|
|
184
|
-
);
|
|
185
|
-
if (!sessionData) {
|
|
186
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 5. Clean current state
|
|
190
|
-
abortMessage(); // Abort any running operations
|
|
191
|
-
subagentManager.cleanup(); // Clean up active subagents
|
|
192
|
-
|
|
193
|
-
// 6. Rebuild usage (in correct order)
|
|
194
|
-
messageManager.rebuildUsageFromMessages(sessionData.messages);
|
|
195
|
-
|
|
196
|
-
// 7. Initialize session state last
|
|
197
|
-
messageManager.initializeFromSession(sessionData);
|
|
198
|
-
|
|
199
|
-
// 8. Run SessionStart hooks for the restored session and inject additional
|
|
200
|
-
// context as a meta user message (matches Claude Code's resume behavior:
|
|
201
|
-
// SessionEnd then SessionStart, hook messages appended to the conversation)
|
|
202
|
-
if (hookManager) {
|
|
203
|
-
try {
|
|
204
|
-
const sessionStartResult = await hookManager.executeSessionStartHooks(
|
|
205
|
-
"resume",
|
|
206
|
-
sessionData.id,
|
|
207
|
-
messageManager.getTranscriptPath(),
|
|
208
|
-
);
|
|
209
|
-
if (sessionStartResult.additionalContext) {
|
|
210
|
-
messageManager.addUserMessage({
|
|
211
|
-
content: `<system-reminder>\nSessionStart hook additional context: ${sessionStartResult.additionalContext}\n</system-reminder>`,
|
|
212
|
-
isMeta: true,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
} catch (error) {
|
|
216
|
-
logger?.warn(
|
|
217
|
-
`SessionStart hooks on restore failed: ${(error as Error).message}`,
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Update task manager with the root session ID to ensure continuity across compactions
|
|
223
|
-
taskManager.setTaskListId(sessionData.id);
|
|
224
|
-
|
|
225
|
-
// 9. Load tasks for the restored session
|
|
226
|
-
const tasks = await taskManager.listTasks();
|
|
227
|
-
options.callbacks?.onTasksChange?.(tasks);
|
|
228
|
-
}
|
|
229
|
-
}
|