@prestyj/cli 5.4.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -12
- package/dist/app-sidecar.js +244 -74
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/general.d.ts +7 -0
- package/dist/chat-agents/general.d.ts.map +1 -0
- package/dist/chat-agents/general.js +16 -0
- package/dist/chat-agents/general.js.map +1 -0
- package/dist/chat-agents/general.test.d.ts +2 -0
- package/dist/chat-agents/general.test.d.ts.map +1 -0
- package/dist/chat-agents/general.test.js +47 -0
- package/dist/chat-agents/general.test.js.map +1 -0
- package/dist/chat-agents/index.d.ts +11 -0
- package/dist/chat-agents/index.d.ts.map +1 -0
- package/dist/chat-agents/index.js +89 -0
- package/dist/chat-agents/index.js.map +1 -0
- package/dist/chat-agents/memory.d.ts +53 -0
- package/dist/chat-agents/memory.d.ts.map +1 -0
- package/dist/chat-agents/memory.js +362 -0
- package/dist/chat-agents/memory.js.map +1 -0
- package/dist/chat-agents/memory.test.d.ts +2 -0
- package/dist/chat-agents/memory.test.d.ts.map +1 -0
- package/dist/chat-agents/memory.test.js +155 -0
- package/dist/chat-agents/memory.test.js.map +1 -0
- package/dist/chat-agents/research.d.ts +7 -0
- package/dist/chat-agents/research.d.ts.map +1 -0
- package/dist/chat-agents/research.js +18 -0
- package/dist/chat-agents/research.js.map +1 -0
- package/dist/chat-agents/shared.d.ts +11 -0
- package/dist/chat-agents/shared.d.ts.map +1 -0
- package/dist/chat-agents/shared.js +48 -0
- package/dist/chat-agents/shared.js.map +1 -0
- package/dist/chat-agents/specialists.test.d.ts +2 -0
- package/dist/chat-agents/specialists.test.d.ts.map +1 -0
- package/dist/chat-agents/specialists.test.js +97 -0
- package/dist/chat-agents/specialists.test.js.map +1 -0
- package/dist/chat-agents/therapist.d.ts +7 -0
- package/dist/chat-agents/therapist.d.ts.map +1 -0
- package/dist/chat-agents/therapist.js +20 -0
- package/dist/chat-agents/therapist.js.map +1 -0
- package/dist/chat-agents/types.d.ts +4 -0
- package/dist/chat-agents/types.d.ts.map +1 -0
- package/dist/chat-agents/types.js +7 -0
- package/dist/chat-agents/types.js.map +1 -0
- package/dist/cli/auth.js +1 -1
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +72 -22
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-memory-tail.test.d.ts +2 -0
- package/dist/core/agent-session-memory-tail.test.d.ts.map +1 -0
- package/dist/core/agent-session-memory-tail.test.js +122 -0
- package/dist/core/agent-session-memory-tail.test.js.map +1 -0
- package/dist/core/agent-session-subagent-policy.test.d.ts +2 -0
- package/dist/core/agent-session-subagent-policy.test.d.ts.map +1 -0
- package/dist/core/agent-session-subagent-policy.test.js +36 -0
- package/dist/core/agent-session-subagent-policy.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +37 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +168 -109
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agents.d.ts +1 -1
- package/dist/core/agents.d.ts.map +1 -1
- package/dist/core/agents.js +4 -2
- package/dist/core/agents.js.map +1 -1
- package/dist/core/auth-providers.js +5 -5
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/compaction/compactor.d.ts +7 -0
- package/dist/core/compaction/compactor.d.ts.map +1 -1
- package/dist/core/compaction/compactor.js +73 -9
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/compaction/compactor.test.js +31 -4
- package/dist/core/compaction/compactor.test.js.map +1 -1
- package/dist/core/event-bus.d.ts +2 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/mcp/defaults.d.ts +1 -1
- package/dist/core/mcp/defaults.js +1 -1
- package/dist/core/mcp/store.d.ts +2 -2
- package/dist/core/mcp/store.test.js +1 -1
- package/dist/core/mcp/store.test.js.map +1 -1
- package/dist/core/progress/rebuild.d.ts +3 -3
- package/dist/core/progress/rebuild.d.ts.map +1 -1
- package/dist/core/progress/rebuild.js +33 -27
- package/dist/core/progress/rebuild.js.map +1 -1
- package/dist/core/progress/rebuild.test.js +15 -0
- package/dist/core/progress/rebuild.test.js.map +1 -1
- package/dist/core/project-discovery.d.ts +1 -1
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +5 -6
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.js +14 -1
- package/dist/core/project-discovery.test.js.map +1 -1
- package/dist/core/radio.d.ts +3 -0
- package/dist/core/radio.d.ts.map +1 -1
- package/dist/core/radio.js +150 -21
- package/dist/core/radio.js.map +1 -1
- package/dist/core/radio.test.d.ts +2 -0
- package/dist/core/radio.test.d.ts.map +1 -0
- package/dist/core/radio.test.js +101 -0
- package/dist/core/radio.test.js.map +1 -0
- package/dist/core/session-history.test.js +1 -1
- package/dist/core/session-history.test.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +2 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-manager.test.js +18 -0
- package/dist/core/session-manager.test.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/subagent-manager.d.ts +73 -0
- package/dist/core/subagent-manager.d.ts.map +1 -0
- package/dist/core/subagent-manager.js +412 -0
- package/dist/core/subagent-manager.js.map +1 -0
- package/dist/core/subagent-manager.test.d.ts +2 -0
- package/dist/core/subagent-manager.test.d.ts.map +1 -0
- package/dist/core/subagent-manager.test.js +103 -0
- package/dist/core/subagent-manager.test.js.map +1 -0
- package/dist/core/subagent-policy.d.ts +4 -0
- package/dist/core/subagent-policy.d.ts.map +1 -0
- package/dist/core/subagent-policy.js +19 -0
- package/dist/core/subagent-policy.js.map +1 -0
- package/dist/modes/json-mode.d.ts.map +1 -1
- package/dist/modes/json-mode.js +3 -4
- package/dist/modes/json-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.d.ts +14 -0
- package/dist/modes/subagent-worker-mode.d.ts.map +1 -0
- package/dist/modes/subagent-worker-mode.js +191 -0
- package/dist/modes/subagent-worker-mode.js.map +1 -0
- package/dist/tools/generate-image.d.ts.map +1 -1
- package/dist/tools/generate-image.js +12 -5
- package/dist/tools/generate-image.js.map +1 -1
- package/dist/tools/generate-image.test.js +17 -0
- package/dist/tools/generate-image.test.js.map +1 -1
- package/dist/tools/goals.d.ts +3 -3
- package/dist/tools/index.d.ts +10 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +17 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/subagent-control.d.ts +6 -0
- package/dist/tools/subagent-control.d.ts.map +1 -0
- package/dist/tools/subagent-control.js +95 -0
- package/dist/tools/subagent-control.js.map +1 -0
- package/dist/tools/subagent-control.test.d.ts +2 -0
- package/dist/tools/subagent-control.test.d.ts.map +1 -0
- package/dist/tools/subagent-control.test.js +40 -0
- package/dist/tools/subagent-control.test.js.map +1 -0
- package/dist/tools/subagent-shared.d.ts +24 -0
- package/dist/tools/subagent-shared.d.ts.map +1 -0
- package/dist/tools/subagent-shared.js +53 -0
- package/dist/tools/subagent-shared.js.map +1 -0
- package/dist/tools/subagent-shared.test.d.ts +2 -0
- package/dist/tools/subagent-shared.test.d.ts.map +1 -0
- package/dist/tools/subagent-shared.test.js +29 -0
- package/dist/tools/subagent-shared.test.js.map +1 -0
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +21 -64
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/subagent.test.js +27 -1
- package/dist/tools/subagent.test.js.map +1 -1
- package/dist/tools/web-fetch.d.ts +1 -0
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +112 -35
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-fetch.test.js +146 -1
- package/dist/tools/web-fetch.test.js.map +1 -1
- package/dist/tools/web-search.d.ts +10 -0
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +236 -28
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools/web-search.test.js +77 -6
- package/dist/tools/web-search.test.js.map +1 -1
- package/dist/ui/App.d.ts +2 -0
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +61 -2
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/hooks/useModeState.d.ts +4 -2
- package/dist/ui/hooks/useModeState.d.ts.map +1 -1
- package/dist/ui/hooks/useModeState.js +14 -3
- package/dist/ui/hooks/useModeState.js.map +1 -1
- package/dist/ui/login.d.ts.map +1 -1
- package/dist/ui/login.js +13 -5
- package/dist/ui/login.js.map +1 -1
- package/dist/ui/render.d.ts +14 -0
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +2 -0
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/render.test.js +17 -0
- package/dist/ui/render.test.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AgentTool } from "@prestyj/agent";
|
|
1
2
|
import { type Message, type Provider, type ThinkingLevel } from "@prestyj/ai";
|
|
2
3
|
import { EventBus } from "./event-bus.js";
|
|
3
4
|
import { SlashCommandRegistry } from "./slash-commands.js";
|
|
@@ -20,9 +21,12 @@ export interface AgentSessionOptions {
|
|
|
20
21
|
cwd: string;
|
|
21
22
|
baseUrl?: string;
|
|
22
23
|
systemPrompt?: string;
|
|
24
|
+
/** Synchronous volatile prompt suffix, refreshed immediately before every run. */
|
|
25
|
+
getSystemPromptTail?: () => string;
|
|
23
26
|
sessionId?: string;
|
|
24
27
|
continueRecent?: boolean;
|
|
25
28
|
maxTokens?: number;
|
|
29
|
+
maxTurns?: number;
|
|
26
30
|
thinkingLevel?: ThinkingLevel;
|
|
27
31
|
signal?: AbortSignal;
|
|
28
32
|
/** Prefix used for provider prompt-cache routing keys. */
|
|
@@ -94,6 +98,24 @@ export interface AgentSessionOptions {
|
|
|
94
98
|
* main build session. Default (undefined) = follow `speedProfile`.
|
|
95
99
|
*/
|
|
96
100
|
forceLongCacheRetention?: boolean;
|
|
101
|
+
/** Hidden persistent subagent workers omit the async orchestration tool suite. */
|
|
102
|
+
subagentWorker?: boolean;
|
|
103
|
+
/** Session storage root override. Chat agents use a dedicated namespace. */
|
|
104
|
+
sessionRootDir?: string;
|
|
105
|
+
/** Register EZ Coder built-in/prompt/custom slash commands. Defaults to true. */
|
|
106
|
+
coderSlashCommands?: boolean;
|
|
107
|
+
/** Enable loop-break, re-grounding, and Ideal review hooks. Defaults to true. */
|
|
108
|
+
selfCorrectionHooks?: boolean;
|
|
109
|
+
/** Load project skills/agents and create local .ezcoder directories. Defaults to true. */
|
|
110
|
+
projectCustomization?: boolean;
|
|
111
|
+
/** Register global + bundled subagents without loading project customization. */
|
|
112
|
+
globalSubagents?: boolean;
|
|
113
|
+
/** Load EZ Coder extensions. Defaults to true. */
|
|
114
|
+
loadExtensions?: boolean;
|
|
115
|
+
/** Inject EZ Coder's model-specific subagent orchestration prompt. Defaults to true. */
|
|
116
|
+
orchestrationPrompt?: boolean;
|
|
117
|
+
/** Host-provided tools appended to this session only (for example, chat delegation). */
|
|
118
|
+
additionalTools?: AgentTool[];
|
|
97
119
|
}
|
|
98
120
|
export interface AgentSessionState {
|
|
99
121
|
provider: Provider;
|
|
@@ -139,12 +161,12 @@ export declare class AgentSession {
|
|
|
139
161
|
private regroundingInjected;
|
|
140
162
|
private compactionOccurred;
|
|
141
163
|
private originalRequest;
|
|
142
|
-
/** True after the cache has been pre-warmed for this session. Ensures we only
|
|
143
|
-
* fire the warm-up call once (before the first real turn). */
|
|
144
|
-
private cachePrewarmed;
|
|
145
164
|
private userQueue;
|
|
146
165
|
private processManager?;
|
|
147
166
|
private lspManager?;
|
|
167
|
+
private subAgentManager?;
|
|
168
|
+
private managerAbortSignal?;
|
|
169
|
+
private readonly managerAbortHandler;
|
|
148
170
|
private mcpManager?;
|
|
149
171
|
/** Deferred MCP tools awaiting discovery via tool_search (bench A win). */
|
|
150
172
|
private mcpCatalog?;
|
|
@@ -160,6 +182,8 @@ export declare class AgentSession {
|
|
|
160
182
|
private maxTokens;
|
|
161
183
|
private thinkingLevel?;
|
|
162
184
|
private customSystemPrompt?;
|
|
185
|
+
/** Stable prompt prefix retained separately from the volatile uncached tail. */
|
|
186
|
+
private baseSystemPrompt;
|
|
163
187
|
/** Shared with the tool layer so plan-mode restrictions read live state. */
|
|
164
188
|
private planModeRef;
|
|
165
189
|
/** Path of the approved plan currently being implemented, or undefined. When
|
|
@@ -167,6 +191,9 @@ export declare class AgentSession {
|
|
|
167
191
|
* model emits step-completion markers the UI's plan-progress widget reads. */
|
|
168
192
|
private approvedPlanPath?;
|
|
169
193
|
private sessionId;
|
|
194
|
+
/** Runtime conversation identity for provider transport headers. Transient
|
|
195
|
+
* children need one even though they intentionally have no persisted session. */
|
|
196
|
+
private readonly transportSessionId;
|
|
170
197
|
private sessionPath;
|
|
171
198
|
private lastPersistedIndex;
|
|
172
199
|
/** Current leaf entry ID in the session DAG — used to chain parentIds for branching. */
|
|
@@ -303,6 +330,8 @@ export declare class AgentSession {
|
|
|
303
330
|
listBackgroundProcesses(): BackgroundProcess[];
|
|
304
331
|
/** Stop a background process by id. Returns a human-readable status string. */
|
|
305
332
|
killBackgroundProcess(id: string): Promise<string>;
|
|
333
|
+
/** Replace a host-owned system prompt in place without resetting conversation history. */
|
|
334
|
+
setCustomSystemPrompt(systemPrompt: string, promptCacheKeyPrefix?: string): void;
|
|
306
335
|
/**
|
|
307
336
|
* Toggle plan mode: flips the shared ref (so tools enforce read-only
|
|
308
337
|
* restrictions) and rebuilds the system prompt in place so the model is told
|
|
@@ -319,6 +348,8 @@ export declare class AgentSession {
|
|
|
319
348
|
setApprovedPlan(approvedPlanPath: string | undefined): Promise<void>;
|
|
320
349
|
/** Rebuild messages[0] from current plan-mode + approved-plan state. */
|
|
321
350
|
private rebuildSystemPromptInPlace;
|
|
351
|
+
private withSystemPromptTail;
|
|
352
|
+
private refreshSystemPromptTail;
|
|
322
353
|
getMessages(): Message[];
|
|
323
354
|
/** Nolan Grout (mentor) turns recorded against this session, in record order. Used
|
|
324
355
|
* by the host to interleave Nolan's advisory exchanges back into the transcript
|
|
@@ -397,8 +428,11 @@ export declare class AgentSession {
|
|
|
397
428
|
/** Set the reasoning/thinking level (undefined turns thinking off). Takes
|
|
398
429
|
* effect on the next prompt, since the in-flight loop reads it at start. */
|
|
399
430
|
setThinkingLevel(level: ThinkingLevel | undefined): void;
|
|
431
|
+
/** Sol/Terra Ultra delegates proactively; lower levels require an explicit request. */
|
|
432
|
+
private syncUltraOrchestrationPrompt;
|
|
400
433
|
/** Replace the abort signal (e.g. after cancellation). */
|
|
401
434
|
setSignal(signal: AbortSignal): void;
|
|
435
|
+
private bindManagerCancellation;
|
|
402
436
|
/** True when speedProfile is "optimized" (1-h cache TTL + pre-warm), or the
|
|
403
437
|
* session was constructed with `forceLongCacheRetention` (Nolan sessions). */
|
|
404
438
|
private isSpeedOptimized;
|
|
@@ -410,11 +444,6 @@ export declare class AgentSession {
|
|
|
410
444
|
* API-only `mimo-v2.5-pro-ultraspeed` has no fallback).
|
|
411
445
|
*/
|
|
412
446
|
private currentAuthStorageKeys;
|
|
413
|
-
/** Fire a cache pre-warm request for Anthropic so the first real turn is a
|
|
414
|
-
* cache read instead of a cold write. No-op for other providers and when
|
|
415
|
-
* speedProfile is not "optimized". Entirely best-effort — any failure is
|
|
416
|
-
* swallowed so prewarm never blocks or aborts the real prompt. */
|
|
417
|
-
private maybePrewarmCache;
|
|
418
447
|
private getPromptCacheKey;
|
|
419
448
|
/** Stable cache-routing key for downstream sub-agent processes. */
|
|
420
449
|
getCurrentCacheKey(): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/core/agent-session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/core/agent-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { agentLoop, isAbortError } from "@prestyj/agent";
|
|
2
|
-
import { ProviderError,
|
|
2
|
+
import { ProviderError, } from "@prestyj/ai";
|
|
3
3
|
import { EventBus } from "./event-bus.js";
|
|
4
4
|
import { SlashCommandRegistry, createBuiltinCommands, } from "./slash-commands.js";
|
|
5
5
|
import { PROMPT_COMMANDS, getPromptCommand } from "./prompt-commands.js";
|
|
@@ -16,6 +16,7 @@ import { discoverSkills } from "./skills.js";
|
|
|
16
16
|
import { ensureAppDirs } from "../config.js";
|
|
17
17
|
import { buildSystemPrompt } from "../system-prompt.js";
|
|
18
18
|
import { createTools, createWebSearchTool, } from "../tools/index.js";
|
|
19
|
+
import { applyAsyncSubagentPolicy } from "./subagent-policy.js";
|
|
19
20
|
import { MCPClientManager, getAllMcpServers } from "./mcp/index.js";
|
|
20
21
|
import { DeferredToolCatalog } from "./mcp/deferred-catalog.js";
|
|
21
22
|
import { createToolSearchTool } from "../tools/tool-search.js";
|
|
@@ -89,9 +90,6 @@ export class AgentSession {
|
|
|
89
90
|
regroundingInjected = false;
|
|
90
91
|
compactionOccurred = false;
|
|
91
92
|
originalRequest = "";
|
|
92
|
-
/** True after the cache has been pre-warmed for this session. Ensures we only
|
|
93
|
-
* fire the warm-up call once (before the first real turn). */
|
|
94
|
-
cachePrewarmed = false;
|
|
95
93
|
// Messages queued by the user while a run is in flight. Drained at the
|
|
96
94
|
// mid-loop steering boundary (user steering wins over the hooks), mirroring
|
|
97
95
|
// the TUI's getSteeringMessages. Each entry carries its own attachments so a
|
|
@@ -99,6 +97,11 @@ export class AgentSession {
|
|
|
99
97
|
userQueue = [];
|
|
100
98
|
processManager;
|
|
101
99
|
lspManager;
|
|
100
|
+
subAgentManager;
|
|
101
|
+
managerAbortSignal;
|
|
102
|
+
managerAbortHandler = () => {
|
|
103
|
+
void this.subAgentManager?.interruptAll();
|
|
104
|
+
};
|
|
102
105
|
mcpManager;
|
|
103
106
|
/** Deferred MCP tools awaiting discovery via tool_search (bench A win). */
|
|
104
107
|
mcpCatalog;
|
|
@@ -114,6 +117,8 @@ export class AgentSession {
|
|
|
114
117
|
maxTokens;
|
|
115
118
|
thinkingLevel;
|
|
116
119
|
customSystemPrompt;
|
|
120
|
+
/** Stable prompt prefix retained separately from the volatile uncached tail. */
|
|
121
|
+
baseSystemPrompt = "";
|
|
117
122
|
/** Shared with the tool layer so plan-mode restrictions read live state. */
|
|
118
123
|
planModeRef = { current: false };
|
|
119
124
|
/** Path of the approved plan currently being implemented, or undefined. When
|
|
@@ -121,6 +126,9 @@ export class AgentSession {
|
|
|
121
126
|
* model emits step-completion markers the UI's plan-progress widget reads. */
|
|
122
127
|
approvedPlanPath;
|
|
123
128
|
sessionId = "";
|
|
129
|
+
/** Runtime conversation identity for provider transport headers. Transient
|
|
130
|
+
* children need one even though they intentionally have no persisted session. */
|
|
131
|
+
transportSessionId = crypto.randomUUID();
|
|
124
132
|
sessionPath = "";
|
|
125
133
|
lastPersistedIndex = 0;
|
|
126
134
|
/** Current leaf entry ID in the session DAG — used to chain parentIds for branching. */
|
|
@@ -162,24 +170,34 @@ export class AgentSession {
|
|
|
162
170
|
await this.settingsManager.load();
|
|
163
171
|
this.authStorage = new AuthStorage(paths.authFile);
|
|
164
172
|
await this.authStorage.load();
|
|
165
|
-
// Session manager
|
|
166
|
-
this.sessionManager = new SessionManager(paths.sessionsDir);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
173
|
+
// Session manager. Agent-specific roots keep chat and coder histories isolated.
|
|
174
|
+
this.sessionManager = new SessionManager(this.opts.sessionRootDir ?? paths.sessionsDir);
|
|
175
|
+
const projectCustomization = this.opts.projectCustomization !== false;
|
|
176
|
+
if (projectCustomization) {
|
|
177
|
+
// Ensure project-local .ezcoder directories exist.
|
|
178
|
+
const localEzDir = path.join(this.cwd, ".ezcoder");
|
|
179
|
+
await fs.mkdir(path.join(localEzDir, "skills"), { recursive: true });
|
|
180
|
+
await fs.mkdir(path.join(localEzDir, "commands"), { recursive: true });
|
|
181
|
+
await fs.mkdir(path.join(localEzDir, "agents"), { recursive: true });
|
|
182
|
+
this.skills = await discoverSkills({
|
|
183
|
+
globalSkillsDir: paths.skillsDir,
|
|
184
|
+
projectDir: this.cwd,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
this.skills = [];
|
|
189
|
+
}
|
|
190
|
+
// Discover agents and create tools (with sub-agent support). Chat sessions
|
|
191
|
+
// can retain bundled workers without loading project/global customization.
|
|
192
|
+
const agents = projectCustomization
|
|
193
|
+
? await discoverAgents({
|
|
194
|
+
globalAgentsDir: paths.agentsDir,
|
|
195
|
+
projectDir: this.cwd,
|
|
196
|
+
})
|
|
197
|
+
: this.opts.globalSubagents
|
|
198
|
+
? await discoverAgents({ globalAgentsDir: paths.agentsDir })
|
|
199
|
+
: [];
|
|
200
|
+
const { tools: builtInTools, processManager, rebuildReadTool, lspManager, subAgentManager, } = await createTools(this.cwd, {
|
|
183
201
|
agents,
|
|
184
202
|
skills: this.skills,
|
|
185
203
|
provider: this.provider,
|
|
@@ -190,7 +208,11 @@ export class AgentSession {
|
|
|
190
208
|
// sub-agent spawns read the current parent state at execution time.
|
|
191
209
|
getProvider: () => this.provider,
|
|
192
210
|
getModel: () => this.model,
|
|
211
|
+
getThinkingLevel: () => this.thinkingLevel,
|
|
212
|
+
getBaseUrl: () => this.baseUrl,
|
|
193
213
|
getCacheKey: () => this.getPromptCacheKey(),
|
|
214
|
+
disableAsyncSubagents: this.opts.subagentWorker,
|
|
215
|
+
onSubAgentState: (snapshot) => this.eventBus.emit("subagent_state", snapshot),
|
|
194
216
|
// Plan mode: only wired when the host supplies callbacks. The ref is
|
|
195
217
|
// shared so bash/edit/write enforce read-only restrictions live.
|
|
196
218
|
...(this.opts.onEnterPlan || this.opts.onExitPlan
|
|
@@ -201,6 +223,7 @@ export class AgentSession {
|
|
|
201
223
|
}
|
|
202
224
|
: {}),
|
|
203
225
|
});
|
|
226
|
+
const tools = [...builtInTools, ...(this.opts.additionalTools ?? [])];
|
|
204
227
|
// Apply the optional tool allow-list (read-only advisory sessions). Filtering
|
|
205
228
|
// here means the excluded tools are never registered with the agent loop, so
|
|
206
229
|
// a hallucinated call can't mutate the repo — and buildSystemPrompt below is
|
|
@@ -209,6 +232,8 @@ export class AgentSession {
|
|
|
209
232
|
this.rebuildReadTool = rebuildReadTool;
|
|
210
233
|
this.processManager = processManager;
|
|
211
234
|
this.lspManager = lspManager;
|
|
235
|
+
this.subAgentManager = subAgentManager;
|
|
236
|
+
this.bindManagerCancellation(this.opts.signal);
|
|
212
237
|
// Connect MCP servers (non-blocking — failures are logged and skipped).
|
|
213
238
|
// Child sessions (subagents and goal workers run via `--json` mode) get the
|
|
214
239
|
// provider defaults only — NOT user-configured servers. The defaults now
|
|
@@ -234,7 +259,9 @@ export class AgentSession {
|
|
|
234
259
|
}
|
|
235
260
|
const basePrompt = this.customSystemPrompt ??
|
|
236
261
|
(await buildSystemPrompt(this.cwd, this.skills, false, undefined, this.tools.map((tool) => tool.name), undefined, this.provider));
|
|
237
|
-
this.
|
|
262
|
+
this.baseSystemPrompt = basePrompt;
|
|
263
|
+
this.messages = [{ role: "system", content: this.withSystemPromptTail(basePrompt) }];
|
|
264
|
+
this.syncUltraOrchestrationPrompt();
|
|
238
265
|
// Load or create session. Transient sessions (subagent spawns) never
|
|
239
266
|
// touch the session store — sessionPath stays empty and persistMessage
|
|
240
267
|
// is a no-op so their transcripts can't pollute `ezcoder continue`.
|
|
@@ -256,48 +283,46 @@ export class AgentSession {
|
|
|
256
283
|
else {
|
|
257
284
|
await this.createNewSession();
|
|
258
285
|
}
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
286
|
+
// EZ Coder owns its command registry. Other agents start with an isolated
|
|
287
|
+
// empty registry and can register their own commands in their own file.
|
|
288
|
+
if (this.opts.coderSlashCommands !== false) {
|
|
289
|
+
const builtins = createBuiltinCommands();
|
|
290
|
+
for (const cmd of builtins)
|
|
291
|
+
this.slashCommands.register(cmd);
|
|
292
|
+
// Wire up /help to show all registered + prompt + custom commands.
|
|
293
|
+
const helpCmd = this.slashCommands.get("help");
|
|
294
|
+
if (helpCmd) {
|
|
295
|
+
const registry = this.slashCommands;
|
|
296
|
+
const cwd = this.cwd;
|
|
297
|
+
helpCmd.execute = async () => {
|
|
298
|
+
const all = registry.getAll();
|
|
299
|
+
const lines = all.map((c) => ` /${c.name}${c.aliases.length ? ` (${c.aliases.map((a) => "/" + a).join(", ")})` : ""} — ${c.description}`);
|
|
300
|
+
if (PROMPT_COMMANDS.length > 0) {
|
|
301
|
+
lines.push("", "Prompt commands:");
|
|
302
|
+
for (const cmd of PROMPT_COMMANDS) {
|
|
303
|
+
lines.push(` /${cmd.name}${cmd.aliases.length ? ` (${cmd.aliases.map((a) => "/" + a).join(", ")})` : ""} — ${cmd.description}`);
|
|
304
|
+
}
|
|
278
305
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
lines.push("Custom commands:");
|
|
285
|
-
for (const cmd of customCmds) {
|
|
286
|
-
lines.push(` /${cmd.name} — ${cmd.description}`);
|
|
306
|
+
const customCmds = await loadCustomCommands(cwd);
|
|
307
|
+
if (customCmds.length > 0) {
|
|
308
|
+
lines.push("", "Custom commands:");
|
|
309
|
+
for (const cmd of customCmds)
|
|
310
|
+
lines.push(` /${cmd.name} — ${cmd.description}`);
|
|
287
311
|
}
|
|
288
|
-
|
|
289
|
-
|
|
312
|
+
return "Available commands:\n" + lines.join("\n");
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (this.opts.loadExtensions !== false) {
|
|
317
|
+
const extContext = {
|
|
318
|
+
eventBus: this.eventBus,
|
|
319
|
+
registerTool: (tool) => this.tools.push(tool),
|
|
320
|
+
registerSlashCommand: (cmd) => this.slashCommands.register(cmd),
|
|
321
|
+
cwd: this.cwd,
|
|
322
|
+
settingsManager: this.settingsManager,
|
|
290
323
|
};
|
|
324
|
+
await this.extensionLoader.loadAll(paths.extensionsDir, extContext);
|
|
291
325
|
}
|
|
292
|
-
// Load extensions
|
|
293
|
-
const extContext = {
|
|
294
|
-
eventBus: this.eventBus,
|
|
295
|
-
registerTool: (tool) => this.tools.push(tool),
|
|
296
|
-
registerSlashCommand: (cmd) => this.slashCommands.register(cmd),
|
|
297
|
-
cwd: this.cwd,
|
|
298
|
-
settingsManager: this.settingsManager,
|
|
299
|
-
};
|
|
300
|
-
await this.extensionLoader.loadAll(paths.extensionsDir, extContext);
|
|
301
326
|
this.eventBus.emit("session_start", { sessionId: this.sessionId });
|
|
302
327
|
}
|
|
303
328
|
/**
|
|
@@ -413,12 +438,17 @@ export class AgentSession {
|
|
|
413
438
|
* Process user input. Handles slash commands or runs agent loop.
|
|
414
439
|
*/
|
|
415
440
|
async prompt(content) {
|
|
416
|
-
|
|
417
|
-
const
|
|
441
|
+
const parsedInput = this.slashCommands.parse(content);
|
|
442
|
+
const coderCommands = this.opts.coderSlashCommands !== false;
|
|
443
|
+
// Non-coder agents only intercept commands registered in their own registry.
|
|
444
|
+
// Unknown `/text` stays a normal conversational prompt.
|
|
445
|
+
const parsed = parsedInput && (coderCommands || this.slashCommands.get(parsedInput.name))
|
|
446
|
+
? parsedInput
|
|
447
|
+
: null;
|
|
418
448
|
if (parsed) {
|
|
419
|
-
//
|
|
420
|
-
const builtinPromptCmd = getPromptCommand(parsed.name);
|
|
421
|
-
const customCmds = await loadCustomCommands(this.cwd);
|
|
449
|
+
// EZ Coder alone can resolve its prompt-template and project commands.
|
|
450
|
+
const builtinPromptCmd = coderCommands ? getPromptCommand(parsed.name) : undefined;
|
|
451
|
+
const customCmds = coderCommands ? await loadCustomCommands(this.cwd) : [];
|
|
422
452
|
const customPromptCmd = !builtinPromptCmd
|
|
423
453
|
? customCmds.find((c) => c.name === parsed.name)
|
|
424
454
|
: undefined;
|
|
@@ -637,6 +667,8 @@ export class AgentSession {
|
|
|
637
667
|
return { role: "user", content: parts };
|
|
638
668
|
});
|
|
639
669
|
}
|
|
670
|
+
if (this.opts.selfCorrectionHooks === false)
|
|
671
|
+
return null;
|
|
640
672
|
if (!this.settingsManager.get("idealReviewEnabled"))
|
|
641
673
|
return null;
|
|
642
674
|
if (!this.loopBreakInjected) {
|
|
@@ -664,6 +696,8 @@ export class AgentSession {
|
|
|
664
696
|
* otherwise finish and the change set is substantial enough to warrant it.
|
|
665
697
|
*/
|
|
666
698
|
getHookFollowUpMessages() {
|
|
699
|
+
if (this.opts.selfCorrectionHooks === false)
|
|
700
|
+
return null;
|
|
667
701
|
if (!this.settingsManager.get("idealReviewEnabled"))
|
|
668
702
|
return null;
|
|
669
703
|
if (this.idealReviewInjected)
|
|
@@ -680,6 +714,7 @@ export class AgentSession {
|
|
|
680
714
|
}
|
|
681
715
|
/** Auto-compact if needed, run agent loop with auth retry, and persist messages. */
|
|
682
716
|
async runLoop() {
|
|
717
|
+
this.refreshSystemPromptTail();
|
|
683
718
|
// One-shot cache-key marker per session so turn_end cacheRead numbers
|
|
684
719
|
// in the log can be traced back to a specific routing namespace —
|
|
685
720
|
// particularly useful when sub-agents inherit `parentKey:subagent`.
|
|
@@ -739,11 +774,13 @@ export class AgentSession {
|
|
|
739
774
|
tools: this.tools,
|
|
740
775
|
webSearch: true,
|
|
741
776
|
maxTokens: this.maxTokens,
|
|
777
|
+
maxTurns: this.opts.maxTurns,
|
|
742
778
|
thinking: this.thinkingLevel,
|
|
743
779
|
apiKey,
|
|
744
780
|
baseUrl: effectiveBaseUrl,
|
|
745
781
|
signal: this.opts.signal,
|
|
746
782
|
accountId,
|
|
783
|
+
transportSessionId: this.sessionId || this.transportSessionId,
|
|
747
784
|
projectId,
|
|
748
785
|
// Kimi For Coding gates the managed endpoint on coding-agent identity
|
|
749
786
|
// headers; attach them only when the Kimi OAuth token is in use.
|
|
@@ -790,11 +827,6 @@ export class AgentSession {
|
|
|
790
827
|
}
|
|
791
828
|
};
|
|
792
829
|
try {
|
|
793
|
-
// Fire cache pre-warm before the first turn (Anthropic + speedProfile optimized).
|
|
794
|
-
// Runs concurrently with nothing — it must complete before runAgentLoop so
|
|
795
|
-
// the cache is warm when the real request arrives. Best-effort: swallowed
|
|
796
|
-
// inside maybePrewarmCache/prewarmAnthropicCache.
|
|
797
|
-
await this.maybePrewarmCache(creds);
|
|
798
830
|
await runAgentLoop(creds.accessToken, creds.accountId, creds.projectId);
|
|
799
831
|
}
|
|
800
832
|
catch (err) {
|
|
@@ -841,6 +873,11 @@ export class AgentSession {
|
|
|
841
873
|
if (provider)
|
|
842
874
|
this.provider = provider;
|
|
843
875
|
this.model = model;
|
|
876
|
+
// Keep host-provided option closures (notably chat delegation) aligned with
|
|
877
|
+
// the live selection after an in-session model switch.
|
|
878
|
+
this.opts.provider = this.provider;
|
|
879
|
+
this.opts.model = this.model;
|
|
880
|
+
this.syncUltraOrchestrationPrompt();
|
|
844
881
|
setEstimatorModel(model);
|
|
845
882
|
// maxTokens must follow the active model — it was frozen at the boot
|
|
846
883
|
// model's `maxOutputTokens` in the constructor, so without this a session
|
|
@@ -984,7 +1021,9 @@ export class AgentSession {
|
|
|
984
1021
|
this.appMarkers = [];
|
|
985
1022
|
const basePrompt = this.customSystemPrompt ??
|
|
986
1023
|
(await buildSystemPrompt(this.cwd, this.skills, false, undefined, this.tools.map((tool) => tool.name), undefined, this.provider));
|
|
987
|
-
this.
|
|
1024
|
+
this.baseSystemPrompt = basePrompt;
|
|
1025
|
+
this.messages = [{ role: "system", content: this.withSystemPromptTail(basePrompt) }];
|
|
1026
|
+
this.syncUltraOrchestrationPrompt();
|
|
988
1027
|
// Fresh conversation — new entries must not chain onto the old DAG's leaf.
|
|
989
1028
|
this.currentLeafId = null;
|
|
990
1029
|
// Transient sessions (Nolan chat/autopilot, subagent spawns) never touch the
|
|
@@ -1099,6 +1138,22 @@ export class AgentSession {
|
|
|
1099
1138
|
return `No background process with id "${id}"`;
|
|
1100
1139
|
return this.processManager.stop(id);
|
|
1101
1140
|
}
|
|
1141
|
+
/** Replace a host-owned system prompt in place without resetting conversation history. */
|
|
1142
|
+
setCustomSystemPrompt(systemPrompt, promptCacheKeyPrefix) {
|
|
1143
|
+
this.customSystemPrompt = systemPrompt;
|
|
1144
|
+
this.baseSystemPrompt = systemPrompt;
|
|
1145
|
+
this.opts.systemPrompt = systemPrompt;
|
|
1146
|
+
if (promptCacheKeyPrefix)
|
|
1147
|
+
this.opts.promptCacheKeyPrefix = promptCacheKeyPrefix;
|
|
1148
|
+
const content = this.withSystemPromptTail(systemPrompt);
|
|
1149
|
+
if (this.messages[0]?.role === "system") {
|
|
1150
|
+
this.messages[0] = { role: "system", content };
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
this.messages.unshift({ role: "system", content });
|
|
1154
|
+
}
|
|
1155
|
+
this.syncUltraOrchestrationPrompt();
|
|
1156
|
+
}
|
|
1102
1157
|
/**
|
|
1103
1158
|
* Toggle plan mode: flips the shared ref (so tools enforce read-only
|
|
1104
1159
|
* restrictions) and rebuilds the system prompt in place so the model is told
|
|
@@ -1128,11 +1183,30 @@ export class AgentSession {
|
|
|
1128
1183
|
if (this.customSystemPrompt)
|
|
1129
1184
|
return;
|
|
1130
1185
|
const rebuilt = await buildSystemPrompt(this.cwd, this.skills, this.planModeRef.current, this.approvedPlanPath, this.tools.map((tool) => tool.name), undefined, this.provider);
|
|
1186
|
+
this.baseSystemPrompt = rebuilt;
|
|
1187
|
+
const content = this.withSystemPromptTail(rebuilt);
|
|
1131
1188
|
if (this.messages[0]?.role === "system") {
|
|
1132
|
-
this.messages[0] = { role: "system", content
|
|
1189
|
+
this.messages[0] = { role: "system", content };
|
|
1133
1190
|
}
|
|
1134
1191
|
else {
|
|
1135
|
-
this.messages.unshift({ role: "system", content
|
|
1192
|
+
this.messages.unshift({ role: "system", content });
|
|
1193
|
+
}
|
|
1194
|
+
this.syncUltraOrchestrationPrompt();
|
|
1195
|
+
}
|
|
1196
|
+
withSystemPromptTail(basePrompt) {
|
|
1197
|
+
if (!this.opts.getSystemPromptTail)
|
|
1198
|
+
return basePrompt;
|
|
1199
|
+
return `${basePrompt}\n\n<!-- uncached -->\n${this.opts.getSystemPromptTail()}`;
|
|
1200
|
+
}
|
|
1201
|
+
refreshSystemPromptTail() {
|
|
1202
|
+
if (!this.opts.getSystemPromptTail)
|
|
1203
|
+
return;
|
|
1204
|
+
const content = this.withSystemPromptTail(this.baseSystemPrompt);
|
|
1205
|
+
if (this.messages[0]?.role === "system") {
|
|
1206
|
+
this.messages[0] = { role: "system", content };
|
|
1207
|
+
}
|
|
1208
|
+
else {
|
|
1209
|
+
this.messages.unshift({ role: "system", content });
|
|
1136
1210
|
}
|
|
1137
1211
|
}
|
|
1138
1212
|
getMessages() {
|
|
@@ -1367,10 +1441,28 @@ export class AgentSession {
|
|
|
1367
1441
|
* effect on the next prompt, since the in-flight loop reads it at start. */
|
|
1368
1442
|
setThinkingLevel(level) {
|
|
1369
1443
|
this.thinkingLevel = level;
|
|
1444
|
+
this.syncUltraOrchestrationPrompt();
|
|
1445
|
+
}
|
|
1446
|
+
/** Sol/Terra Ultra delegates proactively; lower levels require an explicit request. */
|
|
1447
|
+
syncUltraOrchestrationPrompt() {
|
|
1448
|
+
if (this.opts.orchestrationPrompt === false)
|
|
1449
|
+
return;
|
|
1450
|
+
const systemMessage = this.messages[0];
|
|
1451
|
+
if (systemMessage?.role !== "system" || typeof systemMessage.content !== "string")
|
|
1452
|
+
return;
|
|
1453
|
+
systemMessage.content = applyAsyncSubagentPolicy(systemMessage.content, this.provider, this.model, this.thinkingLevel, this.tools.map((tool) => tool.name));
|
|
1370
1454
|
}
|
|
1371
1455
|
/** Replace the abort signal (e.g. after cancellation). */
|
|
1372
1456
|
setSignal(signal) {
|
|
1373
1457
|
this.opts = { ...this.opts, signal };
|
|
1458
|
+
this.bindManagerCancellation(signal);
|
|
1459
|
+
}
|
|
1460
|
+
bindManagerCancellation(signal) {
|
|
1461
|
+
this.managerAbortSignal?.removeEventListener("abort", this.managerAbortHandler);
|
|
1462
|
+
this.managerAbortSignal = signal;
|
|
1463
|
+
signal?.addEventListener("abort", this.managerAbortHandler, { once: true });
|
|
1464
|
+
if (signal?.aborted)
|
|
1465
|
+
this.managerAbortHandler();
|
|
1374
1466
|
}
|
|
1375
1467
|
/** True when speedProfile is "optimized" (1-h cache TTL + pre-warm), or the
|
|
1376
1468
|
* session was constructed with `forceLongCacheRetention` (Nolan sessions). */
|
|
@@ -1388,40 +1480,6 @@ export class AgentSession {
|
|
|
1388
1480
|
currentAuthStorageKeys() {
|
|
1389
1481
|
return getAuthStorageKeys(this.provider, this.model);
|
|
1390
1482
|
}
|
|
1391
|
-
/** Fire a cache pre-warm request for Anthropic so the first real turn is a
|
|
1392
|
-
* cache read instead of a cold write. No-op for other providers and when
|
|
1393
|
-
* speedProfile is not "optimized". Entirely best-effort — any failure is
|
|
1394
|
-
* swallowed so prewarm never blocks or aborts the real prompt. */
|
|
1395
|
-
async maybePrewarmCache(creds) {
|
|
1396
|
-
if (this.cachePrewarmed || !this.isSpeedOptimized() || this.provider !== "anthropic") {
|
|
1397
|
-
return;
|
|
1398
|
-
}
|
|
1399
|
-
this.cachePrewarmed = true;
|
|
1400
|
-
try {
|
|
1401
|
-
const userAgent = await getClaudeCliUserAgent();
|
|
1402
|
-
const systemText = typeof this.messages[0]?.content === "string" ? this.messages[0].content : "";
|
|
1403
|
-
if (!systemText)
|
|
1404
|
-
return;
|
|
1405
|
-
await prewarmAnthropicCache({
|
|
1406
|
-
apiKey: creds.accessToken,
|
|
1407
|
-
model: this.model,
|
|
1408
|
-
system: systemText,
|
|
1409
|
-
tools: this.tools.map((t) => ({
|
|
1410
|
-
name: t.name,
|
|
1411
|
-
description: t.description,
|
|
1412
|
-
parameters: t.parameters,
|
|
1413
|
-
...(t.rawInputSchema ? { rawInputSchema: t.rawInputSchema } : {}),
|
|
1414
|
-
})),
|
|
1415
|
-
baseUrl: this.baseUrl ?? creds.baseUrl,
|
|
1416
|
-
userAgent,
|
|
1417
|
-
cacheRetention: "long",
|
|
1418
|
-
signal: this.opts.signal,
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
catch {
|
|
1422
|
-
// Best-effort — prewarm failure must never block the session.
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
1483
|
getPromptCacheKey() {
|
|
1426
1484
|
if (this.opts.promptCacheKey)
|
|
1427
1485
|
return this.opts.promptCacheKey;
|
|
@@ -1434,9 +1492,10 @@ export class AgentSession {
|
|
|
1434
1492
|
return this.getPromptCacheKey();
|
|
1435
1493
|
}
|
|
1436
1494
|
async dispose() {
|
|
1495
|
+
this.managerAbortSignal?.removeEventListener("abort", this.managerAbortHandler);
|
|
1437
1496
|
this.processManager?.shutdownAll();
|
|
1438
1497
|
this.lspManager?.shutdownAll();
|
|
1439
|
-
await this.mcpManager?.dispose();
|
|
1498
|
+
await Promise.all([this.subAgentManager?.shutdownAll(), this.mcpManager?.dispose()]);
|
|
1440
1499
|
await this.extensionLoader.deactivateAll();
|
|
1441
1500
|
this.eventBus.removeAllListeners();
|
|
1442
1501
|
this.messages = [];
|