wave-code 0.17.0 → 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 +115 -0
- package/package.json +2 -2
- package/src/acp/agent.ts +136 -0
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();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.17.
|
|
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.17.
|
|
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 {
|
|
@@ -262,6 +266,9 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
262
266
|
logger.info(`Loading session: ${sessionId} in ${cwd}`);
|
|
263
267
|
const agent = await this.createAgent(sessionId, cwd, mcpServers);
|
|
264
268
|
|
|
269
|
+
// Replay conversation history via session/update notifications per ACP spec
|
|
270
|
+
await this.replayConversationHistory(agent);
|
|
271
|
+
|
|
265
272
|
return {
|
|
266
273
|
modes: this.getSessionModeState(agent),
|
|
267
274
|
configOptions: this.getSessionConfigOptions(agent),
|
|
@@ -799,6 +806,135 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
799
806
|
}
|
|
800
807
|
}
|
|
801
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
|
+
|
|
802
938
|
private createCallbacks(sessionId: string): AgentOptions["callbacks"] {
|
|
803
939
|
const getAgent = () => this.agents.get(sessionId);
|
|
804
940
|
const toolStates = new Map<
|