MCPcopy Create free account
hub / github.com/TanStack/ai / createBootstrapShell

Function createBootstrapShell

packages/ai-sandbox/src/shell.ts:74–199  ·  view source on GitHub ↗
(
  handle: SandboxHandle,
  opts: BootstrapShellOptions = {},
)

Source from the content-addressed store, hash-verified

72 * The counter `N` is a module-level monotonic integer — no Date.now / random.
73 */
74export async function createBootstrapShell(
75 handle: SandboxHandle,
76 opts: BootstrapShellOptions = {},
77): Promise<BootstrapShell> {
78 // Providers without a writable host→process stdin can't run the sentinel-echo
79 // protocol below (it feeds commands over stdin), so use the exec-backed shell.
80 if (!handle.capabilities.writableStdin) {
81 return createExecBootstrapShell(handle, opts)
82 }
83 const proc = await handle.process.spawn('sh', { cwd: opts.cwd })
84
85 /*
86 * We need to read stdout lines across multiple run() calls while keeping
87 * the iterator open. Buffer chunks into lines manually.
88 */
89 const lineBuffer: Array<string> = []
90 let pending: Array<(line: string) => void> = []
91 let streamDone = false
92
93 /** Feed the stdout async-iterable into the shared line queue. */
94 async function drainStdout(): Promise<void> {
95 let partial = ''
96 for await (const chunk of proc.stdout) {
97 partial += chunk
98 const parts = partial.split('\n')
99 // All but the last element are complete lines.
100 for (let i = 0; i < parts.length - 1; i++) {
101 const line = parts[i] as string
102 const resolver = pending.shift()
103 if (resolver !== undefined) {
104 resolver(line)
105 } else {
106 lineBuffer.push(line)
107 }
108 }
109 partial = parts[parts.length - 1] as string
110 }
111 // Flush any trailing partial line.
112 if (partial.length > 0) {
113 const line = partial
114 const resolver = pending.shift()
115 if (resolver !== undefined) {
116 resolver(line)
117 } else {
118 lineBuffer.push(line)
119 }
120 }
121 streamDone = true
122 // Resolve any remaining waiters with an empty sentinel so they unblock.
123 for (const resolver of pending) {
124 resolver('')
125 }
126 pending = []
127 }
128
129 // Start draining immediately; do NOT await — runs concurrently.
130 const drainPromise = drainStdout()
131

Callers 2

bootstrapWorkspaceFunction · 0.90
shell.test.tsFile · 0.90

Calls 2

createExecBootstrapShellFunction · 0.85
drainStdoutFunction · 0.85

Tested by

no test coverage detected