@sudocode-ai/claude-code-acp 0.13.1 → 0.13.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/README.md +1 -1
- package/dist/acp-agent.d.ts +88 -10
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +172 -9
- package/dist/lib.d.ts +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ This tool implements an ACP agent by using the official [Claude Agent SDK](https
|
|
|
10
10
|
- Images
|
|
11
11
|
- Tool calls (with permission requests)
|
|
12
12
|
- Following
|
|
13
|
-
- Edit
|
|
13
|
+
- Edit reviewddddd
|
|
14
14
|
- TODO lists
|
|
15
15
|
- Interactive (and background) terminals
|
|
16
16
|
- Custom [Slash commands](https://docs.anthropic.com/en/docs/claude-code/slash-commands)
|
package/dist/acp-agent.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Agent, AgentSideConnection, AuthenticateRequest, CancelNotification, ClientCapabilities, ForkSessionRequest, ForkSessionResponse, InitializeRequest, InitializeResponse, LoadSessionRequest, LoadSessionResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, ReadTextFileRequest, ReadTextFileResponse, SessionNotification, SetSessionModelRequest, SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, TerminalHandle, TerminalOutputResponse, WriteTextFileRequest, WriteTextFileResponse } from "@agentclientprotocol/sdk";
|
|
1
|
+
import { Agent, AgentSideConnection, AuthenticateRequest, CancelNotification, ClientCapabilities, ForkSessionRequest, ForkSessionResponse, InitializeRequest, InitializeResponse, LoadSessionRequest, LoadSessionResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, ReadTextFileRequest, ReadTextFileResponse, ResumeSessionRequest, ResumeSessionResponse, SessionNotification, SetSessionModelRequest, SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, TerminalHandle, TerminalOutputResponse, WriteTextFileRequest, WriteTextFileResponse } from "@agentclientprotocol/sdk";
|
|
2
2
|
import { SettingsManager } from "./settings.js";
|
|
3
3
|
import { CanUseTool, Options, PermissionMode, Query, SDKPartialAssistantMessage, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
|
|
4
4
|
import { Pushable } from "./utils.js";
|
|
@@ -12,6 +12,21 @@ export interface Logger {
|
|
|
12
12
|
log: (...args: any[]) => void;
|
|
13
13
|
error: (...args: any[]) => void;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Internal state for tracking compaction.
|
|
17
|
+
*/
|
|
18
|
+
type CompactionState = {
|
|
19
|
+
/** Whether auto-compaction is enabled for this session */
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
/** Token threshold that triggers compaction */
|
|
22
|
+
threshold: number;
|
|
23
|
+
/** Custom instructions for compaction summary */
|
|
24
|
+
customInstructions?: string;
|
|
25
|
+
/** Current total token count for this session */
|
|
26
|
+
currentTokens: number;
|
|
27
|
+
/** Whether a compaction is currently in progress */
|
|
28
|
+
isCompacting: boolean;
|
|
29
|
+
};
|
|
15
30
|
type Session = {
|
|
16
31
|
query: Query;
|
|
17
32
|
input: Pushable<SDKUserMessage>;
|
|
@@ -22,6 +37,8 @@ type Session = {
|
|
|
22
37
|
cwd: string;
|
|
23
38
|
/** Optional: the actual session file path (for forked sessions where filename differs from sessionId) */
|
|
24
39
|
sessionFilePath?: string;
|
|
40
|
+
/** Auto-compaction state tracking */
|
|
41
|
+
compaction: CompactionState;
|
|
25
42
|
};
|
|
26
43
|
type BackgroundTerminal = {
|
|
27
44
|
handle: TerminalHandle;
|
|
@@ -31,6 +48,28 @@ type BackgroundTerminal = {
|
|
|
31
48
|
status: "aborted" | "exited" | "killed" | "timedOut";
|
|
32
49
|
pendingOutput: TerminalOutputResponse;
|
|
33
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* Configuration for automatic context compaction.
|
|
53
|
+
* When enabled, the session will automatically trigger compaction when token usage exceeds the threshold.
|
|
54
|
+
*/
|
|
55
|
+
export type CompactionConfig = {
|
|
56
|
+
/**
|
|
57
|
+
* Whether automatic compaction is enabled.
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
enabled: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Token threshold that triggers automatic compaction.
|
|
63
|
+
* When the total token count exceeds this value, a /compact command is automatically sent.
|
|
64
|
+
* @default 100000
|
|
65
|
+
*/
|
|
66
|
+
contextTokenThreshold?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Optional custom instructions for the compaction summary.
|
|
69
|
+
* These instructions guide how Claude summarizes the conversation.
|
|
70
|
+
*/
|
|
71
|
+
customInstructions?: string;
|
|
72
|
+
};
|
|
34
73
|
/**
|
|
35
74
|
* Extra metadata that can be given to Claude Code when creating a new session.
|
|
36
75
|
*/
|
|
@@ -50,6 +89,11 @@ export type NewSessionMeta = {
|
|
|
50
89
|
* - mcpServers (merged with ACP's mcpServers)
|
|
51
90
|
*/
|
|
52
91
|
options?: Options;
|
|
92
|
+
/**
|
|
93
|
+
* Configuration for automatic context compaction.
|
|
94
|
+
* When enabled, automatically triggers /compact when token usage exceeds the threshold.
|
|
95
|
+
*/
|
|
96
|
+
compaction?: CompactionConfig;
|
|
53
97
|
};
|
|
54
98
|
};
|
|
55
99
|
/**
|
|
@@ -125,16 +169,9 @@ export declare class ClaudeAcpAgent implements Agent {
|
|
|
125
169
|
*/
|
|
126
170
|
loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse>;
|
|
127
171
|
/**
|
|
128
|
-
*
|
|
172
|
+
* Resume an existing session. This delegates to loadSession for enhanced functionality.
|
|
129
173
|
*/
|
|
130
|
-
unstable_resumeSession(params:
|
|
131
|
-
sessionId: string;
|
|
132
|
-
_meta?: {
|
|
133
|
-
cwd?: string;
|
|
134
|
-
mcpServers?: any[];
|
|
135
|
-
[key: string]: unknown;
|
|
136
|
-
} | null;
|
|
137
|
-
}): Promise<LoadSessionResponse>;
|
|
174
|
+
unstable_resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse>;
|
|
138
175
|
authenticate(_params: AuthenticateRequest): Promise<void>;
|
|
139
176
|
prompt(params: PromptRequest): Promise<PromptResponse>;
|
|
140
177
|
cancel(params: CancelNotification): Promise<void>;
|
|
@@ -142,9 +179,42 @@ export declare class ClaudeAcpAgent implements Agent {
|
|
|
142
179
|
* Handle extension methods from the client.
|
|
143
180
|
*
|
|
144
181
|
* Currently supports:
|
|
182
|
+
* - `_session/inject`: Inject a message into an active session mid-execution
|
|
145
183
|
* - `_session/flush`: Flush a session to disk for fork-with-flush support
|
|
184
|
+
* - `_session/setCompaction`: Configure automatic context compaction for a session
|
|
146
185
|
*/
|
|
147
186
|
extMethod(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
187
|
+
/**
|
|
188
|
+
* Inject a message into an active session.
|
|
189
|
+
*
|
|
190
|
+
* This allows sending additional user input while a prompt() call is actively
|
|
191
|
+
* processing. The injected message will be queued and processed by the agent
|
|
192
|
+
* as part of the current conversation turn.
|
|
193
|
+
*
|
|
194
|
+
* Use cases:
|
|
195
|
+
* - Providing clarification while the agent is working
|
|
196
|
+
* - Adding context mid-execution
|
|
197
|
+
* - Sending corrections before a tool completes
|
|
198
|
+
*
|
|
199
|
+
* @param params.sessionId - The session to inject the message into
|
|
200
|
+
* @param params.message - Either a string or an array of ContentBlocks (same format as prompt)
|
|
201
|
+
* @returns Success status and any error message
|
|
202
|
+
*/
|
|
203
|
+
private handleSessionInject;
|
|
204
|
+
/**
|
|
205
|
+
* Configure automatic context compaction for a session.
|
|
206
|
+
*
|
|
207
|
+
* When enabled, the session will automatically trigger compaction when token usage
|
|
208
|
+
* exceeds the configured threshold. This helps manage context window limits during
|
|
209
|
+
* long-running conversations.
|
|
210
|
+
*
|
|
211
|
+
* @param params.sessionId - The session to configure
|
|
212
|
+
* @param params.enabled - Whether automatic compaction is enabled
|
|
213
|
+
* @param params.contextTokenThreshold - Token count that triggers compaction (default: 100000)
|
|
214
|
+
* @param params.customInstructions - Optional instructions for the compaction summary
|
|
215
|
+
* @returns Success status and any error message
|
|
216
|
+
*/
|
|
217
|
+
private handleSessionSetCompaction;
|
|
148
218
|
/**
|
|
149
219
|
* Flush a session to disk by aborting its query subprocess.
|
|
150
220
|
*
|
|
@@ -180,6 +250,14 @@ export declare class ClaudeAcpAgent implements Agent {
|
|
|
180
250
|
readTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse>;
|
|
181
251
|
writeTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse>;
|
|
182
252
|
canUseTool(sessionId: string): CanUseTool;
|
|
253
|
+
/**
|
|
254
|
+
* Check if auto-compaction should be triggered based on current token usage.
|
|
255
|
+
*/
|
|
256
|
+
private shouldTriggerCompaction;
|
|
257
|
+
/**
|
|
258
|
+
* Trigger automatic compaction by sending a /compact command.
|
|
259
|
+
*/
|
|
260
|
+
private triggerAutoCompaction;
|
|
183
261
|
private createSession;
|
|
184
262
|
}
|
|
185
263
|
export declare function promptToClaude(prompt: PromptRequest): SDKUserMessage;
|
package/dist/acp-agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,mBAAmB,EACnB,mBAAmB,EAEnB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EAEnB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
|
package/dist/acp-agent.js
CHANGED
|
@@ -331,16 +331,17 @@ export class ClaudeAcpAgent {
|
|
|
331
331
|
return response;
|
|
332
332
|
}
|
|
333
333
|
/**
|
|
334
|
-
*
|
|
334
|
+
* Resume an existing session. This delegates to loadSession for enhanced functionality.
|
|
335
335
|
*/
|
|
336
336
|
async unstable_resumeSession(params) {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
cwd: meta?.cwd ?? process.cwd(),
|
|
341
|
-
mcpServers: meta?.mcpServers ?? [],
|
|
337
|
+
const response = await this.createSession({
|
|
338
|
+
cwd: params.cwd,
|
|
339
|
+
mcpServers: params.mcpServers ?? [],
|
|
342
340
|
_meta: params._meta,
|
|
341
|
+
}, {
|
|
342
|
+
resume: params.sessionId,
|
|
343
343
|
});
|
|
344
|
+
return response;
|
|
344
345
|
}
|
|
345
346
|
async authenticate(_params) {
|
|
346
347
|
throw new Error("Method not implemented.");
|
|
@@ -365,7 +366,16 @@ export class ClaudeAcpAgent {
|
|
|
365
366
|
switch (message.subtype) {
|
|
366
367
|
case "init":
|
|
367
368
|
break;
|
|
368
|
-
case "compact_boundary":
|
|
369
|
+
case "compact_boundary": {
|
|
370
|
+
// Reset token count after compaction
|
|
371
|
+
const session = this.sessions[params.sessionId];
|
|
372
|
+
if (session) {
|
|
373
|
+
session.compaction.currentTokens = 0;
|
|
374
|
+
session.compaction.isCompacting = false;
|
|
375
|
+
this.logger.log(`[auto-compaction] Compaction completed, token count reset. Previous tokens: ${message.compact_metadata.pre_tokens}`);
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
369
379
|
case "hook_response":
|
|
370
380
|
case "status":
|
|
371
381
|
// Todo: process via status api: https://docs.claude.com/en/docs/claude-code/hooks#hook-output
|
|
@@ -379,6 +389,15 @@ export class ClaudeAcpAgent {
|
|
|
379
389
|
if (this.sessions[params.sessionId].cancelled) {
|
|
380
390
|
return { stopReason: "cancelled" };
|
|
381
391
|
}
|
|
392
|
+
// Track token usage for auto-compaction
|
|
393
|
+
const session = this.sessions[params.sessionId];
|
|
394
|
+
if (session && message.usage) {
|
|
395
|
+
const totalTokens = message.usage.input_tokens +
|
|
396
|
+
message.usage.output_tokens +
|
|
397
|
+
(message.usage.cache_creation_input_tokens ?? 0) +
|
|
398
|
+
(message.usage.cache_read_input_tokens ?? 0);
|
|
399
|
+
session.compaction.currentTokens += totalTokens;
|
|
400
|
+
}
|
|
382
401
|
switch (message.subtype) {
|
|
383
402
|
case "success": {
|
|
384
403
|
if (message.result.includes("Please run /login")) {
|
|
@@ -387,6 +406,11 @@ export class ClaudeAcpAgent {
|
|
|
387
406
|
if (message.is_error) {
|
|
388
407
|
throw RequestError.internalError(undefined, message.result);
|
|
389
408
|
}
|
|
409
|
+
// Check if auto-compaction should be triggered
|
|
410
|
+
if (session && await this.shouldTriggerCompaction(params.sessionId)) {
|
|
411
|
+
await this.triggerAutoCompaction(params.sessionId);
|
|
412
|
+
// Continue processing - the compaction will happen in the background
|
|
413
|
+
}
|
|
390
414
|
return { stopReason: "end_turn" };
|
|
391
415
|
}
|
|
392
416
|
case "error_during_execution":
|
|
@@ -477,14 +501,103 @@ export class ClaudeAcpAgent {
|
|
|
477
501
|
* Handle extension methods from the client.
|
|
478
502
|
*
|
|
479
503
|
* Currently supports:
|
|
504
|
+
* - `_session/inject`: Inject a message into an active session mid-execution
|
|
480
505
|
* - `_session/flush`: Flush a session to disk for fork-with-flush support
|
|
506
|
+
* - `_session/setCompaction`: Configure automatic context compaction for a session
|
|
481
507
|
*/
|
|
482
508
|
async extMethod(method, params) {
|
|
509
|
+
if (method === "_session/inject") {
|
|
510
|
+
return this.handleSessionInject(params);
|
|
511
|
+
}
|
|
483
512
|
if (method === "_session/flush") {
|
|
484
513
|
return this.handleSessionFlush(params);
|
|
485
514
|
}
|
|
515
|
+
if (method === "_session/setCompaction") {
|
|
516
|
+
return this.handleSessionSetCompaction(params);
|
|
517
|
+
}
|
|
486
518
|
throw RequestError.methodNotFound(method);
|
|
487
519
|
}
|
|
520
|
+
/**
|
|
521
|
+
* Inject a message into an active session.
|
|
522
|
+
*
|
|
523
|
+
* This allows sending additional user input while a prompt() call is actively
|
|
524
|
+
* processing. The injected message will be queued and processed by the agent
|
|
525
|
+
* as part of the current conversation turn.
|
|
526
|
+
*
|
|
527
|
+
* Use cases:
|
|
528
|
+
* - Providing clarification while the agent is working
|
|
529
|
+
* - Adding context mid-execution
|
|
530
|
+
* - Sending corrections before a tool completes
|
|
531
|
+
*
|
|
532
|
+
* @param params.sessionId - The session to inject the message into
|
|
533
|
+
* @param params.message - Either a string or an array of ContentBlocks (same format as prompt)
|
|
534
|
+
* @returns Success status and any error message
|
|
535
|
+
*/
|
|
536
|
+
handleSessionInject(params) {
|
|
537
|
+
const { sessionId, message } = params;
|
|
538
|
+
const session = this.sessions[sessionId];
|
|
539
|
+
if (!session) {
|
|
540
|
+
return { success: false, error: `Session ${sessionId} not found` };
|
|
541
|
+
}
|
|
542
|
+
if (session.cancelled) {
|
|
543
|
+
return { success: false, error: `Session ${sessionId} is cancelled` };
|
|
544
|
+
}
|
|
545
|
+
try {
|
|
546
|
+
// Convert string to ContentBlock array if needed
|
|
547
|
+
const prompt = typeof message === "string" ? [{ type: "text", text: message }] : message;
|
|
548
|
+
// Create a PromptRequest-like object to reuse promptToClaude
|
|
549
|
+
const promptRequest = {
|
|
550
|
+
sessionId,
|
|
551
|
+
prompt,
|
|
552
|
+
};
|
|
553
|
+
// Convert to SDK format and push to the session's input queue
|
|
554
|
+
const sdkMessage = promptToClaude(promptRequest);
|
|
555
|
+
session.input.push(sdkMessage);
|
|
556
|
+
this.logger.log(`[claude-code-acp] Injected message into session ${sessionId}`);
|
|
557
|
+
return { success: true };
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
this.logger.error(`[claude-code-acp] Failed to inject message into session ${sessionId}:`, error);
|
|
561
|
+
return { success: false, error: String(error) };
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Configure automatic context compaction for a session.
|
|
566
|
+
*
|
|
567
|
+
* When enabled, the session will automatically trigger compaction when token usage
|
|
568
|
+
* exceeds the configured threshold. This helps manage context window limits during
|
|
569
|
+
* long-running conversations.
|
|
570
|
+
*
|
|
571
|
+
* @param params.sessionId - The session to configure
|
|
572
|
+
* @param params.enabled - Whether automatic compaction is enabled
|
|
573
|
+
* @param params.contextTokenThreshold - Token count that triggers compaction (default: 100000)
|
|
574
|
+
* @param params.customInstructions - Optional instructions for the compaction summary
|
|
575
|
+
* @returns Success status and any error message
|
|
576
|
+
*/
|
|
577
|
+
handleSessionSetCompaction(params) {
|
|
578
|
+
const { sessionId, enabled, contextTokenThreshold, customInstructions } = params;
|
|
579
|
+
const session = this.sessions[sessionId];
|
|
580
|
+
if (!session) {
|
|
581
|
+
return { success: false, error: `Session ${sessionId} not found` };
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
// Update the session's compaction configuration
|
|
585
|
+
session.compaction.enabled = enabled;
|
|
586
|
+
if (contextTokenThreshold !== undefined) {
|
|
587
|
+
session.compaction.threshold = contextTokenThreshold;
|
|
588
|
+
}
|
|
589
|
+
if (customInstructions !== undefined) {
|
|
590
|
+
session.compaction.customInstructions = customInstructions;
|
|
591
|
+
}
|
|
592
|
+
this.logger.log(`[claude-code-acp] Updated compaction config for session ${sessionId}: ` +
|
|
593
|
+
`enabled=${enabled}, threshold=${session.compaction.threshold}`);
|
|
594
|
+
return { success: true };
|
|
595
|
+
}
|
|
596
|
+
catch (error) {
|
|
597
|
+
this.logger.error(`[claude-code-acp] Failed to set compaction config for session ${sessionId}:`, error);
|
|
598
|
+
return { success: false, error: String(error) };
|
|
599
|
+
}
|
|
600
|
+
}
|
|
488
601
|
/**
|
|
489
602
|
* Flush a session to disk by aborting its query subprocess.
|
|
490
603
|
*
|
|
@@ -728,6 +841,48 @@ export class ClaudeAcpAgent {
|
|
|
728
841
|
}
|
|
729
842
|
};
|
|
730
843
|
}
|
|
844
|
+
/**
|
|
845
|
+
* Check if auto-compaction should be triggered based on current token usage.
|
|
846
|
+
*/
|
|
847
|
+
async shouldTriggerCompaction(sessionId) {
|
|
848
|
+
const session = this.sessions[sessionId];
|
|
849
|
+
if (!session)
|
|
850
|
+
return false;
|
|
851
|
+
const { compaction } = session;
|
|
852
|
+
// Check if auto-compaction is enabled and not already in progress
|
|
853
|
+
if (!compaction.enabled || compaction.isCompacting) {
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
// Check if current tokens exceed threshold
|
|
857
|
+
return compaction.currentTokens >= compaction.threshold;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Trigger automatic compaction by sending a /compact command.
|
|
861
|
+
*/
|
|
862
|
+
async triggerAutoCompaction(sessionId) {
|
|
863
|
+
const session = this.sessions[sessionId];
|
|
864
|
+
if (!session)
|
|
865
|
+
return;
|
|
866
|
+
const { compaction, input } = session;
|
|
867
|
+
// Mark compaction as in progress to prevent multiple triggers
|
|
868
|
+
compaction.isCompacting = true;
|
|
869
|
+
this.logger.log(`[auto-compaction] Triggering compaction. Current tokens: ${compaction.currentTokens}, Threshold: ${compaction.threshold}`);
|
|
870
|
+
// Build the compact command with optional custom instructions
|
|
871
|
+
const compactCommand = compaction.customInstructions
|
|
872
|
+
? `/compact ${compaction.customInstructions}`
|
|
873
|
+
: "/compact";
|
|
874
|
+
// Inject the compact command as a user message
|
|
875
|
+
const compactMessage = {
|
|
876
|
+
type: "user",
|
|
877
|
+
message: {
|
|
878
|
+
role: "user",
|
|
879
|
+
content: [{ type: "text", text: compactCommand }],
|
|
880
|
+
},
|
|
881
|
+
session_id: sessionId,
|
|
882
|
+
parent_tool_use_id: null,
|
|
883
|
+
};
|
|
884
|
+
input.push(compactMessage);
|
|
885
|
+
}
|
|
731
886
|
async createSession(params, creationOpts = {}) {
|
|
732
887
|
// We want to create a new session id unless it is resume,
|
|
733
888
|
// but not resume + forkSession.
|
|
@@ -797,8 +952,6 @@ export class ClaudeAcpAgent {
|
|
|
797
952
|
const extraArgs = { ...userProvidedOptions?.extraArgs };
|
|
798
953
|
if (creationOpts?.resume === undefined || creationOpts?.forkSession) {
|
|
799
954
|
// Set our own session id if not resuming an existing session.
|
|
800
|
-
// Note: For forked sessions (resume + fork), Claude CLI assigns its own session ID
|
|
801
|
-
// which means chain forking (fork of a fork) is not currently supported.
|
|
802
955
|
extraArgs["session-id"] = sessionId;
|
|
803
956
|
}
|
|
804
957
|
// Configure thinking tokens from environment variable
|
|
@@ -886,6 +1039,15 @@ export class ClaudeAcpAgent {
|
|
|
886
1039
|
prompt: input,
|
|
887
1040
|
options,
|
|
888
1041
|
});
|
|
1042
|
+
// Extract compaction config from _meta if provided
|
|
1043
|
+
const compactionConfig = params._meta?.claudeCode?.compaction;
|
|
1044
|
+
const compactionState = {
|
|
1045
|
+
enabled: compactionConfig?.enabled ?? false,
|
|
1046
|
+
threshold: compactionConfig?.contextTokenThreshold ?? 100000,
|
|
1047
|
+
customInstructions: compactionConfig?.customInstructions,
|
|
1048
|
+
currentTokens: 0,
|
|
1049
|
+
isCompacting: false,
|
|
1050
|
+
};
|
|
889
1051
|
this.sessions[sessionId] = {
|
|
890
1052
|
query: q,
|
|
891
1053
|
input: input,
|
|
@@ -894,6 +1056,7 @@ export class ClaudeAcpAgent {
|
|
|
894
1056
|
settingsManager,
|
|
895
1057
|
abortController: sessionAbortController,
|
|
896
1058
|
cwd: params.cwd,
|
|
1059
|
+
compaction: compactionState,
|
|
897
1060
|
};
|
|
898
1061
|
const availableCommands = await getAvailableSlashCommands(q);
|
|
899
1062
|
const models = await getAvailableModels(q);
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ClaudeAcpAgent, runAcp, toAcpNotifications, streamEventToAcpNotifications, type ToolUpdateMeta, type NewSessionMeta, } from "./acp-agent.js";
|
|
1
|
+
export { ClaudeAcpAgent, runAcp, toAcpNotifications, streamEventToAcpNotifications, type ToolUpdateMeta, type NewSessionMeta, type CompactionConfig, } from "./acp-agent.js";
|
|
2
2
|
export { loadManagedSettings, applyEnvironmentSettings, nodeToWebReadable, nodeToWebWritable, Pushable, unreachable, } from "./utils.js";
|
|
3
3
|
export { createMcpServer } from "./mcp-server.js";
|
|
4
4
|
export { toolInfoFromToolUse, planEntries, toolUpdateFromToolResult, createPreToolUseHook, acpToolNames as toolNames, } from "./tools.js";
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,IAAI,SAAS,GAC1B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/package.json
CHANGED