wave-code 0.16.13 → 0.17.1
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/acp/agent.d.ts +1 -0
- package/dist/acp/agent.d.ts.map +1 -1
- package/dist/acp/agent.js +117 -0
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +2 -2
- package/dist/components/InputBox.d.ts +2 -0
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +2 -2
- package/dist/components/McpManager.d.ts.map +1 -1
- package/dist/components/McpManager.js +1 -1
- package/dist/components/QueuedMessageList.d.ts.map +1 -1
- package/dist/components/QueuedMessageList.js +2 -1
- package/dist/components/StatusLine.d.ts +2 -0
- package/dist/components/StatusLine.d.ts.map +1 -1
- package/dist/components/StatusLine.js +10 -6
- package/dist/contexts/useChat.d.ts +1 -0
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +5 -1
- package/package.json +2 -2
- package/src/acp/agent.ts +140 -1
- package/src/components/ChatInterface.tsx +3 -0
- package/src/components/InputBox.tsx +7 -0
- package/src/components/McpManager.tsx +7 -0
- package/src/components/QueuedMessageList.tsx +2 -1
- package/src/components/StatusLine.tsx +15 -0
- package/src/contexts/useChat.tsx +6 -1
package/dist/acp/agent.d.ts
CHANGED
package/dist/acp/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAyBA,OAAO,EACL,KAAK,KAAK,IAAI,QAAQ,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAUzB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EAOpC,MAAM,0BAA0B,CAAC;AAGlC,qBAAa,YAAa,YAAW,QAAQ;IAC3C,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,mBAAmB;IAI3C,OAAO,CAAC,mBAAmB;IAkC3B,OAAO,CAAC,uBAAuB;YAmCjB,gBAAgB;IASxB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAyBzC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAI5C,WAAW;IA2EnB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAalE,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAcrE,YAAY,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,oBAAoB,CAAC;IAuB1B,qBAAqB,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAc7B,SAAS,CACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAO7B,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5D,sBAAsB,CAC1B,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,8BAA8B,CAAC;IAuBpC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAyDtD,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IASvD,OAAO,CAAC,kBAAkB;YA2BZ,uBAAuB;IA8LrC,OAAO,CAAC,cAAc;IAwGtB,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,WAAW;YAmBL,yBAAyB;IAiIvC,OAAO,CAAC,eAAe;CAyOxB"}
|
package/dist/acp/agent.js
CHANGED
|
@@ -174,6 +174,8 @@ export class WaveAcpAgent {
|
|
|
174
174
|
const { sessionId, cwd, mcpServers } = params;
|
|
175
175
|
logger.info(`Loading session: ${sessionId} in ${cwd}`);
|
|
176
176
|
const agent = await this.createAgent(sessionId, cwd, mcpServers);
|
|
177
|
+
// Replay conversation history via session/update notifications per ACP spec
|
|
178
|
+
await this.replayConversationHistory(agent);
|
|
177
179
|
return {
|
|
178
180
|
modes: this.getSessionModeState(agent),
|
|
179
181
|
configOptions: this.getSessionConfigOptions(agent),
|
|
@@ -618,6 +620,119 @@ export class WaveAcpAgent {
|
|
|
618
620
|
return "other";
|
|
619
621
|
}
|
|
620
622
|
}
|
|
623
|
+
async replayConversationHistory(agent) {
|
|
624
|
+
const sessionId = agent.sessionId;
|
|
625
|
+
let history;
|
|
626
|
+
try {
|
|
627
|
+
const thread = await agent.getFullMessageThread();
|
|
628
|
+
history = thread.messages;
|
|
629
|
+
}
|
|
630
|
+
catch {
|
|
631
|
+
// Fallback to in-memory messages if full thread fails
|
|
632
|
+
history = agent.messages;
|
|
633
|
+
}
|
|
634
|
+
for (const message of history) {
|
|
635
|
+
if (message.isMeta)
|
|
636
|
+
continue;
|
|
637
|
+
const messageId = message.id;
|
|
638
|
+
for (const block of message.blocks) {
|
|
639
|
+
if (block.type === "text") {
|
|
640
|
+
const textBlock = block;
|
|
641
|
+
const update = message.role === "user"
|
|
642
|
+
? {
|
|
643
|
+
sessionUpdate: "user_message_chunk",
|
|
644
|
+
content: { type: "text", text: textBlock.content },
|
|
645
|
+
messageId,
|
|
646
|
+
}
|
|
647
|
+
: {
|
|
648
|
+
sessionUpdate: "agent_message_chunk",
|
|
649
|
+
content: { type: "text", text: textBlock.content },
|
|
650
|
+
messageId,
|
|
651
|
+
};
|
|
652
|
+
this.connection.sessionUpdate({ sessionId, update });
|
|
653
|
+
}
|
|
654
|
+
else if (block.type === "reasoning") {
|
|
655
|
+
const reasoningBlock = block;
|
|
656
|
+
this.connection.sessionUpdate({
|
|
657
|
+
sessionId,
|
|
658
|
+
update: {
|
|
659
|
+
sessionUpdate: "agent_thought_chunk",
|
|
660
|
+
content: { type: "text", text: reasoningBlock.content },
|
|
661
|
+
messageId,
|
|
662
|
+
},
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
else if (block.type === "tool") {
|
|
666
|
+
const toolBlock = block;
|
|
667
|
+
const toolCallId = toolBlock.id ||
|
|
668
|
+
"replay-" + Math.random().toString(36).substring(2, 9);
|
|
669
|
+
const effectiveName = toolBlock.name || "Tool";
|
|
670
|
+
const effectiveCompactParams = toolBlock.compactParams;
|
|
671
|
+
const displayTitle = effectiveName && effectiveCompactParams
|
|
672
|
+
? `${effectiveName}: ${effectiveCompactParams}`
|
|
673
|
+
: effectiveName;
|
|
674
|
+
let parsedParameters;
|
|
675
|
+
if (toolBlock.parameters) {
|
|
676
|
+
try {
|
|
677
|
+
const parsed = JSON.parse(toolBlock.parameters);
|
|
678
|
+
parsedParameters = Array.isArray(parsed)
|
|
679
|
+
? { args: parsed }
|
|
680
|
+
: parsed;
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
// Ignore parse errors
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
const content = effectiveName && (parsedParameters || toolBlock.shortResult)
|
|
687
|
+
? this.getToolContent(effectiveName, parsedParameters, toolBlock.shortResult)
|
|
688
|
+
: undefined;
|
|
689
|
+
const locations = effectiveName && parsedParameters
|
|
690
|
+
? this.getToolLocations(effectiveName, parsedParameters)
|
|
691
|
+
: undefined;
|
|
692
|
+
const kind = effectiveName
|
|
693
|
+
? this.getToolKind(effectiveName)
|
|
694
|
+
: undefined;
|
|
695
|
+
// Emit tool_call (creation)
|
|
696
|
+
this.connection.sessionUpdate({
|
|
697
|
+
sessionId,
|
|
698
|
+
update: {
|
|
699
|
+
sessionUpdate: "tool_call",
|
|
700
|
+
toolCallId,
|
|
701
|
+
title: displayTitle,
|
|
702
|
+
status: "pending",
|
|
703
|
+
content,
|
|
704
|
+
locations,
|
|
705
|
+
kind,
|
|
706
|
+
rawInput: parsedParameters,
|
|
707
|
+
},
|
|
708
|
+
});
|
|
709
|
+
// Emit tool_call_update with final status
|
|
710
|
+
const status = toolBlock.stage === "end"
|
|
711
|
+
? toolBlock.success
|
|
712
|
+
? "completed"
|
|
713
|
+
: "failed"
|
|
714
|
+
: toolBlock.stage === "running"
|
|
715
|
+
? "in_progress"
|
|
716
|
+
: "pending";
|
|
717
|
+
this.connection.sessionUpdate({
|
|
718
|
+
sessionId,
|
|
719
|
+
update: {
|
|
720
|
+
sessionUpdate: "tool_call_update",
|
|
721
|
+
toolCallId,
|
|
722
|
+
status,
|
|
723
|
+
title: displayTitle,
|
|
724
|
+
rawOutput: toolBlock.result || toolBlock.error,
|
|
725
|
+
content,
|
|
726
|
+
locations,
|
|
727
|
+
kind,
|
|
728
|
+
rawInput: parsedParameters,
|
|
729
|
+
},
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
// Skip: image, bang, compact, error, file_history, task_notification blocks
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
621
736
|
createCallbacks(sessionId) {
|
|
622
737
|
const getAgent = () => this.agents.get(sessionId);
|
|
623
738
|
const toolStates = new Map();
|
|
@@ -821,10 +936,12 @@ function convertAcpMcpServers(servers) {
|
|
|
821
936
|
for (const server of servers) {
|
|
822
937
|
const config = {};
|
|
823
938
|
if ("type" in server && server.type === "http") {
|
|
939
|
+
config.type = "http";
|
|
824
940
|
config.url = server.url;
|
|
825
941
|
config.headers = convertHttpHeaders(server.headers);
|
|
826
942
|
}
|
|
827
943
|
else if ("type" in server && server.type === "sse") {
|
|
944
|
+
config.type = "sse";
|
|
828
945
|
config.url = server.url;
|
|
829
946
|
config.headers = convertHttpHeaders(server.headers);
|
|
830
947
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAkIjC,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { ConfirmationDetails } from "./ConfirmationDetails.js";
|
|
|
10
10
|
import { ConfirmationSelector } from "./ConfirmationSelector.js";
|
|
11
11
|
import { useChat } from "../contexts/useChat.js";
|
|
12
12
|
export const ChatInterface = () => {
|
|
13
|
-
const { messages, isLoading, isCommandRunning, isCompacting, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, requestRemount, } = useChat();
|
|
13
|
+
const { messages, isLoading, isCommandRunning, isCompacting, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, maxInputTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, requestRemount, } = useChat();
|
|
14
14
|
const displayMessages = messages;
|
|
15
15
|
const [forceStatic, setForceStatic] = useState(false);
|
|
16
16
|
const { stdout } = useStdout();
|
|
@@ -37,5 +37,5 @@ export const ChatInterface = () => {
|
|
|
37
37
|
]);
|
|
38
38
|
if (!sessionId)
|
|
39
39
|
return null;
|
|
40
|
-
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading || isCommandRunning || isCompacting) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompacting: isCompacting, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded }, "confirmation-details")) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel })] }))] }));
|
|
40
|
+
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading || isCommandRunning || isCompacting) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompacting: isCompacting, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded }, "confirmation-details")) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel })] }))] }));
|
|
41
41
|
};
|
|
@@ -16,6 +16,8 @@ export interface InputBoxProps {
|
|
|
16
16
|
disconnectMcpServer?: (serverName: string) => Promise<boolean>;
|
|
17
17
|
slashCommands?: SlashCommand[];
|
|
18
18
|
hasSlashCommand?: (commandId: string) => boolean;
|
|
19
|
+
latestTotalTokens?: number;
|
|
20
|
+
maxInputTokens?: number;
|
|
19
21
|
}
|
|
20
22
|
export declare const InputBox: React.FC<InputBoxProps>;
|
|
21
23
|
//# sourceMappingURL=InputBox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAmBzC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAmBzC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAEjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAgS5C,CAAC"}
|
|
@@ -19,7 +19,7 @@ import { useInputManager } from "../hooks/useInputManager.js";
|
|
|
19
19
|
import { useChat } from "../contexts/useChat.js";
|
|
20
20
|
export const INPUT_PLACEHOLDER_TEXT = "Type your message (use /help for more info)...";
|
|
21
21
|
export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
|
|
22
|
-
export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
|
|
22
|
+
export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
|
|
23
23
|
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw, currentModel, configuredModels, setModel, recreateAgent, } = useChat();
|
|
24
24
|
// Input manager with all input state and functionality (including images)
|
|
25
25
|
const { inputText, cursorPosition,
|
|
@@ -122,5 +122,5 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
122
122
|
showHelp ||
|
|
123
123
|
showStatusCommand ||
|
|
124
124
|
showLoginCommand ||
|
|
125
|
-
showPluginManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: btwState.isActive ? "cyan" : "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: btwState.isActive && isPlaceholder ? (_jsxs(_Fragment, { children: [_jsx(Text, { backgroundColor: "white", color: "black", children: " " }), _jsx(Text, { color: "cyan", children: "Type your side question..." })] })) : shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(StatusLine, { permissionMode: permissionMode, isShellCommand: isShellCommand, isBtwActive: btwState.isActive })] }))] }));
|
|
125
|
+
showPluginManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: btwState.isActive ? "cyan" : "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: btwState.isActive && isPlaceholder ? (_jsxs(_Fragment, { children: [_jsx(Text, { backgroundColor: "white", color: "black", children: " " }), _jsx(Text, { color: "cyan", children: "Type your side question..." })] })) : shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(StatusLine, { permissionMode: permissionMode, isShellCommand: isShellCommand, isBtwActive: btwState.isActive, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens })] }))] }));
|
|
126
126
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManager.d.ts","sourceRoot":"","sources":["../../src/components/McpManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAQD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"McpManager.d.ts","sourceRoot":"","sources":["../../src/components/McpManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAQD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAiShD,CAAC"}
|
|
@@ -70,7 +70,7 @@ export const McpManager = ({ onCancel, servers, onConnectServer, onDisconnectSer
|
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
72
|
if (state.viewMode === "detail" && selectedServer) {
|
|
73
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["MCP Server Details: ", selectedServer.name] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", _jsxs(Text, { color: getStatusColor(selectedServer.status), children: [getStatusIcon(selectedServer.status), " ", selectedServer.status] })] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Command:" }), " ", selectedServer.config.command] }) }), selectedServer.originalUrl && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "URL:" }), " ", selectedServer.originalUrl] }) })), selectedServer.config.args && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Args:" }), " ", selectedServer.config.args.join(" ")] }) })), selectedServer.toolCount !== undefined && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Tools:" }), " ", selectedServer.toolCount, " ", "tools"] }) })), selectedServer.capabilities && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Capabilities:" }), " ", selectedServer.capabilities.join(", ")] }) })), selectedServer.lastConnected && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Last Connected:" }), " ", formatTime(selectedServer.lastConnected)] }) })), selectedServer.error && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "red", children: "Error:" }), " ", selectedServer.error] }) }))] }), selectedServer.config.env &&
|
|
73
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["MCP Server Details: ", selectedServer.name] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", _jsxs(Text, { color: getStatusColor(selectedServer.status), children: [getStatusIcon(selectedServer.status), " ", selectedServer.status] })] }) }), selectedServer.config.type && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Type:" }), " ", selectedServer.config.type] }) })), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Command:" }), " ", selectedServer.config.command] }) }), selectedServer.originalUrl && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "URL:" }), " ", selectedServer.originalUrl] }) })), selectedServer.config.args && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Args:" }), " ", selectedServer.config.args.join(" ")] }) })), selectedServer.toolCount !== undefined && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Tools:" }), " ", selectedServer.toolCount, " ", "tools"] }) })), selectedServer.capabilities && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Capabilities:" }), " ", selectedServer.capabilities.join(", ")] }) })), selectedServer.lastConnected && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Last Connected:" }), " ", formatTime(selectedServer.lastConnected)] }) })), selectedServer.error && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "red", children: "Error:" }), " ", selectedServer.error] }) }))] }), selectedServer.config.env &&
|
|
74
74
|
Object.keys(selectedServer.config.env).length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "blue", bold: true, children: "Environment Variables:" }), _jsx(Box, { borderStyle: "single", borderColor: "blue", padding: 1, children: Object.entries(selectedServer.config.env).map(([key, value]) => (_jsxs(Text, { children: [key, "=", value] }, key))) })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [selectedServer.status === "disconnected" ||
|
|
75
75
|
selectedServer.status === "error"
|
|
76
76
|
? "c to connect · "
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueuedMessageList.d.ts","sourceRoot":"","sources":["../../src/components/QueuedMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"QueuedMessageList.d.ts","sourceRoot":"","sources":["../../src/components/QueuedMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EA2BrC,CAAC"}
|
|
@@ -9,7 +9,8 @@ export const QueuedMessageList = () => {
|
|
|
9
9
|
return (_jsx(Box, { flexDirection: "column", children: queuedMessages.map((msg, index) => {
|
|
10
10
|
const content = msg.content.trim();
|
|
11
11
|
const hasImages = msg.images && msg.images.length > 0;
|
|
12
|
-
const
|
|
12
|
+
const prefix = msg.type === "bang" ? "! " : "";
|
|
13
|
+
const displayText = prefix + (content || (hasImages ? "[Images]" : ""));
|
|
13
14
|
return (_jsx(Box, { children: _jsx(Text, { color: "gray", italic: true, children: displayText.length > 60
|
|
14
15
|
? `${displayText.substring(0, 57)}...`
|
|
15
16
|
: displayText }) }, index));
|
|
@@ -3,6 +3,8 @@ export interface StatusLineProps {
|
|
|
3
3
|
permissionMode: string;
|
|
4
4
|
isShellCommand: boolean;
|
|
5
5
|
isBtwActive: boolean;
|
|
6
|
+
latestTotalTokens?: number;
|
|
7
|
+
maxInputTokens?: number;
|
|
6
8
|
}
|
|
7
9
|
export declare const StatusLine: React.FC<StatusLineProps>;
|
|
8
10
|
//# sourceMappingURL=StatusLine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../src/components/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../src/components/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgDhD,CAAC"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
export const StatusLine = ({ permissionMode, isShellCommand, isBtwActive, }) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
export const StatusLine = ({ permissionMode, isShellCommand, isBtwActive, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
|
|
4
|
+
const percentage = latestTotalTokens > 0
|
|
5
|
+
? Math.min(Math.round((latestTotalTokens / maxInputTokens) * 100), 100)
|
|
6
|
+
: 0;
|
|
7
|
+
const contextColor = percentage > 95 ? "red" : percentage > 80 ? "yellow" : "gray";
|
|
8
|
+
return (_jsxs(Box, { paddingRight: 1, justifyContent: "space-between", width: "100%", children: [isBtwActive ? (_jsxs(Text, { color: "gray", children: ["Mode: ", _jsx(Text, { color: "cyan", children: "BTW" }), " (ESC to dismiss)"] })) : isShellCommand ? (_jsxs(Text, { color: "gray", children: ["Shell: ", _jsx(Text, { color: "yellow", children: "Run shell command" })] })) : (_jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan"
|
|
9
|
+
? "yellow"
|
|
10
|
+
: permissionMode === "bypassPermissions"
|
|
11
|
+
? "red"
|
|
12
|
+
: "cyan", bold: permissionMode === "bypassPermissions", children: permissionMode }), " ", "(Shift+Tab to cycle)"] })), percentage > 0 && (_jsxs(Text, { color: contextColor, children: [percentage, "% context"] }))] }));
|
|
9
13
|
};
|
|
@@ -18,6 +18,7 @@ export interface ChatContextType {
|
|
|
18
18
|
askBtw: (question: string) => Promise<string>;
|
|
19
19
|
abortMessage: () => void;
|
|
20
20
|
latestTotalTokens: number;
|
|
21
|
+
maxInputTokens: number;
|
|
21
22
|
currentModel: string;
|
|
22
23
|
configuredModels: string[];
|
|
23
24
|
getConfiguredModels: () => string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,aAAa,EACd,MAAM,gBAAgB,CAAC;AAaxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IAEtB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,cAAc,EAAE,aAAa,EAAE,CAAC;IAEhC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CACX,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
|
package/dist/contexts/useChat.js
CHANGED
|
@@ -24,6 +24,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
24
24
|
const [isTaskListVisible, setIsTaskListVisible] = useState(true);
|
|
25
25
|
const [messages, setMessages] = useState([]);
|
|
26
26
|
const [latestTotalTokens, setLatestTotalTokens] = useState(0);
|
|
27
|
+
const [maxInputTokens, setMaxInputTokens] = useState(128000);
|
|
27
28
|
const throttledSetMessages = useMemo(() => throttle(() => {
|
|
28
29
|
if (!isExpandedRef.current && agentRef.current) {
|
|
29
30
|
const msgs = [...agentRef.current.messages];
|
|
@@ -69,7 +70,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
69
70
|
const [remountKey, setRemountKey] = useState(0);
|
|
70
71
|
const prevSessionId = useRef(null);
|
|
71
72
|
const requestRemount = useMemo(() => throttle(() => {
|
|
72
|
-
logger.
|
|
73
|
+
logger.debug("requesting remount");
|
|
73
74
|
stdout?.write("\u001b[2J\u001b[3J\u001b[0;0H", () => {
|
|
74
75
|
setRemountKey((prev) => prev + 1);
|
|
75
76
|
});
|
|
@@ -195,6 +196,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
195
196
|
setWorkingDirectory(agent.workingDirectory);
|
|
196
197
|
setCurrentModelState(agent.getModelConfig().model);
|
|
197
198
|
setConfiguredModels(agent.getConfiguredModels());
|
|
199
|
+
setMaxInputTokens(agent.getMaxInputTokens());
|
|
198
200
|
// Get initial MCP servers state
|
|
199
201
|
const initialMcpServers = agent.getMcpServers?.() || [];
|
|
200
202
|
setMcpServerStatuses(initialMcpServers);
|
|
@@ -239,6 +241,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
239
241
|
setSessionId("");
|
|
240
242
|
setIsLoading(false);
|
|
241
243
|
setLatestTotalTokens(0);
|
|
244
|
+
setMaxInputTokens(128000);
|
|
242
245
|
setIsCommandRunning(false);
|
|
243
246
|
setIsCompacting(false);
|
|
244
247
|
if (currentSessionId) {
|
|
@@ -476,6 +479,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
476
479
|
askBtw,
|
|
477
480
|
abortMessage,
|
|
478
481
|
latestTotalTokens,
|
|
482
|
+
maxInputTokens,
|
|
479
483
|
currentModel,
|
|
480
484
|
configuredModels,
|
|
481
485
|
getConfiguredModels,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "CLI-based code assistant powered by AI, built with React and Ink",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"semver": "^7.7.4",
|
|
43
43
|
"yargs": "^17.7.2",
|
|
44
44
|
"zod": "^3.23.8",
|
|
45
|
-
"wave-agent-sdk": "0.
|
|
45
|
+
"wave-agent-sdk": "0.17.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.1.8",
|
package/src/acp/agent.ts
CHANGED
|
@@ -17,6 +17,10 @@ import {
|
|
|
17
17
|
ASK_USER_QUESTION_TOOL_NAME,
|
|
18
18
|
AskUserQuestion,
|
|
19
19
|
AskUserQuestionOption,
|
|
20
|
+
type Message,
|
|
21
|
+
type TextBlock,
|
|
22
|
+
type ReasoningBlock,
|
|
23
|
+
type ToolBlock,
|
|
20
24
|
} from "wave-agent-sdk";
|
|
21
25
|
import { logger } from "../utils/logger.js";
|
|
22
26
|
import {
|
|
@@ -211,7 +215,8 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
211
215
|
callbacks.onPermissionModeChange?.(mode),
|
|
212
216
|
onModelChange: (model) => callbacks.onModelChange?.(model),
|
|
213
217
|
onUserMessageAdded: (params) => callbacks.onUserMessageAdded?.(params),
|
|
214
|
-
onMcpServersChange: (servers) =>
|
|
218
|
+
onMcpServersChange: (servers) =>
|
|
219
|
+
callbacks.onMcpServersChange?.(servers),
|
|
215
220
|
},
|
|
216
221
|
});
|
|
217
222
|
|
|
@@ -261,6 +266,9 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
261
266
|
logger.info(`Loading session: ${sessionId} in ${cwd}`);
|
|
262
267
|
const agent = await this.createAgent(sessionId, cwd, mcpServers);
|
|
263
268
|
|
|
269
|
+
// Replay conversation history via session/update notifications per ACP spec
|
|
270
|
+
await this.replayConversationHistory(agent);
|
|
271
|
+
|
|
264
272
|
return {
|
|
265
273
|
modes: this.getSessionModeState(agent),
|
|
266
274
|
configOptions: this.getSessionConfigOptions(agent),
|
|
@@ -798,6 +806,135 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
798
806
|
}
|
|
799
807
|
}
|
|
800
808
|
|
|
809
|
+
private async replayConversationHistory(agent: WaveAgent): Promise<void> {
|
|
810
|
+
const sessionId = agent.sessionId as AcpSessionId;
|
|
811
|
+
|
|
812
|
+
let history: Message[];
|
|
813
|
+
try {
|
|
814
|
+
const thread = await agent.getFullMessageThread();
|
|
815
|
+
history = thread.messages;
|
|
816
|
+
} catch {
|
|
817
|
+
// Fallback to in-memory messages if full thread fails
|
|
818
|
+
history = agent.messages;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
for (const message of history) {
|
|
822
|
+
if (message.isMeta) continue;
|
|
823
|
+
|
|
824
|
+
const messageId = message.id;
|
|
825
|
+
|
|
826
|
+
for (const block of message.blocks) {
|
|
827
|
+
if (block.type === "text") {
|
|
828
|
+
const textBlock = block as TextBlock;
|
|
829
|
+
const update =
|
|
830
|
+
message.role === "user"
|
|
831
|
+
? {
|
|
832
|
+
sessionUpdate: "user_message_chunk" as const,
|
|
833
|
+
content: { type: "text" as const, text: textBlock.content },
|
|
834
|
+
messageId,
|
|
835
|
+
}
|
|
836
|
+
: {
|
|
837
|
+
sessionUpdate: "agent_message_chunk" as const,
|
|
838
|
+
content: { type: "text" as const, text: textBlock.content },
|
|
839
|
+
messageId,
|
|
840
|
+
};
|
|
841
|
+
this.connection.sessionUpdate({ sessionId, update });
|
|
842
|
+
} else if (block.type === "reasoning") {
|
|
843
|
+
const reasoningBlock = block as ReasoningBlock;
|
|
844
|
+
this.connection.sessionUpdate({
|
|
845
|
+
sessionId,
|
|
846
|
+
update: {
|
|
847
|
+
sessionUpdate: "agent_thought_chunk",
|
|
848
|
+
content: { type: "text", text: reasoningBlock.content },
|
|
849
|
+
messageId,
|
|
850
|
+
},
|
|
851
|
+
});
|
|
852
|
+
} else if (block.type === "tool") {
|
|
853
|
+
const toolBlock = block as ToolBlock;
|
|
854
|
+
const toolCallId =
|
|
855
|
+
toolBlock.id ||
|
|
856
|
+
"replay-" + Math.random().toString(36).substring(2, 9);
|
|
857
|
+
const effectiveName = toolBlock.name || "Tool";
|
|
858
|
+
const effectiveCompactParams = toolBlock.compactParams;
|
|
859
|
+
|
|
860
|
+
const displayTitle =
|
|
861
|
+
effectiveName && effectiveCompactParams
|
|
862
|
+
? `${effectiveName}: ${effectiveCompactParams}`
|
|
863
|
+
: effectiveName;
|
|
864
|
+
|
|
865
|
+
let parsedParameters: Record<string, unknown> | undefined;
|
|
866
|
+
if (toolBlock.parameters) {
|
|
867
|
+
try {
|
|
868
|
+
const parsed = JSON.parse(toolBlock.parameters);
|
|
869
|
+
parsedParameters = Array.isArray(parsed)
|
|
870
|
+
? { args: parsed }
|
|
871
|
+
: parsed;
|
|
872
|
+
} catch {
|
|
873
|
+
// Ignore parse errors
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
const content =
|
|
878
|
+
effectiveName && (parsedParameters || toolBlock.shortResult)
|
|
879
|
+
? this.getToolContent(
|
|
880
|
+
effectiveName,
|
|
881
|
+
parsedParameters,
|
|
882
|
+
toolBlock.shortResult,
|
|
883
|
+
)
|
|
884
|
+
: undefined;
|
|
885
|
+
const locations =
|
|
886
|
+
effectiveName && parsedParameters
|
|
887
|
+
? this.getToolLocations(effectiveName, parsedParameters)
|
|
888
|
+
: undefined;
|
|
889
|
+
const kind = effectiveName
|
|
890
|
+
? this.getToolKind(effectiveName)
|
|
891
|
+
: undefined;
|
|
892
|
+
|
|
893
|
+
// Emit tool_call (creation)
|
|
894
|
+
this.connection.sessionUpdate({
|
|
895
|
+
sessionId,
|
|
896
|
+
update: {
|
|
897
|
+
sessionUpdate: "tool_call",
|
|
898
|
+
toolCallId,
|
|
899
|
+
title: displayTitle,
|
|
900
|
+
status: "pending",
|
|
901
|
+
content,
|
|
902
|
+
locations,
|
|
903
|
+
kind,
|
|
904
|
+
rawInput: parsedParameters,
|
|
905
|
+
},
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
// Emit tool_call_update with final status
|
|
909
|
+
const status: ToolCallStatus =
|
|
910
|
+
toolBlock.stage === "end"
|
|
911
|
+
? toolBlock.success
|
|
912
|
+
? "completed"
|
|
913
|
+
: "failed"
|
|
914
|
+
: toolBlock.stage === "running"
|
|
915
|
+
? "in_progress"
|
|
916
|
+
: "pending";
|
|
917
|
+
|
|
918
|
+
this.connection.sessionUpdate({
|
|
919
|
+
sessionId,
|
|
920
|
+
update: {
|
|
921
|
+
sessionUpdate: "tool_call_update",
|
|
922
|
+
toolCallId,
|
|
923
|
+
status,
|
|
924
|
+
title: displayTitle,
|
|
925
|
+
rawOutput: toolBlock.result || toolBlock.error,
|
|
926
|
+
content,
|
|
927
|
+
locations,
|
|
928
|
+
kind,
|
|
929
|
+
rawInput: parsedParameters,
|
|
930
|
+
},
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
// Skip: image, bang, compact, error, file_history, task_notification blocks
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
801
938
|
private createCallbacks(sessionId: string): AgentOptions["callbacks"] {
|
|
802
939
|
const getAgent = () => this.agents.get(sessionId);
|
|
803
940
|
const toolStates = new Map<
|
|
@@ -1043,9 +1180,11 @@ function convertAcpMcpServers(
|
|
|
1043
1180
|
for (const server of servers) {
|
|
1044
1181
|
const config: McpServerConfig = {};
|
|
1045
1182
|
if ("type" in server && server.type === "http") {
|
|
1183
|
+
config.type = "http";
|
|
1046
1184
|
config.url = server.url;
|
|
1047
1185
|
config.headers = convertHttpHeaders(server.headers);
|
|
1048
1186
|
} else if ("type" in server && server.type === "sse") {
|
|
1187
|
+
config.type = "sse";
|
|
1049
1188
|
config.url = server.url;
|
|
1050
1189
|
config.headers = convertHttpHeaders(server.headers);
|
|
1051
1190
|
} else {
|
|
@@ -25,6 +25,7 @@ export const ChatInterface: React.FC = () => {
|
|
|
25
25
|
isExpanded,
|
|
26
26
|
sessionId,
|
|
27
27
|
latestTotalTokens,
|
|
28
|
+
maxInputTokens,
|
|
28
29
|
slashCommands,
|
|
29
30
|
hasSlashCommand,
|
|
30
31
|
isConfirmationVisible,
|
|
@@ -99,6 +100,8 @@ export const ChatInterface: React.FC = () => {
|
|
|
99
100
|
disconnectMcpServer={disconnectMcpServer}
|
|
100
101
|
slashCommands={slashCommands}
|
|
101
102
|
hasSlashCommand={hasSlashCommand}
|
|
103
|
+
latestTotalTokens={latestTotalTokens}
|
|
104
|
+
maxInputTokens={maxInputTokens}
|
|
102
105
|
/>
|
|
103
106
|
</>
|
|
104
107
|
)}
|
|
@@ -44,6 +44,9 @@ export interface InputBoxProps {
|
|
|
44
44
|
// Slash Command related properties
|
|
45
45
|
slashCommands?: SlashCommand[];
|
|
46
46
|
hasSlashCommand?: (commandId: string) => boolean;
|
|
47
|
+
// Token usage
|
|
48
|
+
latestTotalTokens?: number;
|
|
49
|
+
maxInputTokens?: number;
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
export const InputBox: React.FC<InputBoxProps> = ({
|
|
@@ -54,6 +57,8 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
54
57
|
disconnectMcpServer = async () => false,
|
|
55
58
|
slashCommands = [],
|
|
56
59
|
hasSlashCommand = () => false,
|
|
60
|
+
latestTotalTokens = 0,
|
|
61
|
+
maxInputTokens = 128000,
|
|
57
62
|
}) => {
|
|
58
63
|
const {
|
|
59
64
|
permissionMode: chatPermissionMode,
|
|
@@ -325,6 +330,8 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
325
330
|
permissionMode={permissionMode}
|
|
326
331
|
isShellCommand={isShellCommand}
|
|
327
332
|
isBtwActive={btwState.isActive}
|
|
333
|
+
latestTotalTokens={latestTotalTokens}
|
|
334
|
+
maxInputTokens={maxInputTokens}
|
|
328
335
|
/>
|
|
329
336
|
</Box>
|
|
330
337
|
)}
|
|
@@ -122,6 +122,13 @@ export const McpManager: React.FC<McpManagerProps> = ({
|
|
|
122
122
|
</Text>
|
|
123
123
|
</Text>
|
|
124
124
|
</Box>
|
|
125
|
+
{selectedServer.config.type && (
|
|
126
|
+
<Box>
|
|
127
|
+
<Text>
|
|
128
|
+
<Text color="blue">Type:</Text> {selectedServer.config.type}
|
|
129
|
+
</Text>
|
|
130
|
+
</Box>
|
|
131
|
+
)}
|
|
125
132
|
<Box>
|
|
126
133
|
<Text>
|
|
127
134
|
<Text color="blue">Command:</Text> {selectedServer.config.command}
|
|
@@ -14,7 +14,8 @@ export const QueuedMessageList: React.FC = () => {
|
|
|
14
14
|
{queuedMessages.map((msg, index) => {
|
|
15
15
|
const content = msg.content.trim();
|
|
16
16
|
const hasImages = msg.images && msg.images.length > 0;
|
|
17
|
-
const
|
|
17
|
+
const prefix = msg.type === "bang" ? "! " : "";
|
|
18
|
+
const displayText = prefix + (content || (hasImages ? "[Images]" : ""));
|
|
18
19
|
|
|
19
20
|
return (
|
|
20
21
|
<Box key={index}>
|
|
@@ -5,13 +5,25 @@ export interface StatusLineProps {
|
|
|
5
5
|
permissionMode: string;
|
|
6
6
|
isShellCommand: boolean;
|
|
7
7
|
isBtwActive: boolean;
|
|
8
|
+
latestTotalTokens?: number;
|
|
9
|
+
maxInputTokens?: number;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export const StatusLine: React.FC<StatusLineProps> = ({
|
|
11
13
|
permissionMode,
|
|
12
14
|
isShellCommand,
|
|
13
15
|
isBtwActive,
|
|
16
|
+
latestTotalTokens = 0,
|
|
17
|
+
maxInputTokens = 128000,
|
|
14
18
|
}) => {
|
|
19
|
+
const percentage =
|
|
20
|
+
latestTotalTokens > 0
|
|
21
|
+
? Math.min(Math.round((latestTotalTokens / maxInputTokens) * 100), 100)
|
|
22
|
+
: 0;
|
|
23
|
+
|
|
24
|
+
const contextColor =
|
|
25
|
+
percentage > 95 ? "red" : percentage > 80 ? "yellow" : "gray";
|
|
26
|
+
|
|
15
27
|
return (
|
|
16
28
|
<Box paddingRight={1} justifyContent="space-between" width="100%">
|
|
17
29
|
{isBtwActive ? (
|
|
@@ -40,6 +52,9 @@ export const StatusLine: React.FC<StatusLineProps> = ({
|
|
|
40
52
|
(Shift+Tab to cycle)
|
|
41
53
|
</Text>
|
|
42
54
|
)}
|
|
55
|
+
{percentage > 0 && (
|
|
56
|
+
<Text color={contextColor}>{percentage}% context</Text>
|
|
57
|
+
)}
|
|
43
58
|
</Box>
|
|
44
59
|
);
|
|
45
60
|
};
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -54,6 +54,7 @@ export interface ChatContextType {
|
|
|
54
54
|
askBtw: (question: string) => Promise<string>;
|
|
55
55
|
abortMessage: () => void;
|
|
56
56
|
latestTotalTokens: number;
|
|
57
|
+
maxInputTokens: number;
|
|
57
58
|
// Model functionality
|
|
58
59
|
currentModel: string;
|
|
59
60
|
configuredModels: string[];
|
|
@@ -162,6 +163,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
162
163
|
|
|
163
164
|
const [messages, setMessages] = useState<Message[]>([]);
|
|
164
165
|
const [latestTotalTokens, setLatestTotalTokens] = useState(0);
|
|
166
|
+
const [maxInputTokens, setMaxInputTokens] = useState(128000);
|
|
165
167
|
|
|
166
168
|
const throttledSetMessages = useMemo(
|
|
167
169
|
() =>
|
|
@@ -260,7 +262,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
260
262
|
() =>
|
|
261
263
|
throttle(
|
|
262
264
|
() => {
|
|
263
|
-
logger.
|
|
265
|
+
logger.debug("requesting remount");
|
|
264
266
|
stdout?.write("\u001b[2J\u001b[3J\u001b[0;0H", () => {
|
|
265
267
|
setRemountKey((prev) => prev + 1);
|
|
266
268
|
});
|
|
@@ -424,6 +426,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
424
426
|
setWorkingDirectory(agent.workingDirectory);
|
|
425
427
|
setCurrentModelState(agent.getModelConfig().model);
|
|
426
428
|
setConfiguredModels(agent.getConfiguredModels());
|
|
429
|
+
setMaxInputTokens(agent.getMaxInputTokens());
|
|
427
430
|
|
|
428
431
|
// Get initial MCP servers state
|
|
429
432
|
const initialMcpServers = agent.getMcpServers?.() || [];
|
|
@@ -471,6 +474,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
471
474
|
setSessionId("");
|
|
472
475
|
setIsLoading(false);
|
|
473
476
|
setLatestTotalTokens(0);
|
|
477
|
+
setMaxInputTokens(128000);
|
|
474
478
|
setIsCommandRunning(false);
|
|
475
479
|
setIsCompacting(false);
|
|
476
480
|
if (currentSessionId) {
|
|
@@ -750,6 +754,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
750
754
|
askBtw,
|
|
751
755
|
abortMessage,
|
|
752
756
|
latestTotalTokens,
|
|
757
|
+
maxInputTokens,
|
|
753
758
|
currentModel,
|
|
754
759
|
configuredModels,
|
|
755
760
|
getConfiguredModels,
|