wave-agent-sdk 0.18.0 → 0.18.2
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/managers/forkedAgentManager.js +1 -1
- package/dist/managers/messageManager.d.ts +22 -9
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +54 -44
- package/dist/managers/subagentManager.d.ts +14 -2
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +17 -5
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +12 -1
- package/dist/utils/shellResolver.d.ts +3 -0
- package/dist/utils/shellResolver.d.ts.map +1 -0
- package/dist/utils/shellResolver.js +25 -0
- package/package.json +1 -1
- package/src/managers/forkedAgentManager.ts +1 -1
- package/src/managers/messageManager.ts +78 -77
- package/src/managers/subagentManager.ts +42 -33
- package/src/tools/bashTool.ts +14 -1
- package/src/utils/shellResolver.ts +31 -0
|
@@ -63,7 +63,7 @@ export class ForkedAgentManager {
|
|
|
63
63
|
try {
|
|
64
64
|
if (entry.logStream && !entry.logStream.destroyed) {
|
|
65
65
|
entry.logStream.write(`[${new Date().toISOString()}] Final response:\n${result}\n`);
|
|
66
|
-
entry.logStream.write(`[${new Date().toISOString()}] Agent completed
|
|
66
|
+
entry.logStream.write(`[${new Date().toISOString()}] Agent completed\n`);
|
|
67
67
|
entry.logStream.end();
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -10,8 +10,18 @@ export interface MessageManagerCallbacks {
|
|
|
10
10
|
onUsagesChange?: (usages: Usage[]) => void;
|
|
11
11
|
onUserMessageAdded?: (params: UserMessageParams) => void;
|
|
12
12
|
onAssistantMessageAdded?: (messageId: string) => void;
|
|
13
|
-
onAssistantContentUpdated?: (
|
|
14
|
-
|
|
13
|
+
onAssistantContentUpdated?: (params: {
|
|
14
|
+
messageId: string;
|
|
15
|
+
chunk: string;
|
|
16
|
+
accumulated: string;
|
|
17
|
+
stage: "streaming" | "end";
|
|
18
|
+
}) => void;
|
|
19
|
+
onAssistantReasoningUpdated?: (params: {
|
|
20
|
+
messageId: string;
|
|
21
|
+
chunk: string;
|
|
22
|
+
accumulated: string;
|
|
23
|
+
stage: "streaming" | "end";
|
|
24
|
+
}) => void;
|
|
15
25
|
onToolBlockUpdated?: (params: ToolBlockUpdateCallbackParams) => void;
|
|
16
26
|
onErrorBlockAdded?: (error: string) => void;
|
|
17
27
|
onCompactBlockAdded?: (content: string) => void;
|
|
@@ -147,6 +157,13 @@ export declare class MessageManager {
|
|
|
147
157
|
* Trigger usage change callback with all usage data from assistant messages
|
|
148
158
|
*/
|
|
149
159
|
triggerUsageChange(): void;
|
|
160
|
+
/**
|
|
161
|
+
* Finalize a streaming block of the given type by setting its stage to "end".
|
|
162
|
+
* Fires the corresponding incremental callback with chunk="" to signal finalization.
|
|
163
|
+
* Does NOT call onMessagesChange — the caller is responsible for that.
|
|
164
|
+
* Returns true if a block was finalized.
|
|
165
|
+
*/
|
|
166
|
+
private finalizeStreamingBlock;
|
|
150
167
|
/**
|
|
151
168
|
* Update the current assistant message content during streaming
|
|
152
169
|
* This method updates the last assistant message's content without creating a new message
|
|
@@ -158,16 +175,12 @@ export declare class MessageManager {
|
|
|
158
175
|
* This method updates the last assistant message's reasoning content without creating a new message
|
|
159
176
|
*/
|
|
160
177
|
updateCurrentMessageReasoning(newAccumulatedReasoning: string): void;
|
|
161
|
-
/**
|
|
162
|
-
* Public wrapper for finalizeCurrentStreamingBlocks.
|
|
163
|
-
* Finalizes text/reasoning blocks after streaming completes (e.g. final response with no tools).
|
|
164
|
-
*/
|
|
165
|
-
finalizeStreamingBlocks(): void;
|
|
166
178
|
/**
|
|
167
179
|
* Finalize streaming text/reasoning blocks by setting their stage to "end".
|
|
168
|
-
* Called when a new block (e.g. tool) is appended during streaming.
|
|
180
|
+
* Called when a new block (e.g. tool) is appended during streaming, or when streaming completes.
|
|
181
|
+
* Fires incremental callbacks for each finalized block.
|
|
169
182
|
*/
|
|
170
|
-
|
|
183
|
+
finalizeStreamingBlocks(): void;
|
|
171
184
|
/**
|
|
172
185
|
* Remove the last user message from the conversation
|
|
173
186
|
* Used for hook error handling when the user prompt needs to be erased
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageManager.d.ts","sourceRoot":"","sources":["../../src/managers/messageManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,iBAAiB,EACjB,KAAK,0BAA0B,EAC/B,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EAElC,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAIL,WAAW,EAEZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qCAAqC,EAAE,MAAM,qBAAqB,CAAC;AAK5E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACjD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,yBAAyB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IAE3C,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAEzD,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtD,yBAAyB,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"messageManager.d.ts","sourceRoot":"","sources":["../../src/managers/messageManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -289,7 +289,7 @@ export class MessageManager {
|
|
|
289
289
|
}
|
|
290
290
|
updateToolBlock(params) {
|
|
291
291
|
// Finalize any streaming text/reasoning blocks before adding/updating a tool block
|
|
292
|
-
this.
|
|
292
|
+
this.finalizeStreamingBlocks();
|
|
293
293
|
const { messages: newMessages, messageId: resolvedMessageId } = updateToolBlockInMessage({
|
|
294
294
|
messages: this.messages,
|
|
295
295
|
...params,
|
|
@@ -310,7 +310,7 @@ export class MessageManager {
|
|
|
310
310
|
*/
|
|
311
311
|
addToolBlockToMessage(messageId, params) {
|
|
312
312
|
// Finalize any streaming text/reasoning blocks before adding a tool block
|
|
313
|
-
this.
|
|
313
|
+
this.finalizeStreamingBlocks();
|
|
314
314
|
const { messages: newMessages, toolBlockId } = addToolBlockToMessageInMessages(this.messages, messageId, params);
|
|
315
315
|
this.setMessages(newMessages);
|
|
316
316
|
this.callbacks.onToolBlockUpdated?.({
|
|
@@ -463,6 +463,38 @@ export class MessageManager {
|
|
|
463
463
|
triggerUsageChange() {
|
|
464
464
|
this.callbacks.onUsagesChange?.([...this._usages]);
|
|
465
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* Finalize a streaming block of the given type by setting its stage to "end".
|
|
468
|
+
* Fires the corresponding incremental callback with chunk="" to signal finalization.
|
|
469
|
+
* Does NOT call onMessagesChange — the caller is responsible for that.
|
|
470
|
+
* Returns true if a block was finalized.
|
|
471
|
+
*/
|
|
472
|
+
finalizeStreamingBlock(lastMessage, type) {
|
|
473
|
+
const index = lastMessage.blocks.findIndex((block) => block.type === type &&
|
|
474
|
+
block.stage === "streaming");
|
|
475
|
+
if (index < 0)
|
|
476
|
+
return false;
|
|
477
|
+
const block = lastMessage.blocks[index];
|
|
478
|
+
lastMessage.blocks[index] = {
|
|
479
|
+
type: block.type,
|
|
480
|
+
content: block.content,
|
|
481
|
+
stage: "end",
|
|
482
|
+
};
|
|
483
|
+
// Fire incremental callback to signal finalization
|
|
484
|
+
const callbackParams = {
|
|
485
|
+
messageId: lastMessage.id,
|
|
486
|
+
chunk: "",
|
|
487
|
+
accumulated: block.content,
|
|
488
|
+
stage: "end",
|
|
489
|
+
};
|
|
490
|
+
if (type === "text") {
|
|
491
|
+
this.callbacks.onAssistantContentUpdated?.(callbackParams);
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
this.callbacks.onAssistantReasoningUpdated?.(callbackParams);
|
|
495
|
+
}
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
466
498
|
/**
|
|
467
499
|
* Update the current assistant message content during streaming
|
|
468
500
|
* This method updates the last assistant message's content without creating a new message
|
|
@@ -475,16 +507,7 @@ export class MessageManager {
|
|
|
475
507
|
if (lastMessage.role !== "assistant")
|
|
476
508
|
return;
|
|
477
509
|
// Finalize any streaming reasoning blocks before text content arrives
|
|
478
|
-
|
|
479
|
-
block.stage === "streaming");
|
|
480
|
-
if (reasoningIndex >= 0) {
|
|
481
|
-
const reasoningBlock = lastMessage.blocks[reasoningIndex];
|
|
482
|
-
lastMessage.blocks[reasoningIndex] = {
|
|
483
|
-
type: "reasoning",
|
|
484
|
-
content: reasoningBlock.content,
|
|
485
|
-
stage: "end",
|
|
486
|
-
};
|
|
487
|
-
}
|
|
510
|
+
this.finalizeStreamingBlock(lastMessage, "reasoning");
|
|
488
511
|
// Get the current content to calculate the chunk
|
|
489
512
|
const textBlockIndex = lastMessage.blocks.findIndex((block) => block.type === "text");
|
|
490
513
|
const currentContent = textBlockIndex >= 0
|
|
@@ -509,7 +532,12 @@ export class MessageManager {
|
|
|
509
532
|
});
|
|
510
533
|
}
|
|
511
534
|
// FR-001: Trigger callbacks with chunk and accumulated content
|
|
512
|
-
this.callbacks.onAssistantContentUpdated?.(
|
|
535
|
+
this.callbacks.onAssistantContentUpdated?.({
|
|
536
|
+
messageId: lastMessage.id,
|
|
537
|
+
chunk,
|
|
538
|
+
accumulated: newAccumulatedContent,
|
|
539
|
+
stage: "streaming",
|
|
540
|
+
});
|
|
513
541
|
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
514
542
|
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
515
543
|
}
|
|
@@ -524,16 +552,7 @@ export class MessageManager {
|
|
|
524
552
|
if (lastMessage.role !== "assistant")
|
|
525
553
|
return;
|
|
526
554
|
// Finalize any streaming text blocks before reasoning content arrives
|
|
527
|
-
|
|
528
|
-
block.stage === "streaming");
|
|
529
|
-
if (textIndex >= 0) {
|
|
530
|
-
const textBlock = lastMessage.blocks[textIndex];
|
|
531
|
-
lastMessage.blocks[textIndex] = {
|
|
532
|
-
type: "text",
|
|
533
|
-
content: textBlock.content,
|
|
534
|
-
stage: "end",
|
|
535
|
-
};
|
|
536
|
-
}
|
|
555
|
+
this.finalizeStreamingBlock(lastMessage, "text");
|
|
537
556
|
// Get the current reasoning content to calculate the chunk
|
|
538
557
|
const reasoningBlockIndex = lastMessage.blocks.findIndex((block) => block.type === "reasoning");
|
|
539
558
|
const currentReasoning = reasoningBlockIndex >= 0
|
|
@@ -558,37 +577,28 @@ export class MessageManager {
|
|
|
558
577
|
});
|
|
559
578
|
}
|
|
560
579
|
// Trigger callbacks with chunk and accumulated reasoning content
|
|
561
|
-
this.callbacks.onAssistantReasoningUpdated?.(
|
|
580
|
+
this.callbacks.onAssistantReasoningUpdated?.({
|
|
581
|
+
messageId: lastMessage.id,
|
|
582
|
+
chunk,
|
|
583
|
+
accumulated: newAccumulatedReasoning,
|
|
584
|
+
stage: "streaming",
|
|
585
|
+
});
|
|
562
586
|
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
563
587
|
}
|
|
564
|
-
/**
|
|
565
|
-
* Public wrapper for finalizeCurrentStreamingBlocks.
|
|
566
|
-
* Finalizes text/reasoning blocks after streaming completes (e.g. final response with no tools).
|
|
567
|
-
*/
|
|
568
|
-
finalizeStreamingBlocks() {
|
|
569
|
-
this.finalizeCurrentStreamingBlocks();
|
|
570
|
-
}
|
|
571
588
|
/**
|
|
572
589
|
* Finalize streaming text/reasoning blocks by setting their stage to "end".
|
|
573
|
-
* Called when a new block (e.g. tool) is appended during streaming.
|
|
590
|
+
* Called when a new block (e.g. tool) is appended during streaming, or when streaming completes.
|
|
591
|
+
* Fires incremental callbacks for each finalized block.
|
|
574
592
|
*/
|
|
575
|
-
|
|
593
|
+
finalizeStreamingBlocks() {
|
|
576
594
|
if (this.messages.length === 0)
|
|
577
595
|
return;
|
|
578
596
|
const lastMessage = this.messages[this.messages.length - 1];
|
|
579
597
|
if (lastMessage.role !== "assistant")
|
|
580
598
|
return;
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return { ...block, stage: "end" };
|
|
585
|
-
}
|
|
586
|
-
return block;
|
|
587
|
-
});
|
|
588
|
-
// Only update if something changed
|
|
589
|
-
const changed = newBlocks.some((b, i) => b !== lastMessage.blocks[i]);
|
|
590
|
-
if (changed) {
|
|
591
|
-
lastMessage.blocks = newBlocks;
|
|
599
|
+
const textFinalized = this.finalizeStreamingBlock(lastMessage, "text");
|
|
600
|
+
const reasoningFinalized = this.finalizeStreamingBlock(lastMessage, "reasoning");
|
|
601
|
+
if (textFinalized || reasoningFinalized) {
|
|
592
602
|
this.callbacks.onMessagesChange?.([...this.messages]);
|
|
593
603
|
}
|
|
594
604
|
}
|
|
@@ -16,9 +16,21 @@ export interface SubagentManagerCallbacks {
|
|
|
16
16
|
/** Triggered when subagent creates assistant message */
|
|
17
17
|
onSubagentAssistantMessageAdded?: (subagentId: string, messageId: string) => void;
|
|
18
18
|
/** Triggered during subagent content streaming updates */
|
|
19
|
-
onSubagentAssistantContentUpdated?: (
|
|
19
|
+
onSubagentAssistantContentUpdated?: (params: {
|
|
20
|
+
subagentId: string;
|
|
21
|
+
messageId: string;
|
|
22
|
+
chunk: string;
|
|
23
|
+
accumulated: string;
|
|
24
|
+
stage: "streaming" | "end";
|
|
25
|
+
}) => void;
|
|
20
26
|
/** Triggered during subagent reasoning streaming updates */
|
|
21
|
-
onSubagentAssistantReasoningUpdated?: (
|
|
27
|
+
onSubagentAssistantReasoningUpdated?: (params: {
|
|
28
|
+
subagentId: string;
|
|
29
|
+
messageId: string;
|
|
30
|
+
chunk: string;
|
|
31
|
+
accumulated: string;
|
|
32
|
+
stage: "streaming" | "end";
|
|
33
|
+
}) => void;
|
|
22
34
|
/** Triggered when subagent tool block is updated */
|
|
23
35
|
onSubagentToolBlockUpdated?: (subagentId: string, params: ToolBlockUpdateCallbackParams) => void;
|
|
24
36
|
/** Triggered when subagent messages change */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagentManager.d.ts","sourceRoot":"","sources":["../../src/managers/subagentManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EACL,iBAAiB,EACjB,KAAK,6BAA6B,EACnC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAG9D,MAAM,WAAW,wBAAwB;IAEvC,gDAAgD;IAChD,0BAA0B,CAAC,EAAE,CAC3B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,iBAAiB,KACtB,IAAI,CAAC;IACV,wDAAwD;IACxD,+BAA+B,CAAC,EAAE,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,KACd,IAAI,CAAC;IACV,0DAA0D;IAC1D,iCAAiC,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"subagentManager.d.ts","sourceRoot":"","sources":["../../src/managers/subagentManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -407,7 +407,7 @@ export class SubagentManager {
|
|
|
407
407
|
if (instance.logStream && response) {
|
|
408
408
|
instance.logStream.write(`[${new Date().toISOString()}] Final response:\n${response}\n`);
|
|
409
409
|
}
|
|
410
|
-
instance.logStream?.write(`[${new Date().toISOString()}] Agent completed
|
|
410
|
+
instance.logStream?.write(`[${new Date().toISOString()}] Agent completed\n`);
|
|
411
411
|
instance.logStream?.end();
|
|
412
412
|
const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
|
|
413
413
|
if (task) {
|
|
@@ -542,16 +542,22 @@ export class SubagentManager {
|
|
|
542
542
|
this.callbacks.onSubagentAssistantMessageAdded(subagentId, messageId);
|
|
543
543
|
}
|
|
544
544
|
},
|
|
545
|
-
onAssistantContentUpdated: (
|
|
545
|
+
onAssistantContentUpdated: (params) => {
|
|
546
546
|
// Forward assistant content updates to parent via SubagentManager callbacks
|
|
547
547
|
if (this.callbacks?.onSubagentAssistantContentUpdated) {
|
|
548
|
-
this.callbacks.onSubagentAssistantContentUpdated(
|
|
548
|
+
this.callbacks.onSubagentAssistantContentUpdated({
|
|
549
|
+
...params,
|
|
550
|
+
subagentId,
|
|
551
|
+
});
|
|
549
552
|
}
|
|
550
553
|
},
|
|
551
|
-
onAssistantReasoningUpdated: (
|
|
554
|
+
onAssistantReasoningUpdated: (params) => {
|
|
552
555
|
// Forward assistant reasoning updates to parent via SubagentManager callbacks
|
|
553
556
|
if (this.callbacks?.onSubagentAssistantReasoningUpdated) {
|
|
554
|
-
this.callbacks.onSubagentAssistantReasoningUpdated(
|
|
557
|
+
this.callbacks.onSubagentAssistantReasoningUpdated({
|
|
558
|
+
...params,
|
|
559
|
+
subagentId,
|
|
560
|
+
});
|
|
555
561
|
}
|
|
556
562
|
},
|
|
557
563
|
onToolBlockUpdated: (params) => {
|
|
@@ -602,6 +608,12 @@ export class SubagentManager {
|
|
|
602
608
|
this.callbacks.onSubagentLatestTotalTokensChange(subagentId, tokens);
|
|
603
609
|
}
|
|
604
610
|
},
|
|
611
|
+
onErrorBlockAdded: (error) => {
|
|
612
|
+
const instance = this.instances.get(subagentId);
|
|
613
|
+
if (instance?.logStream) {
|
|
614
|
+
instance.logStream.write(`[${new Date().toISOString()}] Error: ${error}\n`);
|
|
615
|
+
}
|
|
616
|
+
},
|
|
605
617
|
};
|
|
606
618
|
}
|
|
607
619
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAuBtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UAmiBtB,CAAC"}
|
package/dist/tools/bashTool.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as fs from "fs";
|
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import * as os from "os";
|
|
5
5
|
import { logger } from "../utils/globalLogger.js";
|
|
6
|
+
import { resolveShellPath } from "../utils/shellResolver.js";
|
|
6
7
|
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
7
8
|
import { processToolResult } from "../utils/toolResultStorage.js";
|
|
8
9
|
import { BASH_MAX_OUTPUT_CHARS } from "../constants/toolLimits.js";
|
|
@@ -23,6 +24,7 @@ function isAutobackgroundingAllowed(command) {
|
|
|
23
24
|
*/
|
|
24
25
|
export const bashTool = {
|
|
25
26
|
name: BASH_TOOL_NAME,
|
|
27
|
+
isConcurrencySafe: false,
|
|
26
28
|
config: {
|
|
27
29
|
type: "function",
|
|
28
30
|
function: {
|
|
@@ -134,6 +136,15 @@ The working directory persists between commands. Try to maintain your current wo
|
|
|
134
136
|
error: "Command parameter is required and must be a string",
|
|
135
137
|
};
|
|
136
138
|
}
|
|
139
|
+
// Resolve shell path: on Windows, use Git Bash; on other platforms, use default
|
|
140
|
+
const shellPath = resolveShellPath();
|
|
141
|
+
if (process.platform === "win32" && !shellPath) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
content: "",
|
|
145
|
+
error: "Git Bash not found. Please install Git for Windows or set GIT_BASH_PATH environment variable.",
|
|
146
|
+
};
|
|
147
|
+
}
|
|
137
148
|
// Validate timeout
|
|
138
149
|
if (timeout !== undefined &&
|
|
139
150
|
(typeof timeout !== "number" || timeout < 0 || timeout > 600000)) {
|
|
@@ -202,7 +213,7 @@ The working directory persists between commands. Try to maintain your current wo
|
|
|
202
213
|
const tempCwdFile = path.join(os.tmpdir(), `wave_cwd_${Date.now()}_${Math.random().toString(36).substring(2, 11)}.tmp`);
|
|
203
214
|
const wrappedCommand = `${command} && pwd -P >| ${tempCwdFile}`;
|
|
204
215
|
const child = spawn(wrappedCommand, {
|
|
205
|
-
shell: true,
|
|
216
|
+
shell: shellPath || true,
|
|
206
217
|
stdio: "pipe",
|
|
207
218
|
detached: true,
|
|
208
219
|
cwd: context.workdir,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellResolver.d.ts","sourceRoot":"","sources":["../../src/utils/shellResolver.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,UAGlC,CAAC;AAEF,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAuBrD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
export const WINDOWS_GIT_BASH_PATHS = [
|
|
3
|
+
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
4
|
+
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
5
|
+
];
|
|
6
|
+
export function resolveShellPath() {
|
|
7
|
+
if (process.platform !== "win32") {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
if (process.env.GIT_BASH_PATH) {
|
|
11
|
+
return process.env.GIT_BASH_PATH;
|
|
12
|
+
}
|
|
13
|
+
const paths = [
|
|
14
|
+
...WINDOWS_GIT_BASH_PATHS,
|
|
15
|
+
process.env.LOCALAPPDATA
|
|
16
|
+
? `${process.env.LOCALAPPDATA}\\Programs\\Git\\bin\\bash.exe`
|
|
17
|
+
: null,
|
|
18
|
+
].filter(Boolean);
|
|
19
|
+
for (const path of paths) {
|
|
20
|
+
if (fs.existsSync(path)) {
|
|
21
|
+
return path;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -138,7 +138,7 @@ export class ForkedAgentManager {
|
|
|
138
138
|
`[${new Date().toISOString()}] Final response:\n${result}\n`,
|
|
139
139
|
);
|
|
140
140
|
entry.logStream.write(
|
|
141
|
-
`[${new Date().toISOString()}] Agent completed
|
|
141
|
+
`[${new Date().toISOString()}] Agent completed\n`,
|
|
142
142
|
);
|
|
143
143
|
entry.logStream.end();
|
|
144
144
|
}
|
|
@@ -43,17 +43,19 @@ export interface MessageManagerCallbacks {
|
|
|
43
43
|
// MODIFIED: Remove arguments for separation of concerns
|
|
44
44
|
onAssistantMessageAdded?: (messageId: string) => void;
|
|
45
45
|
// NEW: Streaming content callback - FR-001: receives chunk and accumulated content
|
|
46
|
-
onAssistantContentUpdated?: (
|
|
47
|
-
messageId: string
|
|
48
|
-
chunk: string
|
|
49
|
-
accumulated: string
|
|
50
|
-
|
|
46
|
+
onAssistantContentUpdated?: (params: {
|
|
47
|
+
messageId: string;
|
|
48
|
+
chunk: string;
|
|
49
|
+
accumulated: string;
|
|
50
|
+
stage: "streaming" | "end";
|
|
51
|
+
}) => void;
|
|
51
52
|
// NEW: Streaming reasoning callback
|
|
52
|
-
onAssistantReasoningUpdated?: (
|
|
53
|
-
messageId: string
|
|
54
|
-
chunk: string
|
|
55
|
-
accumulated: string
|
|
56
|
-
|
|
53
|
+
onAssistantReasoningUpdated?: (params: {
|
|
54
|
+
messageId: string;
|
|
55
|
+
chunk: string;
|
|
56
|
+
accumulated: string;
|
|
57
|
+
stage: "streaming" | "end";
|
|
58
|
+
}) => void;
|
|
57
59
|
onToolBlockUpdated?: (params: ToolBlockUpdateCallbackParams) => void;
|
|
58
60
|
onErrorBlockAdded?: (error: string) => void;
|
|
59
61
|
onCompactBlockAdded?: (content: string) => void;
|
|
@@ -469,7 +471,7 @@ export class MessageManager {
|
|
|
469
471
|
|
|
470
472
|
public updateToolBlock(params: AgentToolBlockUpdateParams): void {
|
|
471
473
|
// Finalize any streaming text/reasoning blocks before adding/updating a tool block
|
|
472
|
-
this.
|
|
474
|
+
this.finalizeStreamingBlocks();
|
|
473
475
|
const { messages: newMessages, messageId: resolvedMessageId } =
|
|
474
476
|
updateToolBlockInMessage({
|
|
475
477
|
messages: this.messages,
|
|
@@ -497,7 +499,7 @@ export class MessageManager {
|
|
|
497
499
|
params: Omit<AgentToolBlockUpdateParams, "id">,
|
|
498
500
|
): string {
|
|
499
501
|
// Finalize any streaming text/reasoning blocks before adding a tool block
|
|
500
|
-
this.
|
|
502
|
+
this.finalizeStreamingBlocks();
|
|
501
503
|
const { messages: newMessages, toolBlockId } =
|
|
502
504
|
addToolBlockToMessageInMessages(this.messages, messageId, params);
|
|
503
505
|
this.setMessages(newMessages);
|
|
@@ -681,6 +683,49 @@ export class MessageManager {
|
|
|
681
683
|
this.callbacks.onUsagesChange?.([...this._usages]);
|
|
682
684
|
}
|
|
683
685
|
|
|
686
|
+
/**
|
|
687
|
+
* Finalize a streaming block of the given type by setting its stage to "end".
|
|
688
|
+
* Fires the corresponding incremental callback with chunk="" to signal finalization.
|
|
689
|
+
* Does NOT call onMessagesChange — the caller is responsible for that.
|
|
690
|
+
* Returns true if a block was finalized.
|
|
691
|
+
*/
|
|
692
|
+
private finalizeStreamingBlock(
|
|
693
|
+
lastMessage: Message,
|
|
694
|
+
type: "text" | "reasoning",
|
|
695
|
+
): boolean {
|
|
696
|
+
const index = lastMessage.blocks.findIndex(
|
|
697
|
+
(block) =>
|
|
698
|
+
block.type === type &&
|
|
699
|
+
(block as { stage?: string }).stage === "streaming",
|
|
700
|
+
);
|
|
701
|
+
if (index < 0) return false;
|
|
702
|
+
|
|
703
|
+
const block = lastMessage.blocks[index] as {
|
|
704
|
+
type: "text" | "reasoning";
|
|
705
|
+
content: string;
|
|
706
|
+
stage?: string;
|
|
707
|
+
};
|
|
708
|
+
lastMessage.blocks[index] = {
|
|
709
|
+
type: block.type,
|
|
710
|
+
content: block.content,
|
|
711
|
+
stage: "end" as const,
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
// Fire incremental callback to signal finalization
|
|
715
|
+
const callbackParams = {
|
|
716
|
+
messageId: lastMessage.id,
|
|
717
|
+
chunk: "",
|
|
718
|
+
accumulated: block.content,
|
|
719
|
+
stage: "end" as const,
|
|
720
|
+
};
|
|
721
|
+
if (type === "text") {
|
|
722
|
+
this.callbacks.onAssistantContentUpdated?.(callbackParams);
|
|
723
|
+
} else {
|
|
724
|
+
this.callbacks.onAssistantReasoningUpdated?.(callbackParams);
|
|
725
|
+
}
|
|
726
|
+
return true;
|
|
727
|
+
}
|
|
728
|
+
|
|
684
729
|
/**
|
|
685
730
|
* Update the current assistant message content during streaming
|
|
686
731
|
* This method updates the last assistant message's content without creating a new message
|
|
@@ -693,23 +738,7 @@ export class MessageManager {
|
|
|
693
738
|
if (lastMessage.role !== "assistant") return;
|
|
694
739
|
|
|
695
740
|
// Finalize any streaming reasoning blocks before text content arrives
|
|
696
|
-
|
|
697
|
-
(block) =>
|
|
698
|
-
block.type === "reasoning" &&
|
|
699
|
-
(block as { stage?: string }).stage === "streaming",
|
|
700
|
-
);
|
|
701
|
-
if (reasoningIndex >= 0) {
|
|
702
|
-
const reasoningBlock = lastMessage.blocks[reasoningIndex] as {
|
|
703
|
-
type: "reasoning";
|
|
704
|
-
content: string;
|
|
705
|
-
stage?: string;
|
|
706
|
-
};
|
|
707
|
-
lastMessage.blocks[reasoningIndex] = {
|
|
708
|
-
type: "reasoning" as const,
|
|
709
|
-
content: reasoningBlock.content,
|
|
710
|
-
stage: "end" as const,
|
|
711
|
-
};
|
|
712
|
-
}
|
|
741
|
+
this.finalizeStreamingBlock(lastMessage, "reasoning");
|
|
713
742
|
|
|
714
743
|
// Get the current content to calculate the chunk
|
|
715
744
|
const textBlockIndex = lastMessage.blocks.findIndex(
|
|
@@ -745,11 +774,12 @@ export class MessageManager {
|
|
|
745
774
|
}
|
|
746
775
|
|
|
747
776
|
// FR-001: Trigger callbacks with chunk and accumulated content
|
|
748
|
-
this.callbacks.onAssistantContentUpdated?.(
|
|
749
|
-
lastMessage.id,
|
|
777
|
+
this.callbacks.onAssistantContentUpdated?.({
|
|
778
|
+
messageId: lastMessage.id,
|
|
750
779
|
chunk,
|
|
751
|
-
newAccumulatedContent,
|
|
752
|
-
|
|
780
|
+
accumulated: newAccumulatedContent,
|
|
781
|
+
stage: "streaming",
|
|
782
|
+
});
|
|
753
783
|
|
|
754
784
|
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
755
785
|
|
|
@@ -767,23 +797,7 @@ export class MessageManager {
|
|
|
767
797
|
if (lastMessage.role !== "assistant") return;
|
|
768
798
|
|
|
769
799
|
// Finalize any streaming text blocks before reasoning content arrives
|
|
770
|
-
|
|
771
|
-
(block) =>
|
|
772
|
-
block.type === "text" &&
|
|
773
|
-
(block as { stage?: string }).stage === "streaming",
|
|
774
|
-
);
|
|
775
|
-
if (textIndex >= 0) {
|
|
776
|
-
const textBlock = lastMessage.blocks[textIndex] as {
|
|
777
|
-
type: "text";
|
|
778
|
-
content: string;
|
|
779
|
-
stage?: string;
|
|
780
|
-
};
|
|
781
|
-
lastMessage.blocks[textIndex] = {
|
|
782
|
-
type: "text" as const,
|
|
783
|
-
content: textBlock.content,
|
|
784
|
-
stage: "end" as const,
|
|
785
|
-
};
|
|
786
|
-
}
|
|
800
|
+
this.finalizeStreamingBlock(lastMessage, "text");
|
|
787
801
|
|
|
788
802
|
// Get the current reasoning content to calculate the chunk
|
|
789
803
|
const reasoningBlockIndex = lastMessage.blocks.findIndex(
|
|
@@ -819,46 +833,33 @@ export class MessageManager {
|
|
|
819
833
|
}
|
|
820
834
|
|
|
821
835
|
// Trigger callbacks with chunk and accumulated reasoning content
|
|
822
|
-
this.callbacks.onAssistantReasoningUpdated?.(
|
|
823
|
-
lastMessage.id,
|
|
836
|
+
this.callbacks.onAssistantReasoningUpdated?.({
|
|
837
|
+
messageId: lastMessage.id,
|
|
824
838
|
chunk,
|
|
825
|
-
newAccumulatedReasoning,
|
|
826
|
-
|
|
839
|
+
accumulated: newAccumulatedReasoning,
|
|
840
|
+
stage: "streaming",
|
|
841
|
+
});
|
|
827
842
|
|
|
828
843
|
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
829
844
|
}
|
|
830
845
|
|
|
831
|
-
/**
|
|
832
|
-
* Public wrapper for finalizeCurrentStreamingBlocks.
|
|
833
|
-
* Finalizes text/reasoning blocks after streaming completes (e.g. final response with no tools).
|
|
834
|
-
*/
|
|
835
|
-
public finalizeStreamingBlocks(): void {
|
|
836
|
-
this.finalizeCurrentStreamingBlocks();
|
|
837
|
-
}
|
|
838
|
-
|
|
839
846
|
/**
|
|
840
847
|
* Finalize streaming text/reasoning blocks by setting their stage to "end".
|
|
841
|
-
* Called when a new block (e.g. tool) is appended during streaming.
|
|
848
|
+
* Called when a new block (e.g. tool) is appended during streaming, or when streaming completes.
|
|
849
|
+
* Fires incremental callbacks for each finalized block.
|
|
842
850
|
*/
|
|
843
|
-
|
|
851
|
+
public finalizeStreamingBlocks(): void {
|
|
844
852
|
if (this.messages.length === 0) return;
|
|
845
853
|
const lastMessage = this.messages[this.messages.length - 1];
|
|
846
854
|
if (lastMessage.role !== "assistant") return;
|
|
847
855
|
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
return { ...block, stage: "end" as const };
|
|
854
|
-
}
|
|
855
|
-
return block;
|
|
856
|
-
});
|
|
856
|
+
const textFinalized = this.finalizeStreamingBlock(lastMessage, "text");
|
|
857
|
+
const reasoningFinalized = this.finalizeStreamingBlock(
|
|
858
|
+
lastMessage,
|
|
859
|
+
"reasoning",
|
|
860
|
+
);
|
|
857
861
|
|
|
858
|
-
|
|
859
|
-
const changed = newBlocks.some((b, i) => b !== lastMessage.blocks[i]);
|
|
860
|
-
if (changed) {
|
|
861
|
-
lastMessage.blocks = newBlocks;
|
|
862
|
+
if (textFinalized || reasoningFinalized) {
|
|
862
863
|
this.callbacks.onMessagesChange?.([...this.messages]);
|
|
863
864
|
}
|
|
864
865
|
}
|
|
@@ -38,19 +38,21 @@ export interface SubagentManagerCallbacks {
|
|
|
38
38
|
messageId: string,
|
|
39
39
|
) => void;
|
|
40
40
|
/** Triggered during subagent content streaming updates */
|
|
41
|
-
onSubagentAssistantContentUpdated?: (
|
|
42
|
-
subagentId: string
|
|
43
|
-
messageId: string
|
|
44
|
-
chunk: string
|
|
45
|
-
accumulated: string
|
|
46
|
-
|
|
41
|
+
onSubagentAssistantContentUpdated?: (params: {
|
|
42
|
+
subagentId: string;
|
|
43
|
+
messageId: string;
|
|
44
|
+
chunk: string;
|
|
45
|
+
accumulated: string;
|
|
46
|
+
stage: "streaming" | "end";
|
|
47
|
+
}) => void;
|
|
47
48
|
/** Triggered during subagent reasoning streaming updates */
|
|
48
|
-
onSubagentAssistantReasoningUpdated?: (
|
|
49
|
-
subagentId: string
|
|
50
|
-
messageId: string
|
|
51
|
-
chunk: string
|
|
52
|
-
accumulated: string
|
|
53
|
-
|
|
49
|
+
onSubagentAssistantReasoningUpdated?: (params: {
|
|
50
|
+
subagentId: string;
|
|
51
|
+
messageId: string;
|
|
52
|
+
chunk: string;
|
|
53
|
+
accumulated: string;
|
|
54
|
+
stage: "streaming" | "end";
|
|
55
|
+
}) => void;
|
|
54
56
|
/** Triggered when subagent tool block is updated */
|
|
55
57
|
onSubagentToolBlockUpdated?: (
|
|
56
58
|
subagentId: string,
|
|
@@ -629,7 +631,7 @@ export class SubagentManager {
|
|
|
629
631
|
);
|
|
630
632
|
}
|
|
631
633
|
instance.logStream?.write(
|
|
632
|
-
`[${new Date().toISOString()}] Agent completed
|
|
634
|
+
`[${new Date().toISOString()}] Agent completed\n`,
|
|
633
635
|
);
|
|
634
636
|
instance.logStream?.end();
|
|
635
637
|
const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
|
|
@@ -789,34 +791,32 @@ export class SubagentManager {
|
|
|
789
791
|
}
|
|
790
792
|
},
|
|
791
793
|
|
|
792
|
-
onAssistantContentUpdated: (
|
|
793
|
-
messageId: string
|
|
794
|
-
chunk: string
|
|
795
|
-
accumulated: string
|
|
796
|
-
|
|
794
|
+
onAssistantContentUpdated: (params: {
|
|
795
|
+
messageId: string;
|
|
796
|
+
chunk: string;
|
|
797
|
+
accumulated: string;
|
|
798
|
+
stage: "streaming" | "end";
|
|
799
|
+
}) => {
|
|
797
800
|
// Forward assistant content updates to parent via SubagentManager callbacks
|
|
798
801
|
if (this.callbacks?.onSubagentAssistantContentUpdated) {
|
|
799
|
-
this.callbacks.onSubagentAssistantContentUpdated(
|
|
802
|
+
this.callbacks.onSubagentAssistantContentUpdated({
|
|
803
|
+
...params,
|
|
800
804
|
subagentId,
|
|
801
|
-
|
|
802
|
-
chunk,
|
|
803
|
-
accumulated,
|
|
804
|
-
);
|
|
805
|
+
});
|
|
805
806
|
}
|
|
806
807
|
},
|
|
807
|
-
onAssistantReasoningUpdated: (
|
|
808
|
-
messageId: string
|
|
809
|
-
chunk: string
|
|
810
|
-
accumulated: string
|
|
811
|
-
|
|
808
|
+
onAssistantReasoningUpdated: (params: {
|
|
809
|
+
messageId: string;
|
|
810
|
+
chunk: string;
|
|
811
|
+
accumulated: string;
|
|
812
|
+
stage: "streaming" | "end";
|
|
813
|
+
}) => {
|
|
812
814
|
// Forward assistant reasoning updates to parent via SubagentManager callbacks
|
|
813
815
|
if (this.callbacks?.onSubagentAssistantReasoningUpdated) {
|
|
814
|
-
this.callbacks.onSubagentAssistantReasoningUpdated(
|
|
816
|
+
this.callbacks.onSubagentAssistantReasoningUpdated({
|
|
817
|
+
...params,
|
|
815
818
|
subagentId,
|
|
816
|
-
|
|
817
|
-
chunk,
|
|
818
|
-
accumulated,
|
|
819
|
-
);
|
|
819
|
+
});
|
|
820
820
|
}
|
|
821
821
|
},
|
|
822
822
|
|
|
@@ -876,6 +876,15 @@ export class SubagentManager {
|
|
|
876
876
|
this.callbacks.onSubagentLatestTotalTokensChange(subagentId, tokens);
|
|
877
877
|
}
|
|
878
878
|
},
|
|
879
|
+
|
|
880
|
+
onErrorBlockAdded: (error: string) => {
|
|
881
|
+
const instance = this.instances.get(subagentId);
|
|
882
|
+
if (instance?.logStream) {
|
|
883
|
+
instance.logStream.write(
|
|
884
|
+
`[${new Date().toISOString()}] Error: ${error}\n`,
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
},
|
|
879
888
|
};
|
|
880
889
|
}
|
|
881
890
|
}
|
package/src/tools/bashTool.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as fs from "fs";
|
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import * as os from "os";
|
|
5
5
|
import { logger } from "../utils/globalLogger.js";
|
|
6
|
+
import { resolveShellPath } from "../utils/shellResolver.js";
|
|
6
7
|
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
7
8
|
import { processToolResult } from "../utils/toolResultStorage.js";
|
|
8
9
|
import { BASH_MAX_OUTPUT_CHARS } from "../constants/toolLimits.js";
|
|
@@ -34,6 +35,7 @@ function isAutobackgroundingAllowed(command: string): boolean {
|
|
|
34
35
|
*/
|
|
35
36
|
export const bashTool: ToolPlugin = {
|
|
36
37
|
name: BASH_TOOL_NAME,
|
|
38
|
+
isConcurrencySafe: false,
|
|
37
39
|
config: {
|
|
38
40
|
type: "function",
|
|
39
41
|
function: {
|
|
@@ -151,6 +153,17 @@ The working directory persists between commands. Try to maintain your current wo
|
|
|
151
153
|
};
|
|
152
154
|
}
|
|
153
155
|
|
|
156
|
+
// Resolve shell path: on Windows, use Git Bash; on other platforms, use default
|
|
157
|
+
const shellPath = resolveShellPath();
|
|
158
|
+
if (process.platform === "win32" && !shellPath) {
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
content: "",
|
|
162
|
+
error:
|
|
163
|
+
"Git Bash not found. Please install Git for Windows or set GIT_BASH_PATH environment variable.",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
154
167
|
// Validate timeout
|
|
155
168
|
if (
|
|
156
169
|
timeout !== undefined &&
|
|
@@ -236,7 +249,7 @@ The working directory persists between commands. Try to maintain your current wo
|
|
|
236
249
|
const wrappedCommand = `${command} && pwd -P >| ${tempCwdFile}`;
|
|
237
250
|
|
|
238
251
|
const child: ChildProcess = spawn(wrappedCommand, {
|
|
239
|
-
shell: true,
|
|
252
|
+
shell: shellPath || true,
|
|
240
253
|
stdio: "pipe",
|
|
241
254
|
detached: true,
|
|
242
255
|
cwd: context.workdir,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export const WINDOWS_GIT_BASH_PATHS = [
|
|
4
|
+
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
5
|
+
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export function resolveShellPath(): string | undefined {
|
|
9
|
+
if (process.platform !== "win32") {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (process.env.GIT_BASH_PATH) {
|
|
14
|
+
return process.env.GIT_BASH_PATH;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const paths = [
|
|
18
|
+
...WINDOWS_GIT_BASH_PATHS,
|
|
19
|
+
process.env.LOCALAPPDATA
|
|
20
|
+
? `${process.env.LOCALAPPDATA}\\Programs\\Git\\bin\\bash.exe`
|
|
21
|
+
: null,
|
|
22
|
+
].filter(Boolean) as string[];
|
|
23
|
+
|
|
24
|
+
for (const path of paths) {
|
|
25
|
+
if (fs.existsSync(path)) {
|
|
26
|
+
return path;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|