wave-agent-sdk 0.19.6 → 0.19.7
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 +9 -14
- package/dist/agent.js +49 -56
- package/dist/constants/goalPrompts.d.ts +0 -1
- package/dist/constants/subagents.d.ts +0 -1
- package/dist/constants/toolLimits.d.ts +0 -1
- package/dist/constants/tools.d.ts +0 -1
- package/dist/core/plugin.d.ts +0 -1
- package/dist/core/session.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/managers/MemoryRuleManager.d.ts +0 -1
- package/dist/managers/aiManager.d.ts +1 -1
- package/dist/managers/aiManager.js +26 -9
- package/dist/managers/backgroundTaskManager.d.ts +0 -2
- package/dist/managers/backgroundTaskManager.js +16 -19
- package/dist/managers/bangManager.d.ts +0 -1
- package/dist/managers/cronManager.d.ts +0 -1
- package/dist/managers/foregroundTaskManager.d.ts +0 -1
- package/dist/managers/forkedAgentManager.d.ts +0 -1
- package/dist/managers/goalManager.d.ts +0 -1
- package/dist/managers/hookManager.d.ts +0 -1
- package/dist/managers/liveConfigManager.d.ts +0 -1
- package/dist/managers/lspManager.d.ts +0 -1
- package/dist/managers/mcpManager.d.ts +0 -1
- package/dist/managers/messageManager.d.ts +0 -1
- package/dist/managers/messageQueue.d.ts +17 -2
- package/dist/managers/messageQueue.js +40 -1
- package/dist/managers/permissionManager.d.ts +0 -1
- package/dist/managers/planManager.d.ts +0 -1
- package/dist/managers/pluginManager.d.ts +0 -1
- package/dist/managers/pluginScopeManager.d.ts +0 -1
- package/dist/managers/reversionManager.d.ts +0 -1
- package/dist/managers/skillManager.d.ts +0 -1
- package/dist/managers/slashCommandManager.d.ts +0 -1
- package/dist/managers/subagentManager.d.ts +0 -3
- package/dist/managers/subagentManager.js +8 -13
- package/dist/managers/toolManager.d.ts +0 -1
- package/dist/managers/workflowManager.d.ts +1 -2
- package/dist/managers/workflowManager.js +4 -4
- package/dist/prompts/autoMemory.d.ts +0 -1
- package/dist/prompts/autoMemoryExtraction.d.ts +0 -1
- package/dist/prompts/index.d.ts +0 -1
- package/dist/prompts/planModeReminders.d.ts +0 -1
- package/dist/services/GitService.d.ts +0 -1
- package/dist/services/MarketplaceService.d.ts +0 -1
- package/dist/services/MemoryRuleService.d.ts +0 -1
- package/dist/services/aiService.d.ts +0 -1
- package/dist/services/authService.d.ts +0 -1
- package/dist/services/autoMemoryService.d.ts +0 -1
- package/dist/services/configurationService.d.ts +0 -1
- package/dist/services/fileWatcher.d.ts +0 -1
- package/dist/services/hook.d.ts +0 -1
- package/dist/services/initializationService.d.ts +0 -1
- package/dist/services/interactionService.d.ts +0 -1
- package/dist/services/interactionService.js +10 -0
- package/dist/services/jsonlHandler.d.ts +0 -1
- package/dist/services/memory.d.ts +0 -1
- package/dist/services/pluginLoader.d.ts +0 -1
- package/dist/services/remoteSettingsService.d.ts +0 -1
- package/dist/services/reversionService.d.ts +0 -1
- package/dist/services/session.d.ts +0 -1
- package/dist/services/taskManager.d.ts +0 -1
- package/dist/services/taskManager.js +8 -1
- package/dist/telemetry/events.d.ts +0 -1
- package/dist/telemetry/instrumentation.d.ts +0 -1
- package/dist/telemetry/sessionTracing.d.ts +0 -1
- package/dist/tools/agentTool.d.ts +0 -1
- package/dist/tools/askUserQuestion.d.ts +0 -1
- package/dist/tools/bashTool.d.ts +0 -1
- package/dist/tools/buildTool.d.ts +0 -1
- package/dist/tools/cronCreateTool.d.ts +0 -1
- package/dist/tools/cronDeleteTool.d.ts +0 -1
- package/dist/tools/cronListTool.d.ts +0 -1
- package/dist/tools/editTool.d.ts +0 -1
- package/dist/tools/enterPlanMode.d.ts +0 -1
- package/dist/tools/enterWorktreeTool.d.ts +0 -1
- package/dist/tools/exitPlanMode.d.ts +0 -1
- package/dist/tools/exitWorktreeTool.d.ts +0 -1
- package/dist/tools/globTool.d.ts +0 -1
- package/dist/tools/grepTool.d.ts +0 -1
- package/dist/tools/lspTool.d.ts +0 -1
- package/dist/tools/readTool.d.ts +0 -1
- package/dist/tools/skillTool.d.ts +0 -1
- package/dist/tools/taskManagementTools.d.ts +0 -1
- package/dist/tools/taskStopTool.d.ts +0 -1
- package/dist/tools/types.d.ts +0 -1
- package/dist/tools/webFetchTool.d.ts +0 -1
- package/dist/tools/workflowTool.d.ts +0 -1
- package/dist/tools/writeTool.d.ts +0 -1
- package/dist/types/agent.d.ts +0 -1
- package/dist/types/auth.d.ts +0 -1
- package/dist/types/commands.d.ts +0 -1
- package/dist/types/config.d.ts +0 -1
- package/dist/types/configuration.d.ts +0 -1
- package/dist/types/core.d.ts +0 -1
- package/dist/types/cron.d.ts +0 -1
- package/dist/types/environment.d.ts +0 -1
- package/dist/types/fileSearch.d.ts +0 -1
- package/dist/types/history.d.ts +0 -1
- package/dist/types/hooks.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/lsp.d.ts +0 -1
- package/dist/types/marketplace.d.ts +0 -1
- package/dist/types/mcp.d.ts +0 -1
- package/dist/types/memoryRule.d.ts +0 -1
- package/dist/types/messaging.d.ts +0 -1
- package/dist/types/permissions.d.ts +0 -1
- package/dist/types/plugins.d.ts +0 -1
- package/dist/types/processes.d.ts +0 -1
- package/dist/types/reversion.d.ts +0 -1
- package/dist/types/session.d.ts +0 -1
- package/dist/types/skills.d.ts +0 -1
- package/dist/types/tasks.d.ts +0 -1
- package/dist/types/telemetry.d.ts +0 -1
- package/dist/types/tools.d.ts +0 -1
- package/dist/types/workflow.d.ts +0 -1
- package/dist/utils/abortUtils.d.ts +0 -1
- package/dist/utils/atomicWrite.d.ts +0 -1
- package/dist/utils/bashParser.d.ts +0 -1
- package/dist/utils/cacheControlUtils.d.ts +0 -1
- package/dist/utils/commandArgumentParser.d.ts +0 -1
- package/dist/utils/commandPathResolver.d.ts +0 -1
- package/dist/utils/configPaths.d.ts +0 -1
- package/dist/utils/configValidator.d.ts +0 -1
- package/dist/utils/constants.d.ts +0 -1
- package/dist/utils/container.d.ts +0 -1
- package/dist/utils/containerSetup.d.ts +0 -1
- package/dist/utils/containerSetup.js +0 -3
- package/dist/utils/convertMessagesForAPI.d.ts +0 -1
- package/dist/utils/cronTasks.d.ts +0 -1
- package/dist/utils/cronTasksLock.d.ts +0 -1
- package/dist/utils/cronToHuman.d.ts +0 -1
- package/dist/utils/customCommands.d.ts +0 -1
- package/dist/utils/editUtils.d.ts +0 -1
- package/dist/utils/fileFormat.d.ts +0 -1
- package/dist/utils/fileSearch.d.ts +0 -1
- package/dist/utils/fileUtils.d.ts +0 -1
- package/dist/utils/gitUtils.d.ts +0 -1
- package/dist/utils/globalLogger.d.ts +0 -1
- package/dist/utils/groupMessagesByApiRound.d.ts +0 -1
- package/dist/utils/hookMatcher.d.ts +0 -1
- package/dist/utils/markdownParser.d.ts +0 -1
- package/dist/utils/mcpUtils.d.ts +0 -1
- package/dist/utils/messageOperations.d.ts +0 -1
- package/dist/utils/modelCapabilities.d.ts +0 -1
- package/dist/utils/nameGenerator.d.ts +0 -1
- package/dist/utils/notificationXml.d.ts +0 -1
- package/dist/utils/openaiClient.d.ts +0 -1
- package/dist/utils/parseCronExpression.d.ts +0 -1
- package/dist/utils/path.d.ts +0 -1
- package/dist/utils/pathEncoder.d.ts +0 -1
- package/dist/utils/pathSafety.d.ts +0 -1
- package/dist/utils/promptHistory.d.ts +0 -1
- package/dist/utils/ripgrep.d.ts +0 -1
- package/dist/utils/shellResolver.d.ts +0 -1
- package/dist/utils/skillParser.d.ts +0 -1
- package/dist/utils/stringUtils.d.ts +0 -1
- package/dist/utils/subagentParser.d.ts +0 -1
- package/dist/utils/taskReminder.d.ts +0 -1
- package/dist/utils/tokenCalculation.d.ts +0 -1
- package/dist/utils/tokenEstimate.d.ts +0 -1
- package/dist/utils/toolResultStorage.d.ts +0 -1
- package/dist/utils/worktreeSession.d.ts +0 -1
- package/dist/utils/worktreeUtils.d.ts +0 -1
- package/dist/workflow/budgetTracker.d.ts +0 -1
- package/dist/workflow/concurrencyLimiter.d.ts +0 -1
- package/dist/workflow/journal.d.ts +0 -1
- package/dist/workflow/progressReporter.d.ts +0 -1
- package/dist/workflow/runState.d.ts +0 -1
- package/dist/workflow/scriptRuntime.d.ts +0 -1
- package/dist/workflow/structuredOutput.d.ts +0 -1
- package/dist/workflow/types.d.ts +0 -1
- package/dist/workflow/workflowApis.d.ts +0 -1
- package/package.json +1 -1
- package/src/agent.ts +49 -67
- package/src/managers/aiManager.ts +30 -10
- package/src/managers/backgroundTaskManager.ts +17 -21
- package/src/managers/messageQueue.ts +43 -2
- package/src/managers/subagentManager.ts +9 -15
- package/src/managers/workflowManager.ts +5 -5
- package/src/services/interactionService.ts +11 -0
- package/src/services/taskManager.ts +8 -1
- package/src/utils/containerSetup.ts +0 -4
- package/dist/agent.d.ts.map +0 -1
- package/dist/constants/goalPrompts.d.ts.map +0 -1
- package/dist/constants/subagents.d.ts.map +0 -1
- package/dist/constants/toolLimits.d.ts.map +0 -1
- package/dist/constants/tools.d.ts.map +0 -1
- package/dist/core/plugin.d.ts.map +0 -1
- package/dist/core/session.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/managers/MemoryRuleManager.d.ts.map +0 -1
- package/dist/managers/aiManager.d.ts.map +0 -1
- package/dist/managers/backgroundTaskManager.d.ts.map +0 -1
- package/dist/managers/bangManager.d.ts.map +0 -1
- package/dist/managers/cronManager.d.ts.map +0 -1
- package/dist/managers/foregroundTaskManager.d.ts.map +0 -1
- package/dist/managers/forkedAgentManager.d.ts.map +0 -1
- package/dist/managers/goalManager.d.ts.map +0 -1
- package/dist/managers/hookManager.d.ts.map +0 -1
- package/dist/managers/liveConfigManager.d.ts.map +0 -1
- package/dist/managers/lspManager.d.ts.map +0 -1
- package/dist/managers/mcpManager.d.ts.map +0 -1
- package/dist/managers/messageManager.d.ts.map +0 -1
- package/dist/managers/messageQueue.d.ts.map +0 -1
- package/dist/managers/notificationQueue.d.ts +0 -8
- package/dist/managers/notificationQueue.d.ts.map +0 -1
- package/dist/managers/notificationQueue.js +0 -17
- package/dist/managers/permissionManager.d.ts.map +0 -1
- package/dist/managers/planManager.d.ts.map +0 -1
- package/dist/managers/pluginManager.d.ts.map +0 -1
- package/dist/managers/pluginScopeManager.d.ts.map +0 -1
- package/dist/managers/reversionManager.d.ts.map +0 -1
- package/dist/managers/skillManager.d.ts.map +0 -1
- package/dist/managers/slashCommandManager.d.ts.map +0 -1
- package/dist/managers/subagentManager.d.ts.map +0 -1
- package/dist/managers/toolManager.d.ts.map +0 -1
- package/dist/managers/workflowManager.d.ts.map +0 -1
- package/dist/prompts/autoMemory.d.ts.map +0 -1
- package/dist/prompts/autoMemoryExtraction.d.ts.map +0 -1
- package/dist/prompts/index.d.ts.map +0 -1
- package/dist/prompts/planModeReminders.d.ts.map +0 -1
- package/dist/services/GitService.d.ts.map +0 -1
- package/dist/services/MarketplaceService.d.ts.map +0 -1
- package/dist/services/MemoryRuleService.d.ts.map +0 -1
- package/dist/services/aiService.d.ts.map +0 -1
- package/dist/services/authService.d.ts.map +0 -1
- package/dist/services/autoMemoryService.d.ts.map +0 -1
- package/dist/services/configurationService.d.ts.map +0 -1
- package/dist/services/fileWatcher.d.ts.map +0 -1
- package/dist/services/hook.d.ts.map +0 -1
- package/dist/services/initializationService.d.ts.map +0 -1
- package/dist/services/interactionService.d.ts.map +0 -1
- package/dist/services/jsonlHandler.d.ts.map +0 -1
- package/dist/services/memory.d.ts.map +0 -1
- package/dist/services/pluginLoader.d.ts.map +0 -1
- package/dist/services/remoteSettingsService.d.ts.map +0 -1
- package/dist/services/reversionService.d.ts.map +0 -1
- package/dist/services/session.d.ts.map +0 -1
- package/dist/services/taskManager.d.ts.map +0 -1
- package/dist/telemetry/events.d.ts.map +0 -1
- package/dist/telemetry/instrumentation.d.ts.map +0 -1
- package/dist/telemetry/sessionTracing.d.ts.map +0 -1
- package/dist/tools/agentTool.d.ts.map +0 -1
- package/dist/tools/askUserQuestion.d.ts.map +0 -1
- package/dist/tools/bashTool.d.ts.map +0 -1
- package/dist/tools/buildTool.d.ts.map +0 -1
- package/dist/tools/cronCreateTool.d.ts.map +0 -1
- package/dist/tools/cronDeleteTool.d.ts.map +0 -1
- package/dist/tools/cronListTool.d.ts.map +0 -1
- package/dist/tools/editTool.d.ts.map +0 -1
- package/dist/tools/enterPlanMode.d.ts.map +0 -1
- package/dist/tools/enterWorktreeTool.d.ts.map +0 -1
- package/dist/tools/exitPlanMode.d.ts.map +0 -1
- package/dist/tools/exitWorktreeTool.d.ts.map +0 -1
- package/dist/tools/globTool.d.ts.map +0 -1
- package/dist/tools/grepTool.d.ts.map +0 -1
- package/dist/tools/lspTool.d.ts.map +0 -1
- package/dist/tools/readTool.d.ts.map +0 -1
- package/dist/tools/skillTool.d.ts.map +0 -1
- package/dist/tools/taskManagementTools.d.ts.map +0 -1
- package/dist/tools/taskStopTool.d.ts.map +0 -1
- package/dist/tools/types.d.ts.map +0 -1
- package/dist/tools/webFetchTool.d.ts.map +0 -1
- package/dist/tools/workflowTool.d.ts.map +0 -1
- package/dist/tools/writeTool.d.ts.map +0 -1
- package/dist/types/agent.d.ts.map +0 -1
- package/dist/types/auth.d.ts.map +0 -1
- package/dist/types/commands.d.ts.map +0 -1
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/configuration.d.ts.map +0 -1
- package/dist/types/core.d.ts.map +0 -1
- package/dist/types/cron.d.ts.map +0 -1
- package/dist/types/environment.d.ts.map +0 -1
- package/dist/types/fileSearch.d.ts.map +0 -1
- package/dist/types/history.d.ts.map +0 -1
- package/dist/types/hooks.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/lsp.d.ts.map +0 -1
- package/dist/types/marketplace.d.ts.map +0 -1
- package/dist/types/mcp.d.ts.map +0 -1
- package/dist/types/memoryRule.d.ts.map +0 -1
- package/dist/types/messaging.d.ts.map +0 -1
- package/dist/types/permissions.d.ts.map +0 -1
- package/dist/types/plugins.d.ts.map +0 -1
- package/dist/types/processes.d.ts.map +0 -1
- package/dist/types/reversion.d.ts.map +0 -1
- package/dist/types/session.d.ts.map +0 -1
- package/dist/types/skills.d.ts.map +0 -1
- package/dist/types/tasks.d.ts.map +0 -1
- package/dist/types/telemetry.d.ts.map +0 -1
- package/dist/types/tools.d.ts.map +0 -1
- package/dist/types/workflow.d.ts.map +0 -1
- package/dist/utils/abortUtils.d.ts.map +0 -1
- package/dist/utils/atomicWrite.d.ts.map +0 -1
- package/dist/utils/bashParser.d.ts.map +0 -1
- package/dist/utils/cacheControlUtils.d.ts.map +0 -1
- package/dist/utils/commandArgumentParser.d.ts.map +0 -1
- package/dist/utils/commandPathResolver.d.ts.map +0 -1
- package/dist/utils/configPaths.d.ts.map +0 -1
- package/dist/utils/configValidator.d.ts.map +0 -1
- package/dist/utils/constants.d.ts.map +0 -1
- package/dist/utils/container.d.ts.map +0 -1
- package/dist/utils/containerSetup.d.ts.map +0 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +0 -1
- package/dist/utils/cronTasks.d.ts.map +0 -1
- package/dist/utils/cronTasksLock.d.ts.map +0 -1
- package/dist/utils/cronToHuman.d.ts.map +0 -1
- package/dist/utils/customCommands.d.ts.map +0 -1
- package/dist/utils/editUtils.d.ts.map +0 -1
- package/dist/utils/fileFormat.d.ts.map +0 -1
- package/dist/utils/fileSearch.d.ts.map +0 -1
- package/dist/utils/fileUtils.d.ts.map +0 -1
- package/dist/utils/gitUtils.d.ts.map +0 -1
- package/dist/utils/globalLogger.d.ts.map +0 -1
- package/dist/utils/groupMessagesByApiRound.d.ts.map +0 -1
- package/dist/utils/hookMatcher.d.ts.map +0 -1
- package/dist/utils/markdownParser.d.ts.map +0 -1
- package/dist/utils/mcpUtils.d.ts.map +0 -1
- package/dist/utils/messageOperations.d.ts.map +0 -1
- package/dist/utils/modelCapabilities.d.ts.map +0 -1
- package/dist/utils/nameGenerator.d.ts.map +0 -1
- package/dist/utils/notificationXml.d.ts.map +0 -1
- package/dist/utils/openaiClient.d.ts.map +0 -1
- package/dist/utils/parseCronExpression.d.ts.map +0 -1
- package/dist/utils/path.d.ts.map +0 -1
- package/dist/utils/pathEncoder.d.ts.map +0 -1
- package/dist/utils/pathSafety.d.ts.map +0 -1
- package/dist/utils/promptHistory.d.ts.map +0 -1
- package/dist/utils/ripgrep.d.ts.map +0 -1
- package/dist/utils/shellResolver.d.ts.map +0 -1
- package/dist/utils/skillParser.d.ts.map +0 -1
- package/dist/utils/stringUtils.d.ts.map +0 -1
- package/dist/utils/subagentParser.d.ts.map +0 -1
- package/dist/utils/taskReminder.d.ts.map +0 -1
- package/dist/utils/tokenCalculation.d.ts.map +0 -1
- package/dist/utils/tokenEstimate.d.ts.map +0 -1
- package/dist/utils/toolResultStorage.d.ts.map +0 -1
- package/dist/utils/worktreeSession.d.ts.map +0 -1
- package/dist/utils/worktreeUtils.d.ts.map +0 -1
- package/dist/workflow/budgetTracker.d.ts.map +0 -1
- package/dist/workflow/concurrencyLimiter.d.ts.map +0 -1
- package/dist/workflow/journal.d.ts.map +0 -1
- package/dist/workflow/progressReporter.d.ts.map +0 -1
- package/dist/workflow/runState.d.ts.map +0 -1
- package/dist/workflow/scriptRuntime.d.ts.map +0 -1
- package/dist/workflow/structuredOutput.d.ts.map +0 -1
- package/dist/workflow/types.d.ts.map +0 -1
- package/dist/workflow/workflowApis.d.ts.map +0 -1
- package/src/managers/notificationQueue.ts +0 -19
package/src/agent.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { BangManager } from "./managers/bangManager.js";
|
|
|
10
10
|
import { CronManager } from "./managers/cronManager.js";
|
|
11
11
|
import { GoalManager } from "./managers/goalManager.js";
|
|
12
12
|
import { BackgroundTaskManager } from "./managers/backgroundTaskManager.js";
|
|
13
|
-
import { NotificationQueue } from "./managers/notificationQueue.js";
|
|
14
13
|
import { MessageQueue, type QueuedMessage } from "./managers/messageQueue.js";
|
|
15
14
|
import { SlashCommandManager } from "./managers/slashCommandManager.js";
|
|
16
15
|
import { PluginManager } from "./managers/pluginManager.js";
|
|
@@ -77,9 +76,8 @@ export class Agent {
|
|
|
77
76
|
private goalManager: GoalManager; // Add goal manager instance
|
|
78
77
|
private hookManager: HookManager; // Add hooks manager instance
|
|
79
78
|
private reversionManager: ReversionManager;
|
|
80
|
-
private
|
|
81
|
-
private
|
|
82
|
-
private pendingNotificationPromises: Promise<void>[] = []; // Track pending notification processing
|
|
79
|
+
private messageQueue: MessageQueue; // Unified queue for messages, bang commands, and notifications
|
|
80
|
+
private dispatchPromise: Promise<void> | null = null; // Track current dispatch for teardown
|
|
83
81
|
private memoryRuleManager: MemoryRuleManager; // Add memory rule manager instance
|
|
84
82
|
private liveConfigManager: LiveConfigManager; // Add live configuration manager
|
|
85
83
|
private taskManager: TaskManager;
|
|
@@ -207,25 +205,8 @@ export class Agent {
|
|
|
207
205
|
this.bangManager = this.container.get("BangManager")!;
|
|
208
206
|
this.cronManager = this.container.get("CronManager")!;
|
|
209
207
|
this.goalManager = this.container.get("GoalManager")!;
|
|
210
|
-
this.notificationQueue = this.container.get("NotificationQueue")!;
|
|
211
208
|
this.messageQueue = this.container.get("MessageQueue")!;
|
|
212
209
|
|
|
213
|
-
// Wire up notification queue to trigger AI when notifications arrive while idle
|
|
214
|
-
this.notificationQueue.onNotificationsEnqueued = () => {
|
|
215
|
-
// If the AI is NOT loading (idle), trigger a new AI cycle to process notifications
|
|
216
|
-
if (!this.aiManager.isLoading) {
|
|
217
|
-
const pendingPromise = this.processPendingNotifications().catch(
|
|
218
|
-
(error) => {
|
|
219
|
-
this.logger?.error(
|
|
220
|
-
"Failed to process pending notifications:",
|
|
221
|
-
error,
|
|
222
|
-
);
|
|
223
|
-
},
|
|
224
|
-
);
|
|
225
|
-
this.pendingNotificationPromises.push(pendingPromise);
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
210
|
// Wire up CWD change callback from AIManager to sync Agent's workdir
|
|
230
211
|
this.aiManager.setOnCwdChange((newCwd) => {
|
|
231
212
|
this.workdir = newCwd;
|
|
@@ -233,18 +214,20 @@ export class Agent {
|
|
|
233
214
|
this.options.callbacks?.onWorkdirChange?.(newCwd);
|
|
234
215
|
});
|
|
235
216
|
|
|
236
|
-
// Wire up message queue to process when agent becomes idle
|
|
237
|
-
|
|
217
|
+
// Wire up message queue to process when agent becomes idle.
|
|
218
|
+
// Both user messages and background task notifications enqueue here,
|
|
219
|
+
// unified through a single dispatch path (tryDispatch).
|
|
220
|
+
this.messageQueue.onMessageEnqueued = () => this.tryDispatch();
|
|
238
221
|
|
|
239
222
|
// Wire up AI loading changes to process queue when AI becomes idle
|
|
240
223
|
this.aiManager.onLoadingChange = (loading: boolean) => {
|
|
241
|
-
if (!loading) this.
|
|
224
|
+
if (!loading) this.tryDispatch();
|
|
242
225
|
};
|
|
243
226
|
|
|
244
227
|
// Wire up bang manager callback for command running changes
|
|
245
228
|
this.bangManager.onCommandRunningChange = (running: boolean) => {
|
|
246
229
|
this.options.callbacks?.onCommandRunningChange?.(running);
|
|
247
|
-
if (!running) this.
|
|
230
|
+
if (!running) this.tryDispatch();
|
|
248
231
|
};
|
|
249
232
|
|
|
250
233
|
// Set initial permission mode if provided
|
|
@@ -346,9 +329,11 @@ export class Agent {
|
|
|
346
329
|
return this.bangManager?.isCommandRunning ?? false;
|
|
347
330
|
}
|
|
348
331
|
|
|
349
|
-
/** Get queued messages */
|
|
332
|
+
/** Get queued user-facing messages (excludes background notifications) */
|
|
350
333
|
public get queuedMessages(): QueuedMessage[] {
|
|
351
|
-
return this.messageQueue
|
|
334
|
+
return this.messageQueue
|
|
335
|
+
.getQueue()
|
|
336
|
+
.filter((m) => m.type !== "notification");
|
|
352
337
|
}
|
|
353
338
|
|
|
354
339
|
/** Get goal status string */
|
|
@@ -421,28 +406,31 @@ export class Agent {
|
|
|
421
406
|
}
|
|
422
407
|
|
|
423
408
|
/**
|
|
424
|
-
* Unified
|
|
425
|
-
*
|
|
426
|
-
*
|
|
409
|
+
* Unified dispatch trigger — checks state machine before processing.
|
|
410
|
+
* Handles user messages, bang commands, and background task notifications
|
|
411
|
+
* through a single serialized path. Called from onMessageEnqueued,
|
|
412
|
+
* onLoadingChange(false), and onCommandRunningChange(false).
|
|
427
413
|
*/
|
|
428
|
-
private
|
|
414
|
+
private tryDispatch(): void {
|
|
429
415
|
if (this.messageQueue.state !== "idle") return;
|
|
430
416
|
if (!this.messageQueue.hasPending()) return;
|
|
431
417
|
if (this.aiManager.isLoading || this.isCommandRunning) return;
|
|
432
418
|
|
|
433
419
|
this.messageQueue.transitionTo("dispatching");
|
|
434
|
-
this.processQueuedMessage()
|
|
420
|
+
this.dispatchPromise = this.processQueuedMessage()
|
|
435
421
|
.catch((error) => {
|
|
436
422
|
this.logger?.error("Failed to process queued message:", error);
|
|
437
423
|
})
|
|
438
424
|
.finally(() => {
|
|
439
425
|
this.messageQueue.transitionTo("idle");
|
|
440
|
-
this.
|
|
426
|
+
this.dispatchPromise = null;
|
|
427
|
+
this.tryDispatch(); // Re-check after processing
|
|
441
428
|
});
|
|
442
429
|
}
|
|
443
430
|
|
|
444
431
|
/**
|
|
445
|
-
* Process the next queued
|
|
432
|
+
* Process the next queued item when the agent becomes idle.
|
|
433
|
+
* Handles three item types: user messages, bang commands, and notifications.
|
|
446
434
|
*/
|
|
447
435
|
private async processQueuedMessage(): Promise<void> {
|
|
448
436
|
const next = this.messageQueue.dequeue();
|
|
@@ -454,6 +442,25 @@ export class Agent {
|
|
|
454
442
|
if (next.type === "bang") {
|
|
455
443
|
await this.bangManager?.executeCommand(next.content);
|
|
456
444
|
await this.messageManager.saveSession();
|
|
445
|
+
} else if (next.type === "notification") {
|
|
446
|
+
// Drain all pending notifications and batch them into a single AI turn
|
|
447
|
+
const allNotifications = [
|
|
448
|
+
next.content,
|
|
449
|
+
...this.messageQueue.drainNotifications(),
|
|
450
|
+
];
|
|
451
|
+
for (const xml of allNotifications) {
|
|
452
|
+
const block = parseTaskNotificationXml(xml);
|
|
453
|
+
if (block) {
|
|
454
|
+
this.messageManager.addNotificationMessage({
|
|
455
|
+
taskId: block.taskId,
|
|
456
|
+
taskType: block.taskType,
|
|
457
|
+
status: block.status,
|
|
458
|
+
summary: block.summary,
|
|
459
|
+
outputFile: block.outputFile,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
await this.aiManager.sendAIMessage({ recursionDepth: 0 });
|
|
457
464
|
} else {
|
|
458
465
|
await this.sendMessage(next.content, next.images);
|
|
459
466
|
}
|
|
@@ -681,31 +688,6 @@ export class Agent {
|
|
|
681
688
|
this.aiManager.abortAIMessage();
|
|
682
689
|
}
|
|
683
690
|
|
|
684
|
-
/**
|
|
685
|
-
* Process pending background task notifications by injecting them as user messages
|
|
686
|
-
* and triggering a new AI response cycle.
|
|
687
|
-
*/
|
|
688
|
-
private async processPendingNotifications(): Promise<void> {
|
|
689
|
-
const notifications = this.notificationQueue.dequeueAll();
|
|
690
|
-
if (notifications.length === 0) return;
|
|
691
|
-
|
|
692
|
-
for (const notification of notifications) {
|
|
693
|
-
const block = parseTaskNotificationXml(notification);
|
|
694
|
-
if (block) {
|
|
695
|
-
this.messageManager.addNotificationMessage({
|
|
696
|
-
taskId: block.taskId,
|
|
697
|
-
taskType: block.taskType,
|
|
698
|
-
status: block.status,
|
|
699
|
-
summary: block.summary,
|
|
700
|
-
outputFile: block.outputFile,
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Trigger AI to process the notifications
|
|
706
|
-
await this.aiManager.sendAIMessage({ recursionDepth: 0 });
|
|
707
|
-
}
|
|
708
|
-
|
|
709
691
|
/** Execute bash command (bang command) */
|
|
710
692
|
public async bang(command: string): Promise<void> {
|
|
711
693
|
// If the agent is busy, enqueue the bang command
|
|
@@ -866,8 +848,9 @@ export class Agent {
|
|
|
866
848
|
/** Unified interrupt method, interrupts both AI messages and command execution */
|
|
867
849
|
public abortMessage(): void {
|
|
868
850
|
if (this.aiManager.isLoading || this.isCommandRunning) {
|
|
869
|
-
// Clear queue first to prevent processQueuedMessage
|
|
870
|
-
// when abortAIMessage triggers onLoadingChange(false)
|
|
851
|
+
// Clear user-facing queue items first to prevent processQueuedMessage
|
|
852
|
+
// from dequeuing when abortAIMessage triggers onLoadingChange(false).
|
|
853
|
+
// Notifications are preserved so background task results aren't lost.
|
|
871
854
|
this.messageQueue.clear();
|
|
872
855
|
this.options.callbacks?.onQueuedMessagesChange?.(this.queuedMessages);
|
|
873
856
|
}
|
|
@@ -957,15 +940,14 @@ export class Agent {
|
|
|
957
940
|
}).catch(() => {});
|
|
958
941
|
await shutdownTelemetry();
|
|
959
942
|
|
|
960
|
-
// Clear
|
|
943
|
+
// Clear message queue callback first to prevent any late triggers from
|
|
961
944
|
// starting async work during teardown
|
|
962
|
-
this.
|
|
945
|
+
this.messageQueue.onMessageEnqueued = undefined;
|
|
963
946
|
|
|
964
|
-
// Await any pending
|
|
947
|
+
// Await any pending dispatch to prevent race conditions
|
|
965
948
|
// with test teardown (e.g., V8 coverage stream cleanup)
|
|
966
|
-
if (this.
|
|
967
|
-
await
|
|
968
|
-
this.pendingNotificationPromises = [];
|
|
949
|
+
if (this.dispatchPromise) {
|
|
950
|
+
await this.dispatchPromise.catch(() => {});
|
|
969
951
|
}
|
|
970
952
|
|
|
971
953
|
// Fire SessionEnd hooks (fire-and-forget, don't block shutdown)
|
|
@@ -41,7 +41,7 @@ import { Container } from "../utils/container.js";
|
|
|
41
41
|
import type { WorktreeSession } from "../utils/worktreeSession.js";
|
|
42
42
|
import { recoverTruncatedJson } from "../utils/stringUtils.js";
|
|
43
43
|
import { ConfigurationService } from "../services/configurationService.js";
|
|
44
|
-
import type {
|
|
44
|
+
import type { MessageQueue } from "./messageQueue.js";
|
|
45
45
|
|
|
46
46
|
import { logger } from "../utils/globalLogger.js";
|
|
47
47
|
import {
|
|
@@ -115,6 +115,7 @@ export interface AIManagerOptions {
|
|
|
115
115
|
|
|
116
116
|
export class AIManager {
|
|
117
117
|
public isLoading: boolean = false;
|
|
118
|
+
private turnGeneration = 0; // Guards against concurrent sendAIMessage turns
|
|
118
119
|
private abortController: AbortController | null = null;
|
|
119
120
|
onLoadingChange?: (loading: boolean) => void;
|
|
120
121
|
private toolAbortController: AbortController | null = null;
|
|
@@ -397,6 +398,10 @@ export class AIManager {
|
|
|
397
398
|
}
|
|
398
399
|
|
|
399
400
|
public abortAIMessage(): void {
|
|
401
|
+
// Bump generation so the in-flight turn's end-of-turn setIsLoading(false)
|
|
402
|
+
// is skipped (generation mismatch), preventing it from racing with this abort.
|
|
403
|
+
this.turnGeneration++;
|
|
404
|
+
|
|
400
405
|
// Interrupt AI service
|
|
401
406
|
if (this.abortController) {
|
|
402
407
|
try {
|
|
@@ -818,6 +823,15 @@ export class AIManager {
|
|
|
818
823
|
const { recursionDepth = 0, model, allowedRules, maxTokens } = options;
|
|
819
824
|
let turnOffset = recursionDepth;
|
|
820
825
|
|
|
826
|
+
// Reserve this turn synchronously before any async work. Bumping the
|
|
827
|
+
// generation invalidates any in-flight turn's end-of-turn cleanup, and
|
|
828
|
+
// recording myGeneration lets us skip cleanup if a newer turn (or abort)
|
|
829
|
+
// has superseded us. setIsLoading(true) here also closes the "idle but
|
|
830
|
+
// previous turn not finished" race window by marking us busy immediately.
|
|
831
|
+
this.turnGeneration++;
|
|
832
|
+
const myGeneration = this.turnGeneration;
|
|
833
|
+
this.setIsLoading(true);
|
|
834
|
+
|
|
821
835
|
outer: while (true) {
|
|
822
836
|
let shouldRestart = false;
|
|
823
837
|
|
|
@@ -839,9 +853,8 @@ export class AIManager {
|
|
|
839
853
|
}).catch(() => {}); // Non-blocking
|
|
840
854
|
}
|
|
841
855
|
|
|
842
|
-
//
|
|
856
|
+
// Apply allowed rules for the initial call
|
|
843
857
|
if (turnOffset === 0) {
|
|
844
|
-
this.setIsLoading(true);
|
|
845
858
|
if (allowedRules && allowedRules.length > 0) {
|
|
846
859
|
this.permissionManager?.addTemporaryRules(allowedRules);
|
|
847
860
|
}
|
|
@@ -1375,8 +1388,6 @@ export class AIManager {
|
|
|
1375
1388
|
|
|
1376
1389
|
// Save session in each iteration to ensure message persistence
|
|
1377
1390
|
await this.messageManager.saveSession();
|
|
1378
|
-
// Set loading to false first
|
|
1379
|
-
this.setIsLoading(false);
|
|
1380
1391
|
|
|
1381
1392
|
// Clear temporary rules
|
|
1382
1393
|
this.permissionManager?.clearTemporaryRules();
|
|
@@ -1475,11 +1486,11 @@ export class AIManager {
|
|
|
1475
1486
|
|
|
1476
1487
|
// Inject pending notifications from background tasks (after Stop hooks,
|
|
1477
1488
|
// aligned with Claude Code which fires Stop hooks unconditionally)
|
|
1478
|
-
const
|
|
1479
|
-
? this.container.get<
|
|
1489
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
1490
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
1480
1491
|
: undefined;
|
|
1481
|
-
if (
|
|
1482
|
-
const notifications =
|
|
1492
|
+
if (messageQueue && messageQueue.hasNotifications()) {
|
|
1493
|
+
const notifications = messageQueue.drainNotifications();
|
|
1483
1494
|
for (const notification of notifications) {
|
|
1484
1495
|
const block = parseTaskNotificationXml(notification);
|
|
1485
1496
|
if (block) {
|
|
@@ -1498,7 +1509,16 @@ export class AIManager {
|
|
|
1498
1509
|
}
|
|
1499
1510
|
}
|
|
1500
1511
|
|
|
1501
|
-
if (!shouldRestart)
|
|
1512
|
+
if (!shouldRestart) {
|
|
1513
|
+
// Release loading state only after ALL cleanup is done (session save,
|
|
1514
|
+
// Stop hooks, notification injection). Generation check ensures a
|
|
1515
|
+
// superseded (aborted or newer) turn doesn't clobber the current
|
|
1516
|
+
// loading state.
|
|
1517
|
+
if (myGeneration === this.turnGeneration) {
|
|
1518
|
+
this.setIsLoading(false);
|
|
1519
|
+
}
|
|
1520
|
+
break outer;
|
|
1521
|
+
}
|
|
1502
1522
|
}
|
|
1503
1523
|
}
|
|
1504
1524
|
|
|
@@ -6,7 +6,7 @@ import { BackgroundTask, BackgroundShell } from "../types/processes.js";
|
|
|
6
6
|
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
7
7
|
import { logger } from "../utils/globalLogger.js";
|
|
8
8
|
import { Container } from "../utils/container.js";
|
|
9
|
-
import {
|
|
9
|
+
import { MessageQueue } from "./messageQueue.js";
|
|
10
10
|
import { resolveShellPath } from "../utils/shellResolver.js";
|
|
11
11
|
|
|
12
12
|
export interface BackgroundTaskManagerCallbacks {
|
|
@@ -32,10 +32,6 @@ export class BackgroundTaskManager {
|
|
|
32
32
|
this.workdir = options.workdir;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
private get notificationQueue(): NotificationQueue {
|
|
36
|
-
return this.container.get<NotificationQueue>("NotificationQueue")!;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
35
|
/**
|
|
40
36
|
* Fire the onBackgroundTasksChange callback so UI consumers refresh.
|
|
41
37
|
* Public so other managers (e.g. WorkflowManager) can trigger a refresh
|
|
@@ -178,13 +174,13 @@ export class BackgroundTaskManager {
|
|
|
178
174
|
|
|
179
175
|
// Skip notification if task was manually killed (user/agent-initiated stop)
|
|
180
176
|
if (!wasKilled) {
|
|
181
|
-
const
|
|
182
|
-
? this.container.get<
|
|
177
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
178
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
183
179
|
: undefined;
|
|
184
|
-
if (
|
|
180
|
+
if (messageQueue) {
|
|
185
181
|
const statusStr = shell.status;
|
|
186
182
|
const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
|
|
187
|
-
|
|
183
|
+
messageQueue.enqueueNotification(
|
|
188
184
|
`<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
|
|
189
185
|
);
|
|
190
186
|
}
|
|
@@ -208,12 +204,12 @@ export class BackgroundTaskManager {
|
|
|
208
204
|
this.notifyTasksChange();
|
|
209
205
|
|
|
210
206
|
// Enqueue error notification
|
|
211
|
-
const
|
|
212
|
-
? this.container.get<
|
|
207
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
208
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
213
209
|
: undefined;
|
|
214
|
-
if (
|
|
210
|
+
if (messageQueue) {
|
|
215
211
|
const summary = `Command "${command}" failed with error: ${stripAnsiColors(error.message)}`;
|
|
216
|
-
|
|
212
|
+
messageQueue.enqueueNotification(
|
|
217
213
|
`<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
|
|
218
214
|
);
|
|
219
215
|
}
|
|
@@ -337,13 +333,13 @@ export class BackgroundTaskManager {
|
|
|
337
333
|
|
|
338
334
|
// Skip notification if task was manually killed (user/agent-initiated stop)
|
|
339
335
|
if (!wasKilled) {
|
|
340
|
-
const
|
|
341
|
-
? this.container.get<
|
|
336
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
337
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
342
338
|
: undefined;
|
|
343
|
-
if (
|
|
339
|
+
if (messageQueue) {
|
|
344
340
|
const statusStr = shell.status;
|
|
345
341
|
const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
|
|
346
|
-
|
|
342
|
+
messageQueue.enqueueNotification(
|
|
347
343
|
`<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
|
|
348
344
|
);
|
|
349
345
|
}
|
|
@@ -364,12 +360,12 @@ export class BackgroundTaskManager {
|
|
|
364
360
|
this.notifyTasksChange();
|
|
365
361
|
|
|
366
362
|
// Enqueue error notification
|
|
367
|
-
const
|
|
368
|
-
? this.container.get<
|
|
363
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
364
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
369
365
|
: undefined;
|
|
370
|
-
if (
|
|
366
|
+
if (messageQueue) {
|
|
371
367
|
const summary = `Command "${command}" failed with error: ${stripAnsiColors(error.message)}`;
|
|
372
|
-
|
|
368
|
+
messageQueue.enqueueNotification(
|
|
373
369
|
`<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
|
|
374
370
|
);
|
|
375
371
|
}
|
|
@@ -2,7 +2,7 @@ export type QueueState = "idle" | "dispatching" | "running";
|
|
|
2
2
|
|
|
3
3
|
export interface QueuedMessage {
|
|
4
4
|
id?: string;
|
|
5
|
-
type?: "message" | "bang";
|
|
5
|
+
type?: "message" | "bang" | "notification";
|
|
6
6
|
content: string;
|
|
7
7
|
images?: Array<{ path: string; mimeType: string }>;
|
|
8
8
|
longTextMap?: Record<string, string>;
|
|
@@ -44,8 +44,12 @@ export class MessageQueue {
|
|
|
44
44
|
return this.queue.shift() ?? null;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Clear user-facing items (messages, bang commands) but preserve pending
|
|
49
|
+
* notifications so background task results are not lost on abort.
|
|
50
|
+
*/
|
|
47
51
|
clear(): void {
|
|
48
|
-
this.queue =
|
|
52
|
+
this.queue = this.queue.filter((m) => m.type === "notification");
|
|
49
53
|
this._state = "idle";
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -113,4 +117,41 @@ export class MessageQueue {
|
|
|
113
117
|
this.queue = remaining;
|
|
114
118
|
return editable;
|
|
115
119
|
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Enqueue a background task notification (XML string). Notifications are
|
|
123
|
+
* not user-editable and not surfaced in the queued-messages UI.
|
|
124
|
+
*/
|
|
125
|
+
enqueueNotification(xml: string): void {
|
|
126
|
+
this.queue.push({
|
|
127
|
+
id: `mq-${this.nextId++}`,
|
|
128
|
+
type: "notification",
|
|
129
|
+
content: xml,
|
|
130
|
+
editable: false,
|
|
131
|
+
});
|
|
132
|
+
this.onMessageEnqueued?.();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Whether any notification items are pending. */
|
|
136
|
+
hasNotifications(): boolean {
|
|
137
|
+
return this.queue.some((m) => m.type === "notification");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Drain all notification items, returning their XML content. Non-notification
|
|
142
|
+
* items (messages, bang commands) are preserved in the queue.
|
|
143
|
+
*/
|
|
144
|
+
drainNotifications(): string[] {
|
|
145
|
+
const notifications: string[] = [];
|
|
146
|
+
const remaining: QueuedMessage[] = [];
|
|
147
|
+
for (const msg of this.queue) {
|
|
148
|
+
if (msg.type === "notification") {
|
|
149
|
+
notifications.push(msg.content);
|
|
150
|
+
} else {
|
|
151
|
+
remaining.push(msg);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
this.queue = remaining;
|
|
155
|
+
return notifications;
|
|
156
|
+
}
|
|
116
157
|
}
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
createAbortPromise,
|
|
20
20
|
} from "../utils/abortUtils.js";
|
|
21
21
|
import { BackgroundTaskManager } from "./backgroundTaskManager.js";
|
|
22
|
-
import {
|
|
22
|
+
import { MessageQueue } from "./messageQueue.js";
|
|
23
23
|
import { logger } from "../utils/globalLogger.js";
|
|
24
24
|
import {
|
|
25
25
|
UserMessageParams,
|
|
@@ -81,7 +81,6 @@ export interface SubagentInstance {
|
|
|
81
81
|
toolManager: ToolManager;
|
|
82
82
|
permissionManager: PermissionManager;
|
|
83
83
|
backgroundTaskManager: BackgroundTaskManager;
|
|
84
|
-
notificationQueue: NotificationQueue;
|
|
85
84
|
status: "initializing" | "active" | "completed" | "error" | "aborted";
|
|
86
85
|
messages: Message[];
|
|
87
86
|
usedTools: {
|
|
@@ -393,10 +392,6 @@ export class SubagentManager {
|
|
|
393
392
|
});
|
|
394
393
|
subagentContainer.register("AIManager", aiManager);
|
|
395
394
|
|
|
396
|
-
// Create isolated NotificationQueue for the subagent/forked agent
|
|
397
|
-
const subagentNotificationQueue = new NotificationQueue();
|
|
398
|
-
subagentContainer.register("NotificationQueue", subagentNotificationQueue);
|
|
399
|
-
|
|
400
395
|
// Create isolated BackgroundTaskManager for the subagent/forked agent
|
|
401
396
|
const subagentBackgroundTaskManager = new BackgroundTaskManager(
|
|
402
397
|
subagentContainer,
|
|
@@ -417,7 +412,6 @@ export class SubagentManager {
|
|
|
417
412
|
toolManager,
|
|
418
413
|
permissionManager: subagentPermissionManager,
|
|
419
414
|
backgroundTaskManager: subagentBackgroundTaskManager,
|
|
420
|
-
notificationQueue: subagentNotificationQueue,
|
|
421
415
|
status: "initializing",
|
|
422
416
|
messages: [],
|
|
423
417
|
usedTools: [], // Initialize usedTools
|
|
@@ -657,12 +651,12 @@ export class SubagentManager {
|
|
|
657
651
|
}
|
|
658
652
|
// Skip notification if task was already stopped (e.g. by main agent shutdown)
|
|
659
653
|
if (!wasAlreadyKilled) {
|
|
660
|
-
const
|
|
661
|
-
? this.container.get<
|
|
654
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
655
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
662
656
|
: undefined;
|
|
663
|
-
if (
|
|
657
|
+
if (messageQueue) {
|
|
664
658
|
const summary = `Agent task "${instance.description}" completed`;
|
|
665
|
-
|
|
659
|
+
messageQueue.enqueueNotification(
|
|
666
660
|
`<task-notification>\n<task-id>${instance.backgroundTaskId}</task-id>\n<task-type>agent</task-type>\n<status>completed</status>\n<summary>${summary}</summary>\n</task-notification>`,
|
|
667
661
|
);
|
|
668
662
|
}
|
|
@@ -694,14 +688,14 @@ export class SubagentManager {
|
|
|
694
688
|
}
|
|
695
689
|
// Skip notification if task was already stopped (e.g. by main agent shutdown)
|
|
696
690
|
if (!wasAlreadyKilled) {
|
|
697
|
-
const
|
|
698
|
-
? this.container.get<
|
|
691
|
+
const messageQueue = this.container.has("MessageQueue")
|
|
692
|
+
? this.container.get<MessageQueue>("MessageQueue")
|
|
699
693
|
: undefined;
|
|
700
|
-
if (
|
|
694
|
+
if (messageQueue) {
|
|
701
695
|
const errorMsg =
|
|
702
696
|
error instanceof Error ? error.message : String(error);
|
|
703
697
|
const summary = `Agent task "${instance.description}" failed: ${errorMsg}`;
|
|
704
|
-
|
|
698
|
+
messageQueue.enqueueNotification(
|
|
705
699
|
`<task-notification>\n<task-id>${instance.backgroundTaskId}</task-id>\n<task-type>agent</task-type>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
|
|
706
700
|
);
|
|
707
701
|
}
|
|
@@ -4,7 +4,7 @@ import * as fs from "fs";
|
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import { Container } from "../utils/container.js";
|
|
6
6
|
import { BackgroundTaskManager } from "./backgroundTaskManager.js";
|
|
7
|
-
import {
|
|
7
|
+
import { MessageQueue } from "./messageQueue.js";
|
|
8
8
|
import { SubagentManager } from "./subagentManager.js";
|
|
9
9
|
import { taskNotificationToXml } from "../utils/notificationXml.js";
|
|
10
10
|
import { ConcurrencyLimiter } from "../workflow/concurrencyLimiter.js";
|
|
@@ -49,8 +49,8 @@ export class WorkflowManager {
|
|
|
49
49
|
return this.container.get<BackgroundTaskManager>("BackgroundTaskManager")!;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
private get
|
|
53
|
-
return this.container.get<
|
|
52
|
+
private get messageQueue(): MessageQueue {
|
|
53
|
+
return this.container.get<MessageQueue>("MessageQueue")!;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
private get subagentManager(): SubagentManager {
|
|
@@ -295,7 +295,7 @@ export class WorkflowManager {
|
|
|
295
295
|
|
|
296
296
|
// Enqueue completion notification
|
|
297
297
|
const journalPath = journal.filePath;
|
|
298
|
-
this.
|
|
298
|
+
this.messageQueue.enqueueNotification(
|
|
299
299
|
taskNotificationToXml({
|
|
300
300
|
type: "task_notification",
|
|
301
301
|
taskId: runId,
|
|
@@ -337,7 +337,7 @@ export class WorkflowManager {
|
|
|
337
337
|
task.endTime = Date.now();
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
-
this.
|
|
340
|
+
this.messageQueue.enqueueNotification(
|
|
341
341
|
taskNotificationToXml({
|
|
342
342
|
type: "task_notification",
|
|
343
343
|
taskId: runId,
|
|
@@ -71,6 +71,13 @@ export class InteractionService {
|
|
|
71
71
|
})),
|
|
72
72
|
});
|
|
73
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
|
+
|
|
74
81
|
// Execute UserPromptSubmit hooks after adding the user message
|
|
75
82
|
if (hookManager) {
|
|
76
83
|
try {
|
|
@@ -104,6 +111,8 @@ export class InteractionService {
|
|
|
104
111
|
"UserPromptSubmit hook blocked prompt processing with error:",
|
|
105
112
|
processResult.errorMessage,
|
|
106
113
|
);
|
|
114
|
+
// Release the loading state we reserved above
|
|
115
|
+
aiManager.setIsLoading(false);
|
|
107
116
|
return; // Don't send to AI
|
|
108
117
|
}
|
|
109
118
|
} catch (error) {
|
|
@@ -116,6 +125,8 @@ export class InteractionService {
|
|
|
116
125
|
await aiManager.sendAIMessage();
|
|
117
126
|
} catch (error) {
|
|
118
127
|
console.error("Failed to add user message:", error);
|
|
128
|
+
// Ensure loading state is released on error
|
|
129
|
+
aiManager.setIsLoading(false);
|
|
119
130
|
// Loading state will be automatically updated by the useEffect that watches messages
|
|
120
131
|
}
|
|
121
132
|
}
|
|
@@ -7,6 +7,13 @@ import { logger } from "../utils/globalLogger.js";
|
|
|
7
7
|
import { Container } from "../utils/container.js";
|
|
8
8
|
import type { MessageManager } from "../managers/messageManager.js";
|
|
9
9
|
|
|
10
|
+
function byIdAsc(a: Task, b: Task) {
|
|
11
|
+
const aNum = parseInt(a.id, 10);
|
|
12
|
+
const bNum = parseInt(b.id, 10);
|
|
13
|
+
if (!isNaN(aNum) && !isNaN(bNum)) return aNum - bNum;
|
|
14
|
+
return a.id.localeCompare(b.id);
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
export class TaskManager extends EventEmitter {
|
|
11
18
|
private readonly baseDir: string;
|
|
12
19
|
private taskListId: string;
|
|
@@ -234,7 +241,7 @@ export class TaskManager extends EventEmitter {
|
|
|
234
241
|
}),
|
|
235
242
|
);
|
|
236
243
|
|
|
237
|
-
return tasks.filter((t): t is Task => t !== null);
|
|
244
|
+
return tasks.filter((t): t is Task => t !== null).sort(byIdAsc);
|
|
238
245
|
} catch (error) {
|
|
239
246
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
240
247
|
return [];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Container } from "./container.js";
|
|
2
2
|
import { ForegroundTaskManager } from "../managers/foregroundTaskManager.js";
|
|
3
3
|
import { BackgroundTaskManager } from "../managers/backgroundTaskManager.js";
|
|
4
|
-
import { NotificationQueue } from "../managers/notificationQueue.js";
|
|
5
4
|
import { MessageQueue } from "../managers/messageQueue.js";
|
|
6
5
|
import { TaskManager } from "../services/taskManager.js";
|
|
7
6
|
import { MessageManager } from "../managers/messageManager.js";
|
|
@@ -92,9 +91,6 @@ export function setupAgentContainer(
|
|
|
92
91
|
// container so it is isolated per session, not shared process-wide.
|
|
93
92
|
container.register("WorktreeSession", null);
|
|
94
93
|
|
|
95
|
-
const notificationQueue = new NotificationQueue();
|
|
96
|
-
container.register("NotificationQueue", notificationQueue);
|
|
97
|
-
|
|
98
94
|
const messageQueue = new MessageQueue();
|
|
99
95
|
container.register("MessageQueue", messageQueue);
|
|
100
96
|
|
package/dist/agent.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|