byterover-cli 3.0.0 → 3.1.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/dist/agent/core/domain/tools/constants.d.ts +1 -0
- package/dist/agent/core/domain/tools/constants.js +1 -0
- package/dist/agent/core/interfaces/cipher-services.d.ts +8 -0
- package/dist/agent/core/interfaces/i-cipher-agent.d.ts +1 -0
- package/dist/agent/infra/agent/agent-error-codes.d.ts +0 -1
- package/dist/agent/infra/agent/agent-error-codes.js +0 -1
- package/dist/agent/infra/agent/agent-error.d.ts +0 -1
- package/dist/agent/infra/agent/agent-error.js +0 -1
- package/dist/agent/infra/agent/agent-state-manager.d.ts +1 -3
- package/dist/agent/infra/agent/agent-state-manager.js +1 -3
- package/dist/agent/infra/agent/base-agent.d.ts +1 -1
- package/dist/agent/infra/agent/base-agent.js +1 -1
- package/dist/agent/infra/agent/cipher-agent.d.ts +15 -1
- package/dist/agent/infra/agent/cipher-agent.js +188 -3
- package/dist/agent/infra/agent/index.d.ts +1 -1
- package/dist/agent/infra/agent/index.js +1 -1
- package/dist/agent/infra/agent/service-initializer.d.ts +3 -3
- package/dist/agent/infra/agent/service-initializer.js +14 -8
- package/dist/agent/infra/agent/types.d.ts +0 -1
- package/dist/agent/infra/file-system/file-system-service.js +6 -5
- package/dist/agent/infra/folder-pack/folder-pack-service.d.ts +1 -0
- package/dist/agent/infra/folder-pack/folder-pack-service.js +29 -15
- package/dist/agent/infra/llm/providers/openai.js +12 -0
- package/dist/agent/infra/llm/stream-to-text.d.ts +7 -0
- package/dist/agent/infra/llm/stream-to-text.js +14 -0
- package/dist/agent/infra/map/abstract-generator.d.ts +22 -0
- package/dist/agent/infra/map/abstract-generator.js +67 -0
- package/dist/agent/infra/map/abstract-queue.d.ts +67 -0
- package/dist/agent/infra/map/abstract-queue.js +218 -0
- package/dist/agent/infra/memory/memory-deduplicator.d.ts +44 -0
- package/dist/agent/infra/memory/memory-deduplicator.js +88 -0
- package/dist/agent/infra/memory/memory-manager.d.ts +1 -0
- package/dist/agent/infra/memory/memory-manager.js +6 -5
- package/dist/agent/infra/sandbox/curate-service.d.ts +4 -2
- package/dist/agent/infra/sandbox/curate-service.js +6 -7
- package/dist/agent/infra/sandbox/local-sandbox.d.ts +5 -0
- package/dist/agent/infra/sandbox/local-sandbox.js +57 -1
- package/dist/agent/infra/sandbox/tools-sdk.d.ts +3 -1
- package/dist/agent/infra/session/session-compressor.d.ts +43 -0
- package/dist/agent/infra/session/session-compressor.js +296 -0
- package/dist/agent/infra/session/session-manager.d.ts +7 -0
- package/dist/agent/infra/session/session-manager.js +9 -0
- package/dist/agent/infra/tools/implementations/curate-tool.d.ts +3 -2
- package/dist/agent/infra/tools/implementations/curate-tool.js +54 -27
- package/dist/agent/infra/tools/implementations/expand-knowledge-tool.d.ts +3 -3
- package/dist/agent/infra/tools/implementations/expand-knowledge-tool.js +34 -7
- package/dist/agent/infra/tools/implementations/ingest-resource-tool.d.ts +17 -0
- package/dist/agent/infra/tools/implementations/ingest-resource-tool.js +224 -0
- package/dist/agent/infra/tools/implementations/memory-symbol-tree.d.ts +8 -0
- package/dist/agent/infra/tools/implementations/search-knowledge-service.d.ts +1 -1
- package/dist/agent/infra/tools/implementations/search-knowledge-service.js +207 -34
- package/dist/agent/infra/tools/implementations/search-knowledge-tool.js +2 -2
- package/dist/agent/infra/tools/tool-provider.js +1 -0
- package/dist/agent/infra/tools/tool-registry.d.ts +3 -0
- package/dist/agent/infra/tools/tool-registry.js +15 -4
- package/dist/server/constants.d.ts +2 -0
- package/dist/server/constants.js +2 -0
- package/dist/server/core/domain/knowledge/memory-scoring.d.ts +3 -3
- package/dist/server/core/domain/knowledge/memory-scoring.js +5 -5
- package/dist/server/core/domain/knowledge/summary-types.d.ts +4 -0
- package/dist/server/core/domain/transport/schemas.d.ts +10 -10
- package/dist/server/infra/context-tree/derived-artifact.js +5 -1
- package/dist/server/infra/context-tree/file-context-tree-manifest-service.d.ts +2 -1
- package/dist/server/infra/context-tree/file-context-tree-manifest-service.js +43 -7
- package/dist/server/infra/context-tree/file-context-tree-summary-service.js +20 -2
- package/dist/server/infra/executor/curate-executor.js +2 -1
- package/dist/server/infra/executor/folder-pack-executor.js +72 -2
- package/dist/server/infra/executor/query-executor.js +11 -3
- package/dist/server/infra/transport/handlers/status-handler.js +10 -0
- package/dist/server/utils/curate-result-parser.d.ts +4 -4
- package/dist/shared/transport/types/dto.d.ts +7 -0
- package/oclif.manifest.json +1 -1
- package/package.json +10 -4
|
@@ -9,6 +9,7 @@ export declare const ToolName: {
|
|
|
9
9
|
readonly EXPAND_KNOWLEDGE: 'expand_knowledge';
|
|
10
10
|
readonly GLOB_FILES: 'glob_files';
|
|
11
11
|
readonly GREP_CONTENT: 'grep_content';
|
|
12
|
+
readonly INGEST_RESOURCE: 'ingest_resource';
|
|
12
13
|
readonly LIST_DIRECTORY: 'list_directory';
|
|
13
14
|
readonly LLM_MAP: 'llm_map';
|
|
14
15
|
readonly READ_FILE: 'read_file';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentEventBus, SessionEventBus } from '../../infra/events/event-emitter.js';
|
|
2
2
|
import type { FileSystemService } from '../../infra/file-system/file-system-service.js';
|
|
3
3
|
import type { CompactionService } from '../../infra/llm/context/compaction/compaction-service.js';
|
|
4
|
+
import type { AbstractGenerationQueue } from '../../infra/map/abstract-queue.js';
|
|
4
5
|
import type { MemoryManager } from '../../infra/memory/memory-manager.js';
|
|
5
6
|
import type { ProcessService } from '../../infra/process/process-service.js';
|
|
6
7
|
import type { MessageStorageService } from '../../infra/storage/message-storage-service.js';
|
|
@@ -30,6 +31,11 @@ import type { IToolScheduler } from './i-tool-scheduler.js';
|
|
|
30
31
|
* - ToolProvider: Provides available tools
|
|
31
32
|
*/
|
|
32
33
|
export interface CipherAgentServices {
|
|
34
|
+
/**
|
|
35
|
+
* Background queue for generating L0/L1 abstract files (.abstract.md, .overview.md).
|
|
36
|
+
* Generator is injected lazily via setGenerator() from rebindCurateTools().
|
|
37
|
+
*/
|
|
38
|
+
abstractQueue: AbstractGenerationQueue;
|
|
33
39
|
agentEventBus: AgentEventBus;
|
|
34
40
|
blobStorage: IBlobStorage;
|
|
35
41
|
/**
|
|
@@ -50,6 +56,8 @@ export interface CipherAgentServices {
|
|
|
50
56
|
toolManager: ToolManager;
|
|
51
57
|
toolProvider: ToolProvider;
|
|
52
58
|
toolScheduler: IToolScheduler;
|
|
59
|
+
/** Absolute path to the project working directory. */
|
|
60
|
+
workingDirectory: string;
|
|
53
61
|
}
|
|
54
62
|
/**
|
|
55
63
|
* Session-specific services created per conversation session.
|
|
@@ -4,7 +4,6 @@ import { AgentErrorCode } from './agent-error-codes.js';
|
|
|
4
4
|
* Agent-specific error with typed error codes.
|
|
5
5
|
* Extends ExitError for oclif CLI integration.
|
|
6
6
|
*
|
|
7
|
-
* Follows DextoAgent pattern with static factory methods
|
|
8
7
|
* for creating well-typed errors.
|
|
9
8
|
*/
|
|
10
9
|
export declare class AgentError extends ExitError {
|
|
@@ -4,7 +4,6 @@ import { AgentErrorCode } from './agent-error-codes.js';
|
|
|
4
4
|
* Agent-specific error with typed error codes.
|
|
5
5
|
* Extends ExitError for oclif CLI integration.
|
|
6
6
|
*
|
|
7
|
-
* Follows DextoAgent pattern with static factory methods
|
|
8
7
|
* for creating well-typed errors.
|
|
9
8
|
*/
|
|
10
9
|
export class AgentError extends ExitError {
|
|
@@ -9,11 +9,9 @@ export interface SessionOverride {
|
|
|
9
9
|
llm?: Partial<ValidatedLLMConfig>;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Unified agent state manager combining DextoAgent config patterns with execution state tracking.
|
|
13
|
-
*
|
|
14
12
|
* Manages two concerns:
|
|
15
13
|
*
|
|
16
|
-
* 1. Configuration State
|
|
14
|
+
* 1. Configuration State:
|
|
17
15
|
* - baselineConfig: Original validated config, never mutated
|
|
18
16
|
* - runtimeConfig: Current active config, can be mutated
|
|
19
17
|
* - sessionOverrides: Per-session config overrides
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unified agent state manager combining DextoAgent config patterns with execution state tracking.
|
|
3
|
-
*
|
|
4
2
|
* Manages two concerns:
|
|
5
3
|
*
|
|
6
|
-
* 1. Configuration State
|
|
4
|
+
* 1. Configuration State:
|
|
7
5
|
* - baselineConfig: Original validated config, never mutated
|
|
8
6
|
* - runtimeConfig: Current active config, can be mutated
|
|
9
7
|
* - sessionOverrides: Per-session config overrides
|
|
@@ -3,7 +3,7 @@ import type { AgentEventBus } from '../events/event-emitter.js';
|
|
|
3
3
|
import { type LLMUpdates, type ValidatedAgentConfig, type ValidatedLLMConfig } from './agent-schemas.js';
|
|
4
4
|
import { AgentStateManager } from './agent-state-manager.js';
|
|
5
5
|
/**
|
|
6
|
-
* Abstract base agent class encapsulating
|
|
6
|
+
* Abstract base agent class encapsulating.
|
|
7
7
|
*
|
|
8
8
|
* Provides:
|
|
9
9
|
* - Two-phase initialization (constructor + start)
|
|
@@ -2,7 +2,7 @@ import { AgentError } from './agent-error.js';
|
|
|
2
2
|
import { AgentConfigSchema, LLMUpdatesSchema } from './agent-schemas.js';
|
|
3
3
|
import { AgentStateManager } from './agent-state-manager.js';
|
|
4
4
|
/**
|
|
5
|
-
* Abstract base agent class encapsulating
|
|
5
|
+
* Abstract base agent class encapsulating.
|
|
6
6
|
*
|
|
7
7
|
* Provides:
|
|
8
8
|
* - Two-phase initialization (constructor + start)
|
|
@@ -25,7 +25,7 @@ import { BaseAgent } from './base-agent.js';
|
|
|
25
25
|
* - Typed error handling
|
|
26
26
|
* - Configuration validation (Zod)
|
|
27
27
|
*
|
|
28
|
-
* Architecture
|
|
28
|
+
* Architecture:
|
|
29
29
|
* - Agent creates AgentEventBus in constructor (available before start)
|
|
30
30
|
* - Agent creates and owns shared services (ToolManager, SystemPromptManager, etc.)
|
|
31
31
|
* - SessionManager creates session-specific services (LLM, SessionEventBus)
|
|
@@ -57,7 +57,11 @@ export declare class CipherAgent extends BaseAgent implements ICipherAgent {
|
|
|
57
57
|
* Used for bulk deregistration on agent teardown (cleanupServices).
|
|
58
58
|
*/
|
|
59
59
|
private readonly rootEligibleSessions;
|
|
60
|
+
/** Lazily-created session compressor, rebuilt on each rebindCurateTools() call. */
|
|
61
|
+
private sessionCompressor?;
|
|
60
62
|
private sessionManager?;
|
|
63
|
+
/** Tracks user-facing task sessions for post-session memory extraction. */
|
|
64
|
+
private readonly userFacingTaskSessions;
|
|
61
65
|
/**
|
|
62
66
|
* Creates a new CipherAgent instance.
|
|
63
67
|
* Does NOT initialize services - call start() for async initialization.
|
|
@@ -114,6 +118,7 @@ export declare class CipherAgent extends BaseAgent implements ICipherAgent {
|
|
|
114
118
|
*/
|
|
115
119
|
createTaskSession(taskId: string, commandType: string, options?: {
|
|
116
120
|
mapRootEligible?: boolean;
|
|
121
|
+
userFacing?: boolean;
|
|
117
122
|
}): Promise<string>;
|
|
118
123
|
/**
|
|
119
124
|
* Delete a sandbox variable from the agent's default session.
|
|
@@ -131,6 +136,11 @@ export declare class CipherAgent extends BaseAgent implements ICipherAgent {
|
|
|
131
136
|
* Delete a task session and all its resources (sandbox + history).
|
|
132
137
|
*/
|
|
133
138
|
deleteTaskSession(sessionId: string): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Wait for shared background work (such as abstract generation) to finish.
|
|
141
|
+
* Used by task executors before reporting task completion.
|
|
142
|
+
*/
|
|
143
|
+
drainBackgroundWork(): Promise<void>;
|
|
134
144
|
/**
|
|
135
145
|
* Execute the agent with user input.
|
|
136
146
|
* Uses the agent's default session (created during start()).
|
|
@@ -260,6 +270,8 @@ export declare class CipherAgent extends BaseAgent implements ICipherAgent {
|
|
|
260
270
|
* Uses lazy providers when injected (child process mode), otherwise static config.
|
|
261
271
|
*/
|
|
262
272
|
private buildHttpConfig;
|
|
273
|
+
private createFreshRetryableGenerator;
|
|
274
|
+
private drainAbstractQueue;
|
|
263
275
|
private getHistoryStorageInternal;
|
|
264
276
|
private getSessionIdInternal;
|
|
265
277
|
private getSessionManagerInternal;
|
|
@@ -273,7 +285,9 @@ export declare class CipherAgent extends BaseAgent implements ICipherAgent {
|
|
|
273
285
|
* Rebuild map tool dependencies and update ToolProvider + SandboxService.
|
|
274
286
|
* Called from both start() (initial setup) and refreshProviderConfig() (hot-swap).
|
|
275
287
|
*/
|
|
288
|
+
private rebindCurateTools;
|
|
276
289
|
private rebindMapTools;
|
|
290
|
+
private refreshSessionCompressorFromTransport;
|
|
277
291
|
/**
|
|
278
292
|
* Register a session as root-eligible and track it for lifecycle cleanup.
|
|
279
293
|
* Routes all root-eligible registrations through a single point.
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { setMaxListeners } from 'node:events';
|
|
3
|
+
import { TransportStateEventNames } from '../../../server/core/domain/transport/schemas.js';
|
|
4
|
+
import { agentLog } from '../../../server/utils/process-logger.js';
|
|
3
5
|
import { getEffectiveMaxInputTokens, resolveRegistryProvider } from '../../core/domain/llm/index.js';
|
|
4
6
|
import { STREAMING_EVENT_NAMES } from '../../core/domain/streaming/types.js';
|
|
5
7
|
import { ToolName } from '../../core/domain/tools/constants.js';
|
|
6
8
|
import { AgentEventBus } from '../events/event-emitter.js';
|
|
9
|
+
import { RetryableContentGenerator } from '../llm/generators/index.js';
|
|
7
10
|
import { createGeneratorForProvider } from '../llm/providers/index.js';
|
|
11
|
+
import { DEFAULT_RETRY_POLICY } from '../llm/retry/retry-policy.js';
|
|
8
12
|
import { EventBasedLogger } from '../logger/event-based-logger.js';
|
|
9
13
|
import { deregisterRootEligibleSession, registerRootEligibleSession } from '../map/agentic-map-service.js';
|
|
14
|
+
import { MemoryDeduplicator } from '../memory/memory-deduplicator.js';
|
|
15
|
+
import { createCurateService } from '../sandbox/curate-service.js';
|
|
16
|
+
import { SessionCompressor } from '../session/session-compressor.js';
|
|
10
17
|
import { SessionManager } from '../session/session-manager.js';
|
|
11
18
|
import { TransportEventBridge } from '../transport/transport-event-bridge.js';
|
|
12
19
|
import { AgentError } from './agent-error.js';
|
|
13
20
|
import { BaseAgent } from './base-agent.js';
|
|
14
21
|
import { createCipherAgentServices } from './service-initializer.js';
|
|
22
|
+
const QUEUE_TRACE_ENABLED = process.env.BRV_QUEUE_TRACE === '1';
|
|
15
23
|
/**
|
|
16
24
|
* CipherAgent - Main agent implementation extending BaseAgent.
|
|
17
25
|
*
|
|
@@ -22,7 +30,7 @@ import { createCipherAgentServices } from './service-initializer.js';
|
|
|
22
30
|
* - Typed error handling
|
|
23
31
|
* - Configuration validation (Zod)
|
|
24
32
|
*
|
|
25
|
-
* Architecture
|
|
33
|
+
* Architecture:
|
|
26
34
|
* - Agent creates AgentEventBus in constructor (available before start)
|
|
27
35
|
* - Agent creates and owns shared services (ToolManager, SystemPromptManager, etc.)
|
|
28
36
|
* - SessionManager creates session-specific services (LLM, SessionEventBus)
|
|
@@ -55,7 +63,11 @@ export class CipherAgent extends BaseAgent {
|
|
|
55
63
|
* Used for bulk deregistration on agent teardown (cleanupServices).
|
|
56
64
|
*/
|
|
57
65
|
rootEligibleSessions = new Set();
|
|
66
|
+
/** Lazily-created session compressor, rebuilt on each rebindCurateTools() call. */
|
|
67
|
+
sessionCompressor;
|
|
58
68
|
sessionManager;
|
|
69
|
+
/** Tracks user-facing task sessions for post-session memory extraction. */
|
|
70
|
+
userFacingTaskSessions = new Set();
|
|
59
71
|
/**
|
|
60
72
|
* Creates a new CipherAgent instance.
|
|
61
73
|
* Does NOT initialize services - call start() for async initialization.
|
|
@@ -72,7 +84,7 @@ export class CipherAgent extends BaseAgent {
|
|
|
72
84
|
constructor(config, brvConfig, options) {
|
|
73
85
|
// Call parent constructor (validates with Zod)
|
|
74
86
|
super(config);
|
|
75
|
-
// Create event bus early (
|
|
87
|
+
// Create event bus early (available before start)
|
|
76
88
|
this._agentEventBus = new AgentEventBus();
|
|
77
89
|
this._brvConfig = brvConfig;
|
|
78
90
|
this._projectIdProvider = options?.projectIdProvider;
|
|
@@ -146,6 +158,8 @@ export class CipherAgent extends BaseAgent {
|
|
|
146
158
|
}
|
|
147
159
|
// === Public Methods (alphabetical order) ===
|
|
148
160
|
async cleanupServices() {
|
|
161
|
+
// Drain abstract generation queue before session disposal
|
|
162
|
+
await this.drainAbstractQueue();
|
|
149
163
|
// Abort all active streams and clear controllers
|
|
150
164
|
for (const controller of this.activeStreamControllers.values()) {
|
|
151
165
|
controller.abort();
|
|
@@ -207,6 +221,10 @@ export class CipherAgent extends BaseAgent {
|
|
|
207
221
|
if (options?.mapRootEligible) {
|
|
208
222
|
this.registerSessionInternal(childSession.id);
|
|
209
223
|
}
|
|
224
|
+
// Track user-facing sessions for post-session memory extraction.
|
|
225
|
+
if (options?.userFacing) {
|
|
226
|
+
this.userFacingTaskSessions.add(childSession.id);
|
|
227
|
+
}
|
|
210
228
|
return childSession.id;
|
|
211
229
|
}
|
|
212
230
|
/**
|
|
@@ -248,6 +266,38 @@ export class CipherAgent extends BaseAgent {
|
|
|
248
266
|
*/
|
|
249
267
|
async deleteTaskSession(sessionId) {
|
|
250
268
|
this.ensureStarted();
|
|
269
|
+
// Compress memories for user-facing sessions before disposal (fail-open).
|
|
270
|
+
if (this.userFacingTaskSessions.has(sessionId) && this.sessionCompressor) {
|
|
271
|
+
try {
|
|
272
|
+
// Refresh OAuth token and rebuild compressor before compression
|
|
273
|
+
if (this._transportClient && this.services) {
|
|
274
|
+
try {
|
|
275
|
+
await this.refreshSessionCompressorFromTransport();
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Fail-open: use existing compressor with potentially stale token
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const session = this.getSessionManagerInternal().getSession(sessionId);
|
|
282
|
+
if (session) {
|
|
283
|
+
const messages = session.getLLMService().getContextManager().getComprehensiveMessages();
|
|
284
|
+
const commandType = this.getSessionManagerInternal().getSessionCommandType(sessionId) ?? 'curate';
|
|
285
|
+
// Task sessions often contain a compact prompt/response trace, so use a
|
|
286
|
+
// lower threshold than the interactive default to preserve useful memories.
|
|
287
|
+
await this.sessionCompressor.compress(messages, commandType, { minMessages: 2 }).catch((error) => {
|
|
288
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
289
|
+
console.debug(`[CipherAgent] Session compression failed for ${sessionId}: ${msg}`);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
// Fail-open: synchronous errors in the session accessor chain (e.g. corrupted
|
|
295
|
+
// session state) must not prevent clearSession + deleteSession from running.
|
|
296
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
297
|
+
console.debug(`[CipherAgent] Session compression setup failed for ${sessionId}: ${msg}`);
|
|
298
|
+
}
|
|
299
|
+
this.userFacingTaskSessions.delete(sessionId);
|
|
300
|
+
}
|
|
251
301
|
await this.services.sandboxService.clearSession(sessionId);
|
|
252
302
|
await this.getSessionManagerInternal().deleteSession(sessionId);
|
|
253
303
|
// Deregister root-eligible record if this agent owns it.
|
|
@@ -258,6 +308,14 @@ export class CipherAgent extends BaseAgent {
|
|
|
258
308
|
this.rootEligibleSessions.delete(sessionId);
|
|
259
309
|
}
|
|
260
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* Wait for shared background work (such as abstract generation) to finish.
|
|
313
|
+
* Used by task executors before reporting task completion.
|
|
314
|
+
*/
|
|
315
|
+
async drainBackgroundWork() {
|
|
316
|
+
this.ensureStarted();
|
|
317
|
+
await this.drainAbstractQueue();
|
|
318
|
+
}
|
|
261
319
|
/**
|
|
262
320
|
* Execute the agent with user input.
|
|
263
321
|
* Uses the agent's default session (created during start()).
|
|
@@ -388,7 +446,7 @@ export class CipherAgent extends BaseAgent {
|
|
|
388
446
|
return this.getSystemPromptManagerInternal().build({});
|
|
389
447
|
}
|
|
390
448
|
async initializeServices() {
|
|
391
|
-
// Pass pre-created event bus to service initializer
|
|
449
|
+
// Pass pre-created event bus to service initializer
|
|
392
450
|
return createCipherAgentServices(this.config, this._agentEventBus);
|
|
393
451
|
}
|
|
394
452
|
/**
|
|
@@ -461,6 +519,8 @@ export class CipherAgent extends BaseAgent {
|
|
|
461
519
|
this.services.sandboxService.setSessionManager?.(this.sessionManager);
|
|
462
520
|
// Rebind map tools with fresh generator/tokenizer/maxContextTokens
|
|
463
521
|
this.rebindMapTools(services, httpConfig, sessionLLMConfig);
|
|
522
|
+
// Rebind curate tools with fresh generator + abstract queue
|
|
523
|
+
this.rebindCurateTools(services, httpConfig, sessionLLMConfig);
|
|
464
524
|
}
|
|
465
525
|
/**
|
|
466
526
|
* Reset the agent to initial state.
|
|
@@ -562,6 +622,8 @@ export class CipherAgent extends BaseAgent {
|
|
|
562
622
|
// Uses rebindMapTools() which atomically replaces map tools with fresh deps
|
|
563
623
|
// (generator, tokenizer, maxContextTokens, logger).
|
|
564
624
|
this.rebindMapTools(services, httpConfig, sessionLLMConfig);
|
|
625
|
+
// Wire abstract generation queue with curate generator + rebuild curate service.
|
|
626
|
+
this.rebindCurateTools(services, httpConfig, sessionLLMConfig);
|
|
565
627
|
// Create event bridge if transport client is injected (child process mode).
|
|
566
628
|
// The bridge forwards AgentEventBus llmservice:* events to the transport server.
|
|
567
629
|
if (this._transportClient) {
|
|
@@ -778,6 +840,64 @@ export class CipherAgent extends BaseAgent {
|
|
|
778
840
|
};
|
|
779
841
|
}
|
|
780
842
|
// === Private Helpers (alphabetical order) ===
|
|
843
|
+
createFreshRetryableGenerator(fresh, options) {
|
|
844
|
+
if (fresh.providerKeyMissing || !fresh.activeProvider) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
const provider = fresh.provider ?? (fresh.openRouterApiKey ? 'openrouter' : 'byterover');
|
|
848
|
+
const freshGenerator = createGeneratorForProvider(provider, {
|
|
849
|
+
apiKey: provider === 'openrouter'
|
|
850
|
+
? (fresh.openRouterApiKey ?? fresh.providerApiKey)
|
|
851
|
+
: fresh.providerApiKey,
|
|
852
|
+
baseUrl: fresh.providerBaseUrl,
|
|
853
|
+
headers: fresh.providerHeaders,
|
|
854
|
+
httpConfig: options.httpConfig,
|
|
855
|
+
httpReferer: options.httpReferer,
|
|
856
|
+
maxTokens: 4096,
|
|
857
|
+
model: fresh.activeModel ?? options.modelFallback,
|
|
858
|
+
siteName: options.siteName,
|
|
859
|
+
temperature: 0,
|
|
860
|
+
});
|
|
861
|
+
return new RetryableContentGenerator(freshGenerator, { policy: DEFAULT_RETRY_POLICY });
|
|
862
|
+
}
|
|
863
|
+
async drainAbstractQueue() {
|
|
864
|
+
const abstractQueue = this.services?.abstractQueue;
|
|
865
|
+
if (!abstractQueue) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
const settleDeadline = Date.now() + 5000;
|
|
869
|
+
let idleSince;
|
|
870
|
+
let pass = 0;
|
|
871
|
+
/* eslint-disable no-await-in-loop */
|
|
872
|
+
while (Date.now() <= settleDeadline) {
|
|
873
|
+
pass++;
|
|
874
|
+
if (QUEUE_TRACE_ENABLED) {
|
|
875
|
+
agentLog(`drainAbstractQueue:pass:${pass}:start`);
|
|
876
|
+
}
|
|
877
|
+
await abstractQueue.drain();
|
|
878
|
+
const status = abstractQueue.getStatus();
|
|
879
|
+
if (QUEUE_TRACE_ENABLED) {
|
|
880
|
+
agentLog(`drainAbstractQueue:pass:${pass}:status pending=${status.pending} processing=${status.processing} processed=${status.processed} failed=${status.failed}`);
|
|
881
|
+
}
|
|
882
|
+
if (!status.processing && status.pending === 0) {
|
|
883
|
+
idleSince ??= Date.now();
|
|
884
|
+
if (Date.now() - idleSince >= 250) {
|
|
885
|
+
if (QUEUE_TRACE_ENABLED) {
|
|
886
|
+
agentLog(`drainAbstractQueue:settled pass=${pass}`);
|
|
887
|
+
}
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
idleSince = undefined;
|
|
893
|
+
}
|
|
894
|
+
await new Promise((resolve) => { setTimeout(resolve, 100); });
|
|
895
|
+
}
|
|
896
|
+
/* eslint-enable no-await-in-loop */
|
|
897
|
+
if (QUEUE_TRACE_ENABLED) {
|
|
898
|
+
agentLog('drainAbstractQueue:deadline-reached');
|
|
899
|
+
}
|
|
900
|
+
}
|
|
781
901
|
getHistoryStorageInternal() {
|
|
782
902
|
const storage = this.services?.historyStorage;
|
|
783
903
|
if (!storage) {
|
|
@@ -818,6 +938,54 @@ export class CipherAgent extends BaseAgent {
|
|
|
818
938
|
* Rebuild map tool dependencies and update ToolProvider + SandboxService.
|
|
819
939
|
* Called from both start() (initial setup) and refreshProviderConfig() (hot-swap).
|
|
820
940
|
*/
|
|
941
|
+
rebindCurateTools(services, httpConfig, sessionLLMConfig) {
|
|
942
|
+
const curateProvider = sessionLLMConfig.provider
|
|
943
|
+
?? (sessionLLMConfig.openRouterApiKey ? 'openrouter' : 'byterover');
|
|
944
|
+
const curateGenerator = createGeneratorForProvider(curateProvider, {
|
|
945
|
+
apiKey: curateProvider === 'openrouter'
|
|
946
|
+
? (sessionLLMConfig.openRouterApiKey ?? sessionLLMConfig.providerApiKey)
|
|
947
|
+
: sessionLLMConfig.providerApiKey,
|
|
948
|
+
baseUrl: sessionLLMConfig.providerBaseUrl,
|
|
949
|
+
headers: sessionLLMConfig.providerHeaders,
|
|
950
|
+
httpConfig: httpConfig,
|
|
951
|
+
httpReferer: sessionLLMConfig.httpReferer,
|
|
952
|
+
maxTokens: 4096,
|
|
953
|
+
model: sessionLLMConfig.model,
|
|
954
|
+
siteName: sessionLLMConfig.siteName,
|
|
955
|
+
temperature: 0,
|
|
956
|
+
});
|
|
957
|
+
// Wrap with retry for background resilience (no event bus — background tasks have no UI)
|
|
958
|
+
const retryableCurateGenerator = new RetryableContentGenerator(curateGenerator, {
|
|
959
|
+
policy: DEFAULT_RETRY_POLICY,
|
|
960
|
+
});
|
|
961
|
+
// Wire generator into the abstract queue so background generation can proceed
|
|
962
|
+
services.abstractQueue.setGenerator(retryableCurateGenerator);
|
|
963
|
+
// Refresh OAuth token before each background generation (tokens expire between tasks)
|
|
964
|
+
if (this._transportClient) {
|
|
965
|
+
const transportClient = this._transportClient;
|
|
966
|
+
services.abstractQueue.setBeforeProcess(async () => {
|
|
967
|
+
const fresh = await transportClient.requestWithAck(TransportStateEventNames.GET_PROVIDER_CONFIG);
|
|
968
|
+
const retryableFreshGenerator = this.createFreshRetryableGenerator(fresh, {
|
|
969
|
+
httpConfig,
|
|
970
|
+
httpReferer: sessionLLMConfig.httpReferer,
|
|
971
|
+
modelFallback: sessionLLMConfig.model,
|
|
972
|
+
siteName: sessionLLMConfig.siteName,
|
|
973
|
+
});
|
|
974
|
+
if (!retryableFreshGenerator) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
services.abstractQueue.setGenerator(retryableFreshGenerator);
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
// Rebuild sandbox CurateService with the queue — reuses existing hot-swap path
|
|
981
|
+
const newCurateService = createCurateService(services.workingDirectory, services.abstractQueue);
|
|
982
|
+
services.sandboxService.setCurateService?.(newCurateService);
|
|
983
|
+
// Atomically rebuild CURATE + INGEST_RESOURCE tools so both enqueue abstracts
|
|
984
|
+
services.toolProvider.replaceTools([ToolName.CURATE, ToolName.INGEST_RESOURCE], { abstractQueue: services.abstractQueue, contentGenerator: retryableCurateGenerator });
|
|
985
|
+
// Rebuild session compressor with the new generator (used in deleteTaskSession)
|
|
986
|
+
const deduplicator = new MemoryDeduplicator(retryableCurateGenerator);
|
|
987
|
+
this.sessionCompressor = new SessionCompressor(deduplicator, retryableCurateGenerator, services.memoryManager);
|
|
988
|
+
}
|
|
821
989
|
rebindMapTools(services, httpConfig, sessionLLMConfig) {
|
|
822
990
|
const mapProvider = sessionLLMConfig.provider
|
|
823
991
|
?? (sessionLLMConfig.openRouterApiKey ? 'openrouter' : 'byterover');
|
|
@@ -855,6 +1023,23 @@ export class CipherAgent extends BaseAgent {
|
|
|
855
1023
|
// Update sandbox for tools.curation.mapExtract()
|
|
856
1024
|
services.sandboxService.setContentGenerator?.(mapGenerator);
|
|
857
1025
|
}
|
|
1026
|
+
async refreshSessionCompressorFromTransport() {
|
|
1027
|
+
if (!this._transportClient || !this.services) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const fresh = await this._transportClient.requestWithAck(TransportStateEventNames.GET_PROVIDER_CONFIG);
|
|
1031
|
+
const retryable = this.createFreshRetryableGenerator(fresh, {
|
|
1032
|
+
httpConfig: this.buildHttpConfig(),
|
|
1033
|
+
httpReferer: this.config.httpReferer,
|
|
1034
|
+
modelFallback: this.stateManager?.getModel() ?? this.config.model,
|
|
1035
|
+
siteName: this.config.siteName,
|
|
1036
|
+
});
|
|
1037
|
+
if (!retryable) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
const deduplicator = new MemoryDeduplicator(retryable);
|
|
1041
|
+
this.sessionCompressor = new SessionCompressor(deduplicator, retryable, this.services.memoryManager);
|
|
1042
|
+
}
|
|
858
1043
|
/**
|
|
859
1044
|
* Register a session as root-eligible and track it for lifecycle cleanup.
|
|
860
1045
|
* Routes all root-eligible registrations through a single point.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This module is responsible for initializing and wiring together all core agent services.
|
|
5
5
|
* It provides a single entry point for constructing the service graph.
|
|
6
6
|
*
|
|
7
|
-
* Following
|
|
7
|
+
* Following pattern:
|
|
8
8
|
* - Config file is source of truth (ValidatedAgentConfig)
|
|
9
9
|
* - Centralized function (not factory class) for service creation
|
|
10
10
|
* - Explicit dependency order with numbered steps
|
|
@@ -61,7 +61,7 @@ export type { CipherAgentServices, SessionManagerConfig, SessionServices } from
|
|
|
61
61
|
* Creates shared services for CipherAgent.
|
|
62
62
|
* These services are singletons shared across all sessions.
|
|
63
63
|
*
|
|
64
|
-
* Initialization order
|
|
64
|
+
* Initialization order (explicit numbered steps):
|
|
65
65
|
* 1. Logger (uses provided event bus)
|
|
66
66
|
* 2. File system service (no dependencies)
|
|
67
67
|
* 3. Process service (no dependencies)
|
|
@@ -76,7 +76,7 @@ export type { CipherAgentServices, SessionManagerConfig, SessionServices } from
|
|
|
76
76
|
* 12. Return all services
|
|
77
77
|
*
|
|
78
78
|
* @param config - Validated agent configuration (Zod-validated)
|
|
79
|
-
* @param agentEventBus - Pre-created event bus from agent constructor
|
|
79
|
+
* @param agentEventBus - Pre-created event bus from agent constructor
|
|
80
80
|
* @returns Initialized shared services
|
|
81
81
|
*/
|
|
82
82
|
export declare function createCipherAgentServices(config: ValidatedAgentConfig, agentEventBus: AgentEventBus): Promise<CipherAgentServices>;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This module is responsible for initializing and wiring together all core agent services.
|
|
5
5
|
* It provides a single entry point for constructing the service graph.
|
|
6
6
|
*
|
|
7
|
-
* Following
|
|
7
|
+
* Following pattern:
|
|
8
8
|
* - Config file is source of truth (ValidatedAgentConfig)
|
|
9
9
|
* - Centralized function (not factory class) for service creation
|
|
10
10
|
* - Explicit dependency order with numbered steps
|
|
@@ -26,6 +26,7 @@ import { createGeneratorForProvider } from '../llm/providers/index.js';
|
|
|
26
26
|
import { DEFAULT_RETRY_POLICY } from '../llm/retry/retry-policy.js';
|
|
27
27
|
import { GeminiTokenizer } from '../llm/tokenizers/gemini-tokenizer.js';
|
|
28
28
|
import { EventBasedLogger } from '../logger/event-based-logger.js';
|
|
29
|
+
import { AbstractGenerationQueue } from '../map/abstract-queue.js';
|
|
29
30
|
import { MemoryManager } from '../memory/memory-manager.js';
|
|
30
31
|
import { ProcessService } from '../process/process-service.js';
|
|
31
32
|
import { SandboxService } from '../sandbox/sandbox-service.js';
|
|
@@ -45,7 +46,7 @@ import { ToolProvider } from '../tools/tool-provider.js';
|
|
|
45
46
|
* Creates shared services for CipherAgent.
|
|
46
47
|
* These services are singletons shared across all sessions.
|
|
47
48
|
*
|
|
48
|
-
* Initialization order
|
|
49
|
+
* Initialization order (explicit numbered steps):
|
|
49
50
|
* 1. Logger (uses provided event bus)
|
|
50
51
|
* 2. File system service (no dependencies)
|
|
51
52
|
* 3. Process service (no dependencies)
|
|
@@ -60,11 +61,11 @@ import { ToolProvider } from '../tools/tool-provider.js';
|
|
|
60
61
|
* 12. Return all services
|
|
61
62
|
*
|
|
62
63
|
* @param config - Validated agent configuration (Zod-validated)
|
|
63
|
-
* @param agentEventBus - Pre-created event bus from agent constructor
|
|
64
|
+
* @param agentEventBus - Pre-created event bus from agent constructor
|
|
64
65
|
* @returns Initialized shared services
|
|
65
66
|
*/
|
|
66
67
|
export async function createCipherAgentServices(config, agentEventBus) {
|
|
67
|
-
// 1. Logger (uses provided event bus
|
|
68
|
+
// 1. Logger (uses provided event bus )
|
|
68
69
|
const logger = new EventBasedLogger(agentEventBus, 'CipherAgent');
|
|
69
70
|
// 2. File system service (no dependencies)
|
|
70
71
|
const fileSystemService = new FileSystemService(config.fileSystem);
|
|
@@ -132,10 +133,13 @@ export async function createCipherAgentServices(config, agentEventBus) {
|
|
|
132
133
|
// Priority 16 — right after context tree structure, before memories
|
|
133
134
|
const mapSelectionContributor = new MapSelectionContributor('mapSelection', 16);
|
|
134
135
|
systemPromptManager.registerContributor(mapSelectionContributor);
|
|
135
|
-
// 7.
|
|
136
|
+
// 7. Abstract generation queue (generator injected later via rebindCurateTools)
|
|
137
|
+
const abstractQueue = new AbstractGenerationQueue(workingDirectory);
|
|
138
|
+
// 8. Tool provider (depends on FileSystemService, ProcessService, MemoryManager, SystemPromptManager)
|
|
136
139
|
const verbose = config.llm.verbose ?? false;
|
|
137
140
|
const descriptionLoader = new ToolDescriptionLoader();
|
|
138
141
|
const toolProvider = new ToolProvider({
|
|
142
|
+
abstractQueue,
|
|
139
143
|
environmentContext,
|
|
140
144
|
fileSystemService,
|
|
141
145
|
getToolProvider: () => toolProvider,
|
|
@@ -144,14 +148,14 @@ export async function createCipherAgentServices(config, agentEventBus) {
|
|
|
144
148
|
sandboxService,
|
|
145
149
|
}, systemPromptManager, descriptionLoader);
|
|
146
150
|
await toolProvider.initialize();
|
|
147
|
-
//
|
|
151
|
+
// 9. Policy engine with default rules for autonomous execution
|
|
148
152
|
const policyEngine = new PolicyEngine({ defaultDecision: 'ALLOW' });
|
|
149
153
|
policyEngine.addRules(DEFAULT_POLICY_RULES);
|
|
150
|
-
//
|
|
154
|
+
// 10. Tool scheduler (orchestrates policy check → execution)
|
|
151
155
|
const toolScheduler = new CoreToolScheduler(toolProvider, policyEngine, undefined, {
|
|
152
156
|
verbose,
|
|
153
157
|
});
|
|
154
|
-
//
|
|
158
|
+
// 11. Tool manager (with scheduler for policy-based execution)
|
|
155
159
|
const toolManager = new ToolManager(toolProvider, toolScheduler);
|
|
156
160
|
await toolManager.initialize();
|
|
157
161
|
// 11. History storage - granular file-based storage
|
|
@@ -177,6 +181,7 @@ export async function createCipherAgentServices(config, agentEventBus) {
|
|
|
177
181
|
workingDirectory,
|
|
178
182
|
});
|
|
179
183
|
return {
|
|
184
|
+
abstractQueue,
|
|
180
185
|
agentEventBus,
|
|
181
186
|
blobStorage,
|
|
182
187
|
compactionService,
|
|
@@ -191,6 +196,7 @@ export async function createCipherAgentServices(config, agentEventBus) {
|
|
|
191
196
|
toolManager,
|
|
192
197
|
toolProvider,
|
|
193
198
|
toolScheduler,
|
|
199
|
+
workingDirectory,
|
|
194
200
|
};
|
|
195
201
|
}
|
|
196
202
|
/**
|
|
@@ -19,7 +19,6 @@ export interface AgentExecutionContext {
|
|
|
19
19
|
/**
|
|
20
20
|
* Agent event subscriber interface.
|
|
21
21
|
* Objects implementing this can be registered for event subscription.
|
|
22
|
-
* Follows DextoAgent's AgentEventSubscriber pattern.
|
|
23
22
|
*/
|
|
24
23
|
export interface AgentEventSubscriber {
|
|
25
24
|
/**
|