-
Notifications
You must be signed in to change notification settings - Fork 748
fix(chat): fix shell command execution output markdown block issue #6995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -117,6 +117,14 @@ export interface CommandValidation { | |||
| warning?: string | ||||
| } | ||||
|
|
||||
| // Interface for timestamped output chunks | ||||
| interface TimestampedChunk { | ||||
| timestamp: number | ||||
| isStdout: boolean | ||||
| content: string | ||||
| isFirst: boolean | ||||
| } | ||||
|
|
||||
| export class ExecuteBash { | ||||
| private readonly command: string | ||||
| private readonly workingDirectory?: string | ||||
|
|
@@ -207,8 +215,33 @@ export class ExecuteBash { | |||
| const stdoutBuffer: string[] = [] | ||||
| const stderrBuffer: string[] = [] | ||||
|
|
||||
| let firstChunk = true | ||||
| let firstStderrChunk = true | ||||
| // Use a queue to maintain chronological order of chunks | ||||
| // This ensures that the output is processed in the exact order it was generated by the child process. | ||||
| const outputQueue: TimestampedChunk[] = [] | ||||
| let processingQueue = false | ||||
| const firstChunk = new AtomicBoolean(true) | ||||
|
||||
| private static _asyncLock = new AsyncLock() |
But this risks deadlock. It would be less risky to collect stdout and stderr separately, then combine them later, if that's important to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think as the javascript event loop is a single thread, we can use a simple boolean variable(isFirstChunk) in closure to replace the AsyncLock in my use case.
-
The onStdout and onStderr callbacks are never truly executing simultaneously for one bash command execution - they're queued and executed one after another on the event loop.
-
The only shared state is the simple boolean flag (isFirstChunk) that's only set once from true to false. and there is no any other async operations.
Overall, the usage of AsyncLock adds unnecessary overhead for such a simple operation.
I can remove the atomic inner class(as it causes confusion). just use var and a function.
// Use a closure boolean value firstChunk and a function to get and set its value
let isFirstChunk = true
const getAndSetFirstChunk = (newValue: boolean): boolean => {
const oldValue = isFirstChunk
isFirstChunk = newValue
return oldValue
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set its value atomically
what is the purpose of mentioning this? there is no atomicity provided by this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, remove it from the comment.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
? javascript is single-thread, what is the purpose of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, javascript is single-thread, but we have the use case that one process can send bash command execution output to stdout and stderr, which the streaming of stdout and stderr is async.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
javascript has a lot of asynchrony, but each async execution context is executed fully until a async call, and is not "preemptible". getAndSet() is not doing anything useful here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would be a field that actually needs a brief comment that gives insight into its purpose.