wave-agent-sdk 0.14.1 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builtin/skills/settings/HOOKS.md +69 -0
- package/builtin/skills/settings/PLUGINS.md +171 -0
- package/builtin/skills/settings/SKILL.md +8 -3
- package/builtin/skills/settings/SUBAGENTS.md +21 -2
- package/dist/agent.d.ts +2 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +12 -3
- package/dist/managers/aiManager.d.ts +6 -6
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +122 -59
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
- package/dist/managers/backgroundTaskManager.js +28 -18
- package/dist/managers/hookManager.d.ts +16 -1
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +97 -8
- package/dist/managers/messageManager.d.ts +19 -4
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +63 -18
- package/dist/managers/pluginManager.d.ts +1 -0
- package/dist/managers/pluginManager.d.ts.map +1 -1
- package/dist/managers/pluginManager.js +7 -0
- package/dist/managers/subagentManager.d.ts +5 -0
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +35 -0
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +1 -1
- package/dist/services/MarketplaceService.d.ts +0 -11
- package/dist/services/MarketplaceService.d.ts.map +1 -1
- package/dist/services/MarketplaceService.js +21 -89
- package/dist/services/aiService.d.ts +3 -3
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +7 -7
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +15 -0
- package/dist/services/initializationService.d.ts.map +1 -1
- package/dist/services/initializationService.js +24 -1
- package/dist/services/interactionService.js +1 -1
- package/dist/services/pluginLoader.d.ts +5 -6
- package/dist/services/pluginLoader.d.ts.map +1 -1
- package/dist/services/pluginLoader.js +43 -53
- package/dist/services/session.d.ts +1 -1
- package/dist/services/session.js +7 -7
- package/dist/services/taskManager.d.ts +1 -1
- package/dist/services/taskManager.js +1 -1
- package/dist/types/core.d.ts +1 -1
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +9 -1
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +2 -0
- package/dist/types/marketplace.d.ts +1 -26
- package/dist/types/marketplace.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +3 -3
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/plugins.d.ts +3 -13
- package/dist/types/plugins.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.d.ts +1 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +18 -7
- package/dist/utils/groupMessagesByApiRound.d.ts +1 -1
- package/dist/utils/groupMessagesByApiRound.js +6 -6
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +3 -3
- package/dist/utils/subagentParser.d.ts +8 -1
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +18 -3
- package/package.json +1 -1
- package/src/agent.ts +16 -3
- package/src/managers/aiManager.ts +142 -63
- package/src/managers/backgroundTaskManager.ts +32 -22
- package/src/managers/hookManager.ts +125 -10
- package/src/managers/messageManager.ts +76 -22
- package/src/managers/pluginManager.ts +10 -0
- package/src/managers/subagentManager.ts +47 -0
- package/src/prompts/index.ts +1 -1
- package/src/services/MarketplaceService.ts +26 -127
- package/src/services/aiService.ts +11 -11
- package/src/services/hook.ts +17 -0
- package/src/services/initializationService.ts +33 -1
- package/src/services/interactionService.ts +1 -1
- package/src/services/pluginLoader.ts +51 -67
- package/src/services/session.ts +7 -7
- package/src/services/taskManager.ts +1 -1
- package/src/types/core.ts +1 -1
- package/src/types/hooks.ts +16 -2
- package/src/types/marketplace.ts +1 -24
- package/src/types/messaging.ts +3 -3
- package/src/types/plugins.ts +3 -13
- package/src/utils/convertMessagesForAPI.ts +24 -9
- package/src/utils/groupMessagesByApiRound.ts +6 -6
- package/src/utils/messageOperations.ts +3 -5
- package/src/utils/subagentParser.ts +31 -4
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Boundaries:
|
|
8
8
|
* - A new `role: "user"` message starts a new round.
|
|
9
9
|
* - A new `role: "assistant"` message with a different `id` starts a new round.
|
|
10
|
-
* - A message with a `
|
|
10
|
+
* - A message with a `compact` block is pushed as its own round and starts a
|
|
11
11
|
* new round after it.
|
|
12
12
|
*/
|
|
13
13
|
export function groupMessagesByApiRound(messages) {
|
|
@@ -20,9 +20,9 @@ export function groupMessagesByApiRound(messages) {
|
|
|
20
20
|
startNewRound = true;
|
|
21
21
|
}
|
|
22
22
|
else if (msg.role === "assistant") {
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
23
|
+
// Compact block is always its own round
|
|
24
|
+
const hasCompact = msg.blocks.some((b) => b.type === "compact");
|
|
25
|
+
if (hasCompact) {
|
|
26
26
|
startNewRound = true;
|
|
27
27
|
}
|
|
28
28
|
else if (msg.id !== lastAssistantId) {
|
|
@@ -46,9 +46,9 @@ export function groupMessagesByApiRound(messages) {
|
|
|
46
46
|
currentRound = [];
|
|
47
47
|
}
|
|
48
48
|
currentRound.push(msg);
|
|
49
|
-
// After pushing a
|
|
49
|
+
// After pushing a compact message as its own round, flush immediately
|
|
50
50
|
if (msg.role === "assistant" &&
|
|
51
|
-
msg.blocks.some((b) => b.type === "
|
|
51
|
+
msg.blocks.some((b) => b.type === "compact")) {
|
|
52
52
|
rounds.push({
|
|
53
53
|
messages: currentRound,
|
|
54
54
|
estimatedTokens: estimateTokens(currentRound),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -423,9 +423,9 @@ export function getMessageContent(message) {
|
|
|
423
423
|
if (bangBlock && "command" in bangBlock) {
|
|
424
424
|
return `!${bangBlock.command}`;
|
|
425
425
|
}
|
|
426
|
-
const
|
|
427
|
-
if (
|
|
428
|
-
return
|
|
426
|
+
const compactBlock = message.blocks.find((block) => block.type === "compact");
|
|
427
|
+
if (compactBlock && "content" in compactBlock) {
|
|
428
|
+
return compactBlock.content;
|
|
429
429
|
}
|
|
430
430
|
return "";
|
|
431
431
|
}
|
|
@@ -5,9 +5,16 @@ export interface SubagentConfiguration {
|
|
|
5
5
|
model?: string;
|
|
6
6
|
systemPrompt: string;
|
|
7
7
|
filePath: string;
|
|
8
|
-
scope: "project" | "user" | "builtin";
|
|
8
|
+
scope: "project" | "user" | "builtin" | "plugin";
|
|
9
9
|
priority: number;
|
|
10
|
+
/** Plugin root directory path, set when scope is "plugin" */
|
|
11
|
+
pluginRoot?: string;
|
|
10
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse a plugin agent markdown file.
|
|
15
|
+
* Exposed as a public API for PluginLoader to use.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseAgentFile(filePath: string, scope: "plugin", pluginRoot: string): SubagentConfiguration;
|
|
11
18
|
/**
|
|
12
19
|
* Load all subagent configurations from project and user directories, plus built-in subagents
|
|
13
20
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagentParser.d.ts","sourceRoot":"","sources":["../../src/utils/subagentParser.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"subagentParser.d.ts","sourceRoot":"","sources":["../../src/utils/subagentParser.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkKD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,QAAQ,EACf,UAAU,EAAE,MAAM,GACjB,qBAAqB,CAEvB;AAqCD;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAsBlC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAGvC"}
|
|
@@ -80,9 +80,9 @@ function validateConfiguration(config, filePath) {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
|
-
* Parse a single subagent markdown file
|
|
83
|
+
* Parse a single subagent markdown file with optional pluginRoot support
|
|
84
84
|
*/
|
|
85
|
-
function parseSubagentFile(filePath, scope) {
|
|
85
|
+
function parseSubagentFile(filePath, scope, pluginRoot) {
|
|
86
86
|
try {
|
|
87
87
|
const content = readFileSync(filePath, "utf-8");
|
|
88
88
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
@@ -99,21 +99,36 @@ function parseSubagentFile(filePath, scope) {
|
|
|
99
99
|
priority = 2;
|
|
100
100
|
if (scope === "builtin")
|
|
101
101
|
priority = 3;
|
|
102
|
+
if (scope === "plugin")
|
|
103
|
+
priority = 2; // Same priority as user-level
|
|
104
|
+
let systemPrompt = body;
|
|
105
|
+
// Substitute ${WAVE_PLUGIN_ROOT} for plugin scope at parse time
|
|
106
|
+
if (scope === "plugin" && pluginRoot) {
|
|
107
|
+
systemPrompt = systemPrompt.replace(/\$\{WAVE_PLUGIN_ROOT\}/g, pluginRoot);
|
|
108
|
+
}
|
|
102
109
|
return {
|
|
103
110
|
name: frontmatter.name,
|
|
104
111
|
description: frontmatter.description,
|
|
105
112
|
tools: frontmatter.tools,
|
|
106
113
|
model: frontmatter.model,
|
|
107
|
-
systemPrompt
|
|
114
|
+
systemPrompt,
|
|
108
115
|
filePath,
|
|
109
116
|
scope,
|
|
110
117
|
priority,
|
|
118
|
+
pluginRoot: scope === "plugin" ? pluginRoot : undefined,
|
|
111
119
|
};
|
|
112
120
|
}
|
|
113
121
|
catch (error) {
|
|
114
122
|
throw new Error(`Failed to parse subagent file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
115
123
|
}
|
|
116
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Parse a plugin agent markdown file.
|
|
127
|
+
* Exposed as a public API for PluginLoader to use.
|
|
128
|
+
*/
|
|
129
|
+
export function parseAgentFile(filePath, scope, pluginRoot) {
|
|
130
|
+
return parseSubagentFile(filePath, scope, pluginRoot);
|
|
131
|
+
}
|
|
117
132
|
/**
|
|
118
133
|
* Scan directory for subagent files
|
|
119
134
|
*/
|
package/package.json
CHANGED
package/src/agent.ts
CHANGED
|
@@ -317,9 +317,9 @@ export class Agent {
|
|
|
317
317
|
return this.aiManager.isLoading;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
/** Get message
|
|
321
|
-
public get
|
|
322
|
-
return this.aiManager.
|
|
320
|
+
/** Get message compaction status */
|
|
321
|
+
public get isCompacting(): boolean {
|
|
322
|
+
return this.aiManager.getIsCompacting();
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
/** Get bash command execution status */
|
|
@@ -633,6 +633,19 @@ export class Agent {
|
|
|
633
633
|
this.pendingNotificationPromises = [];
|
|
634
634
|
}
|
|
635
635
|
|
|
636
|
+
// Fire SessionEnd hooks (fire-and-forget, don't block shutdown)
|
|
637
|
+
try {
|
|
638
|
+
const sessionId = this.messageManager.getSessionId();
|
|
639
|
+
const transcriptPath = this.messageManager.getTranscriptPath();
|
|
640
|
+
await this.hookManager.executeSessionEndHooks(
|
|
641
|
+
"stop",
|
|
642
|
+
sessionId,
|
|
643
|
+
transcriptPath,
|
|
644
|
+
);
|
|
645
|
+
} catch (error) {
|
|
646
|
+
this.logger?.warn(`SessionEnd hooks failed: ${(error as Error).message}`);
|
|
647
|
+
}
|
|
648
|
+
|
|
636
649
|
await this.messageManager.saveSession();
|
|
637
650
|
this.abortAIMessage(); // This will abort tools including Agent tool (subagents)
|
|
638
651
|
this.abortBashCommand();
|
|
@@ -30,7 +30,7 @@ import type { NotificationQueue } from "./notificationQueue.js";
|
|
|
30
30
|
import { logger } from "../utils/globalLogger.js";
|
|
31
31
|
|
|
32
32
|
export interface AIManagerCallbacks {
|
|
33
|
-
|
|
33
|
+
onCompactionStateChange?: (isCompacting: boolean) => void;
|
|
34
34
|
onUsageAdded?: (usage: Usage) => void;
|
|
35
35
|
onCwdChange?: (newCwd: string) => void;
|
|
36
36
|
}
|
|
@@ -58,7 +58,7 @@ export class AIManager {
|
|
|
58
58
|
private stream: boolean; // Streaming mode flag
|
|
59
59
|
private modelOverride?: string;
|
|
60
60
|
private _onCwdChange?: (newCwd: string) => void; // Store callback for CWD changes
|
|
61
|
-
private
|
|
61
|
+
private consecutiveCompactionFailures: number = 0;
|
|
62
62
|
|
|
63
63
|
// Service overrides
|
|
64
64
|
constructor(
|
|
@@ -177,7 +177,7 @@ export class AIManager {
|
|
|
177
177
|
this._onCwdChange = callback;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
private
|
|
180
|
+
private isCompacting: boolean = false;
|
|
181
181
|
private callbacks: AIManagerCallbacks;
|
|
182
182
|
|
|
183
183
|
/**
|
|
@@ -253,8 +253,8 @@ export class AIManager {
|
|
|
253
253
|
return "";
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
// Private method to handle token statistics and message
|
|
257
|
-
private async
|
|
256
|
+
// Private method to handle token statistics and message compaction
|
|
257
|
+
private async handleTokenUsageAndCompaction(
|
|
258
258
|
usage: Usage | undefined,
|
|
259
259
|
abortController: AbortController,
|
|
260
260
|
): Promise<void> {
|
|
@@ -272,30 +272,30 @@ export class AIManager {
|
|
|
272
272
|
this.getMaxInputTokens()
|
|
273
273
|
) {
|
|
274
274
|
logger?.debug(
|
|
275
|
-
`Token usage exceeded ${this.getMaxInputTokens()},
|
|
275
|
+
`Token usage exceeded ${this.getMaxInputTokens()}, compacting messages...`,
|
|
276
276
|
);
|
|
277
277
|
|
|
278
|
-
// Check if messages need
|
|
279
|
-
const
|
|
278
|
+
// Check if messages need compaction
|
|
279
|
+
const messagesToCompact = this.messageManager.getMessages();
|
|
280
280
|
|
|
281
|
-
// If there are messages to
|
|
282
|
-
if (
|
|
283
|
-
// Circuit breaker: skip
|
|
284
|
-
if (this.
|
|
281
|
+
// If there are messages to compact, perform compaction
|
|
282
|
+
if (messagesToCompact.length > 0) {
|
|
283
|
+
// Circuit breaker: skip compaction after 3 consecutive failures
|
|
284
|
+
if (this.consecutiveCompactionFailures >= 3) {
|
|
285
285
|
logger?.warn(
|
|
286
|
-
`Skipping
|
|
286
|
+
`Skipping compaction: ${this.consecutiveCompactionFailures} consecutive failures`,
|
|
287
287
|
);
|
|
288
288
|
return;
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
const recentChatMessages = convertMessagesForAPI(
|
|
291
|
+
const recentChatMessages = convertMessagesForAPI(messagesToCompact);
|
|
292
292
|
|
|
293
|
-
// Save session before
|
|
293
|
+
// Save session before compaction to preserve original messages
|
|
294
294
|
await this.messageManager.saveSession();
|
|
295
295
|
|
|
296
|
-
this.
|
|
296
|
+
this.setIsCompacting(true);
|
|
297
297
|
try {
|
|
298
|
-
const
|
|
298
|
+
const compactResult = await aiService.compactMessages({
|
|
299
299
|
gatewayConfig: this.getGatewayConfig(),
|
|
300
300
|
modelConfig: this.getModelConfig(),
|
|
301
301
|
messages: recentChatMessages,
|
|
@@ -303,15 +303,15 @@ export class AIManager {
|
|
|
303
303
|
model: this.getModelConfig().fastModel,
|
|
304
304
|
});
|
|
305
305
|
|
|
306
|
-
// Handle usage tracking for
|
|
307
|
-
let
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
prompt_tokens:
|
|
311
|
-
completion_tokens:
|
|
312
|
-
total_tokens:
|
|
306
|
+
// Handle usage tracking for compaction operations
|
|
307
|
+
let compactUsage: Usage | undefined;
|
|
308
|
+
if (compactResult.usage) {
|
|
309
|
+
compactUsage = {
|
|
310
|
+
prompt_tokens: compactResult.usage.prompt_tokens,
|
|
311
|
+
completion_tokens: compactResult.usage.completion_tokens,
|
|
312
|
+
total_tokens: compactResult.usage.total_tokens,
|
|
313
313
|
model: this.getModelConfig().fastModel,
|
|
314
|
-
operation_type: "
|
|
314
|
+
operation_type: "compact",
|
|
315
315
|
};
|
|
316
316
|
}
|
|
317
317
|
|
|
@@ -364,73 +364,152 @@ export class AIManager {
|
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
// 4.
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
if (
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
367
|
+
// 4. Invoked skills context (with token budget, matching Claude Code)
|
|
368
|
+
const POST_COMPACT_SKILLS_TOKEN_BUDGET = 25_000;
|
|
369
|
+
const POST_COMPACT_MAX_TOKENS_PER_SKILL = 5_000;
|
|
370
|
+
const invokedSkillNames =
|
|
371
|
+
this.messageManager.getInvokedSkillNames(10);
|
|
372
|
+
if (invokedSkillNames.length > 0 && this.skillManager) {
|
|
373
|
+
const invokedSkillParts: string[] = [];
|
|
374
|
+
let skillsUsedTokens = 0;
|
|
375
|
+
for (const skillName of invokedSkillNames) {
|
|
376
|
+
try {
|
|
377
|
+
const skill = await this.skillManager.loadSkill(skillName);
|
|
378
|
+
if (!skill) continue;
|
|
379
|
+
|
|
380
|
+
// Extract content after frontmatter (matching prepareSkillContent pattern)
|
|
381
|
+
const contentMatch = skill.content.match(
|
|
382
|
+
/^---\n[\s\S]*?\n---\n([\s\S]*)$/,
|
|
383
|
+
);
|
|
384
|
+
let skillContent = contentMatch
|
|
385
|
+
? contentMatch[1].trim()
|
|
386
|
+
: skill.content;
|
|
387
|
+
|
|
388
|
+
// Per-skill token budget enforcement (~4 chars per token)
|
|
389
|
+
const maxSkillChars = POST_COMPACT_MAX_TOKENS_PER_SKILL * 4;
|
|
390
|
+
if (skillContent.length > maxSkillChars) {
|
|
391
|
+
skillContent =
|
|
392
|
+
skillContent.slice(0, maxSkillChars) +
|
|
393
|
+
"\n\n...[truncated]...";
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const skillTokens = Math.ceil(skillContent.length / 4);
|
|
397
|
+
if (
|
|
398
|
+
skillsUsedTokens + skillTokens >
|
|
399
|
+
POST_COMPACT_SKILLS_TOKEN_BUDGET
|
|
400
|
+
)
|
|
401
|
+
break;
|
|
402
|
+
skillsUsedTokens += skillTokens;
|
|
403
|
+
|
|
404
|
+
invokedSkillParts.push(
|
|
405
|
+
`\n\n## ${skill.name}\n${skill.description ? `*${skill.description}*\n\n` : ""}\`\`\`\n${skillContent}\n\`\`\``,
|
|
406
|
+
);
|
|
407
|
+
} catch {
|
|
408
|
+
// Skip skills that can't be loaded
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (invokedSkillParts.length > 0) {
|
|
412
|
+
contextParts.push(
|
|
413
|
+
`\n\n[Invoked Skills]\n${invokedSkillParts.join("")}`,
|
|
414
|
+
);
|
|
415
|
+
}
|
|
377
416
|
}
|
|
378
417
|
|
|
379
|
-
// 5. Background
|
|
380
|
-
const agents =
|
|
418
|
+
// 5. Background subagent status (shell tasks excluded, matching Claude Code's createAsyncAgentAttachmentsIfNeeded)
|
|
419
|
+
const agents =
|
|
420
|
+
this.backgroundTaskManager
|
|
421
|
+
?.getAllTasks()
|
|
422
|
+
.filter((a) => a.type === "subagent") || [];
|
|
381
423
|
if (agents.length > 0) {
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
.
|
|
385
|
-
|
|
424
|
+
const agentParts: string[] = [];
|
|
425
|
+
for (const a of agents) {
|
|
426
|
+
if (a.status === "killed") {
|
|
427
|
+
agentParts.push(
|
|
428
|
+
`Task "${a.description}" (${a.id}) was stopped by the user.`,
|
|
429
|
+
);
|
|
430
|
+
} else if (a.status === "running") {
|
|
431
|
+
const parts = [
|
|
432
|
+
`Background agent "${a.description}" (${a.id}) is still running.`,
|
|
433
|
+
`Do NOT spawn a duplicate. You will be notified when it completes.`,
|
|
434
|
+
];
|
|
435
|
+
if (a.outputPath) {
|
|
436
|
+
parts.push(`You can read partial output at ${a.outputPath}.`);
|
|
437
|
+
}
|
|
438
|
+
agentParts.push(parts.join(" "));
|
|
439
|
+
} else {
|
|
440
|
+
// completed or failed
|
|
441
|
+
const parts = [
|
|
442
|
+
`Task ${a.id} (status: ${a.status}) (description: ${a.description}).`,
|
|
443
|
+
];
|
|
444
|
+
const deltaText = a.status === "failed" ? a.stderr : a.stdout;
|
|
445
|
+
if (deltaText && deltaText.length > 0) {
|
|
446
|
+
const summary =
|
|
447
|
+
deltaText.length > 500
|
|
448
|
+
? deltaText.slice(0, 500) + "..."
|
|
449
|
+
: deltaText;
|
|
450
|
+
parts.push(`Delta: ${summary}`);
|
|
451
|
+
}
|
|
452
|
+
if (a.outputPath) {
|
|
453
|
+
parts.push(
|
|
454
|
+
`Read the output file to retrieve the result: ${a.outputPath}.`,
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
agentParts.push(parts.join(" "));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (agentParts.length > 0) {
|
|
461
|
+
contextParts.push(
|
|
462
|
+
`\n\n[Background Tasks]\n${agentParts.join("\n")}`,
|
|
463
|
+
);
|
|
464
|
+
}
|
|
386
465
|
}
|
|
387
466
|
|
|
388
467
|
// Merge context restoration into summary
|
|
389
468
|
const enhancedSummary =
|
|
390
|
-
|
|
469
|
+
compactResult.content +
|
|
391
470
|
(contextParts.length > 0
|
|
392
471
|
? `\n\n[Context Restoration]` + contextParts.join("")
|
|
393
472
|
: "");
|
|
394
473
|
|
|
395
|
-
// Execute message reconstruction and sessionId update after
|
|
396
|
-
this.messageManager.
|
|
474
|
+
// Execute message reconstruction and sessionId update after compaction
|
|
475
|
+
this.messageManager.compactMessagesAndUpdateSession(
|
|
397
476
|
enhancedSummary,
|
|
398
|
-
|
|
477
|
+
compactUsage,
|
|
399
478
|
);
|
|
400
479
|
|
|
401
480
|
// Notify Agent to add to usage tracking
|
|
402
|
-
if (
|
|
403
|
-
this.callbacks.onUsageAdded(
|
|
481
|
+
if (compactUsage && this.callbacks?.onUsageAdded) {
|
|
482
|
+
this.callbacks.onUsageAdded(compactUsage);
|
|
404
483
|
}
|
|
405
484
|
|
|
406
485
|
logger?.debug(
|
|
407
|
-
`Successfully
|
|
486
|
+
`Successfully compacted ${messagesToCompact.length} messages and updated session`,
|
|
408
487
|
);
|
|
409
|
-
this.
|
|
410
|
-
} catch (
|
|
411
|
-
this.
|
|
488
|
+
this.consecutiveCompactionFailures = 0;
|
|
489
|
+
} catch (compactError) {
|
|
490
|
+
this.consecutiveCompactionFailures++;
|
|
412
491
|
logger?.error(
|
|
413
|
-
`Failed to
|
|
414
|
-
|
|
492
|
+
`Failed to compact messages (${this.consecutiveCompactionFailures} consecutive):`,
|
|
493
|
+
compactError,
|
|
415
494
|
);
|
|
416
495
|
this.messageManager.addErrorBlock(
|
|
417
|
-
`Failed to
|
|
496
|
+
`Failed to compact conversation history: ${compactError instanceof Error ? compactError.message : String(compactError)}. You may encounter context limit issues.`,
|
|
418
497
|
);
|
|
419
498
|
} finally {
|
|
420
|
-
this.
|
|
499
|
+
this.setIsCompacting(false);
|
|
421
500
|
}
|
|
422
501
|
}
|
|
423
502
|
}
|
|
424
503
|
}
|
|
425
504
|
|
|
426
|
-
public
|
|
427
|
-
return this.
|
|
505
|
+
public getIsCompacting(): boolean {
|
|
506
|
+
return this.isCompacting;
|
|
428
507
|
}
|
|
429
508
|
|
|
430
|
-
public
|
|
431
|
-
if (this.
|
|
432
|
-
this.
|
|
433
|
-
this.callbacks.
|
|
509
|
+
public setIsCompacting(isCompacting: boolean): void {
|
|
510
|
+
if (this.isCompacting !== isCompacting) {
|
|
511
|
+
this.isCompacting = isCompacting;
|
|
512
|
+
this.callbacks.onCompactionStateChange?.(isCompacting);
|
|
434
513
|
}
|
|
435
514
|
}
|
|
436
515
|
|
|
@@ -914,8 +993,8 @@ export class AIManager {
|
|
|
914
993
|
await Promise.all(toolExecutionPromises);
|
|
915
994
|
}
|
|
916
995
|
|
|
917
|
-
// Handle token statistics and message
|
|
918
|
-
await this.
|
|
996
|
+
// Handle token statistics and message compaction
|
|
997
|
+
await this.handleTokenUsageAndCompaction(result.usage, abortController);
|
|
919
998
|
|
|
920
999
|
// Finalize text/reasoning blocks for the final response (no tools)
|
|
921
1000
|
this.messageManager.finalizeStreamingBlocks();
|
|
@@ -153,22 +153,27 @@ export class BackgroundTaskManager {
|
|
|
153
153
|
if (logStream.writable) {
|
|
154
154
|
logStream.end();
|
|
155
155
|
}
|
|
156
|
-
shell.status
|
|
156
|
+
const wasKilled = shell.status === "killed";
|
|
157
|
+
if (!wasKilled) {
|
|
158
|
+
shell.status = code === 0 ? "completed" : "failed";
|
|
159
|
+
}
|
|
157
160
|
shell.exitCode = code ?? 0;
|
|
158
161
|
shell.endTime = Date.now();
|
|
159
162
|
shell.runtime = shell.endTime - startTime;
|
|
160
163
|
this.notifyTasksChange();
|
|
161
164
|
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
165
|
+
// Skip notification if task was manually killed (user/agent-initiated stop)
|
|
166
|
+
if (!wasKilled) {
|
|
167
|
+
const notificationQueue = this.container.has("NotificationQueue")
|
|
168
|
+
? this.container.get<NotificationQueue>("NotificationQueue")
|
|
169
|
+
: undefined;
|
|
170
|
+
if (notificationQueue) {
|
|
171
|
+
const statusStr = shell.status;
|
|
172
|
+
const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
|
|
173
|
+
notificationQueue.enqueue(
|
|
174
|
+
`<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>`,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
172
177
|
}
|
|
173
178
|
};
|
|
174
179
|
|
|
@@ -301,22 +306,27 @@ export class BackgroundTaskManager {
|
|
|
301
306
|
if (logStream.writable) {
|
|
302
307
|
logStream.end();
|
|
303
308
|
}
|
|
304
|
-
shell.status
|
|
309
|
+
const wasKilled = shell.status === "killed";
|
|
310
|
+
if (!wasKilled) {
|
|
311
|
+
shell.status = code === 0 ? "completed" : "failed";
|
|
312
|
+
}
|
|
305
313
|
shell.exitCode = code ?? 0;
|
|
306
314
|
shell.endTime = Date.now();
|
|
307
315
|
shell.runtime = shell.endTime - startTime;
|
|
308
316
|
this.notifyTasksChange();
|
|
309
317
|
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
318
|
+
// Skip notification if task was manually killed (user/agent-initiated stop)
|
|
319
|
+
if (!wasKilled) {
|
|
320
|
+
const notificationQueue = this.container.has("NotificationQueue")
|
|
321
|
+
? this.container.get<NotificationQueue>("NotificationQueue")
|
|
322
|
+
: undefined;
|
|
323
|
+
if (notificationQueue) {
|
|
324
|
+
const statusStr = shell.status;
|
|
325
|
+
const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
|
|
326
|
+
notificationQueue.enqueue(
|
|
327
|
+
`<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>`,
|
|
328
|
+
);
|
|
329
|
+
}
|
|
320
330
|
}
|
|
321
331
|
});
|
|
322
332
|
|