- captureExec: stop wrapping with { … ; }; Bare shell splits ; naively, so {
became argv[0] (“unknown command: {”). Redirect only, append EXIT:N from
BARE_OS_EXIT_STATUS after execLine.
- Streaming: normalize newlines for SSH PTY (bareOsPtyStdoutCrlf on SSH child ctx,
bareAgentWriteOut uses ctx).
This commit is contained in:
+34
-7
@@ -3368,14 +3368,13 @@ async function bareAgentDispatchTool(o) {
|
||||
async function captureExec(line, timeoutMs, captureOpts) {
|
||||
const outPath = paths.cmdOut
|
||||
const captureExit = Boolean(captureOpts && captureOpts.captureExit)
|
||||
const wrapped = captureExit
|
||||
? '{ ' +
|
||||
/**
|
||||
* Do not wrap with `{ cmd ; }` — Bare OS `splitTokensBySemicolon` splits on every `;`
|
||||
* at depth 0 and does not treat `{ … }` as a compound, so `{` became argv[0]
|
||||
* (`unknown command: {`). Redirect only; read exit from env after `execLine`.
|
||||
*/
|
||||
const wrapped =
|
||||
line +
|
||||
' ; } > ' +
|
||||
bareAgentShellQuote(outPath) +
|
||||
' 2>&1; printf "\\nEXIT:%s\\n" $? >> ' +
|
||||
bareAgentShellQuote(outPath)
|
||||
: line +
|
||||
' > ' +
|
||||
bareAgentShellQuote(outPath) +
|
||||
' 2>&1'
|
||||
@@ -3409,6 +3408,34 @@ async function bareAgentDispatchTool(o) {
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
if (captureExit) {
|
||||
const env = ctx.vfs?.env && typeof ctx.vfs.env === 'object' ? ctx.vfs.env : null
|
||||
const rawEc =
|
||||
env && env.BARE_OS_EXIT_STATUS != null && env.BARE_OS_EXIT_STATUS !== ''
|
||||
? env.BARE_OS_EXIT_STATUS
|
||||
: ctx.exitCode
|
||||
const n = Number(rawEc)
|
||||
const codeStr = String(Number.isFinite(n) ? n : 0)
|
||||
const exitLine = '\nEXIT:' + codeStr + '\n'
|
||||
captured += exitLine
|
||||
try {
|
||||
if (vfs?.readFile && vfs?.writeFile && ctx.b4a && typeof ctx.b4a.concat === 'function') {
|
||||
let prev = await vfs.readFile(outPath)
|
||||
const prevBytes =
|
||||
prev && prev.length
|
||||
? prev instanceof Uint8Array
|
||||
? prev
|
||||
: ctx.b4a.from(prev)
|
||||
: ctx.b4a.from('')
|
||||
await vfs.writeFile(
|
||||
outPath,
|
||||
ctx.b4a.concat([prevBytes, ctx.b4a.from(exitLine)])
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
const max = 120_000
|
||||
if (captured.length > max) captured = captured.slice(0, max) + '\n… truncated'
|
||||
return { ok: true, stdout_stderr: captured }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"profileId": "bare-os-posix-like",
|
||||
"generatedAt": "2026-04-22T21:10:53.539Z",
|
||||
"generatedAt": "2026-04-22T21:32:31.052Z",
|
||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||
"commandIndex": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1776892253538,
|
||||
"atMs": 1776893551051,
|
||||
"commands": [
|
||||
"agent",
|
||||
"arch",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -549,14 +549,13 @@ async function bareAgentDispatchTool(o) {
|
||||
async function captureExec(line, timeoutMs, captureOpts) {
|
||||
const outPath = paths.cmdOut
|
||||
const captureExit = Boolean(captureOpts && captureOpts.captureExit)
|
||||
const wrapped = captureExit
|
||||
? '{ ' +
|
||||
/**
|
||||
* Do not wrap with `{ cmd ; }` — Bare OS `splitTokensBySemicolon` splits on every `;`
|
||||
* at depth 0 and does not treat `{ … }` as a compound, so `{` became argv[0]
|
||||
* (`unknown command: {`). Redirect only; read exit from env after `execLine`.
|
||||
*/
|
||||
const wrapped =
|
||||
line +
|
||||
' ; } > ' +
|
||||
bareAgentShellQuote(outPath) +
|
||||
' 2>&1; printf "\\nEXIT:%s\\n" $? >> ' +
|
||||
bareAgentShellQuote(outPath)
|
||||
: line +
|
||||
' > ' +
|
||||
bareAgentShellQuote(outPath) +
|
||||
' 2>&1'
|
||||
@@ -590,6 +589,34 @@ async function bareAgentDispatchTool(o) {
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
if (captureExit) {
|
||||
const env = ctx.vfs?.env && typeof ctx.vfs.env === 'object' ? ctx.vfs.env : null
|
||||
const rawEc =
|
||||
env && env.BARE_OS_EXIT_STATUS != null && env.BARE_OS_EXIT_STATUS !== ''
|
||||
? env.BARE_OS_EXIT_STATUS
|
||||
: ctx.exitCode
|
||||
const n = Number(rawEc)
|
||||
const codeStr = String(Number.isFinite(n) ? n : 0)
|
||||
const exitLine = '\nEXIT:' + codeStr + '\n'
|
||||
captured += exitLine
|
||||
try {
|
||||
if (vfs?.readFile && vfs?.writeFile && ctx.b4a && typeof ctx.b4a.concat === 'function') {
|
||||
let prev = await vfs.readFile(outPath)
|
||||
const prevBytes =
|
||||
prev && prev.length
|
||||
? prev instanceof Uint8Array
|
||||
? prev
|
||||
: ctx.b4a.from(prev)
|
||||
: ctx.b4a.from('')
|
||||
await vfs.writeFile(
|
||||
outPath,
|
||||
ctx.b4a.concat([prevBytes, ctx.b4a.from(exitLine)])
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
const max = 120_000
|
||||
if (captured.length > max) captured = captured.slice(0, max) + '\n… truncated'
|
||||
return { ok: true, stdout_stderr: captured }
|
||||
|
||||
@@ -3368,14 +3368,13 @@ async function bareAgentDispatchTool(o) {
|
||||
async function captureExec(line, timeoutMs, captureOpts) {
|
||||
const outPath = paths.cmdOut
|
||||
const captureExit = Boolean(captureOpts && captureOpts.captureExit)
|
||||
const wrapped = captureExit
|
||||
? '{ ' +
|
||||
/**
|
||||
* Do not wrap with `{ cmd ; }` — Bare OS `splitTokensBySemicolon` splits on every `;`
|
||||
* at depth 0 and does not treat `{ … }` as a compound, so `{` became argv[0]
|
||||
* (`unknown command: {`). Redirect only; read exit from env after `execLine`.
|
||||
*/
|
||||
const wrapped =
|
||||
line +
|
||||
' ; } > ' +
|
||||
bareAgentShellQuote(outPath) +
|
||||
' 2>&1; printf "\\nEXIT:%s\\n" $? >> ' +
|
||||
bareAgentShellQuote(outPath)
|
||||
: line +
|
||||
' > ' +
|
||||
bareAgentShellQuote(outPath) +
|
||||
' 2>&1'
|
||||
@@ -3409,6 +3408,34 @@ async function bareAgentDispatchTool(o) {
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
if (captureExit) {
|
||||
const env = ctx.vfs?.env && typeof ctx.vfs.env === 'object' ? ctx.vfs.env : null
|
||||
const rawEc =
|
||||
env && env.BARE_OS_EXIT_STATUS != null && env.BARE_OS_EXIT_STATUS !== ''
|
||||
? env.BARE_OS_EXIT_STATUS
|
||||
: ctx.exitCode
|
||||
const n = Number(rawEc)
|
||||
const codeStr = String(Number.isFinite(n) ? n : 0)
|
||||
const exitLine = '\nEXIT:' + codeStr + '\n'
|
||||
captured += exitLine
|
||||
try {
|
||||
if (vfs?.readFile && vfs?.writeFile && ctx.b4a && typeof ctx.b4a.concat === 'function') {
|
||||
let prev = await vfs.readFile(outPath)
|
||||
const prevBytes =
|
||||
prev && prev.length
|
||||
? prev instanceof Uint8Array
|
||||
? prev
|
||||
: ctx.b4a.from(prev)
|
||||
: ctx.b4a.from('')
|
||||
await vfs.writeFile(
|
||||
outPath,
|
||||
ctx.b4a.concat([prevBytes, ctx.b4a.from(exitLine)])
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
const max = 120_000
|
||||
if (captured.length > max) captured = captured.slice(0, max) + '\n… truncated'
|
||||
return { ok: true, stdout_stderr: captured }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"profileId": "bare-os-posix-like",
|
||||
"generatedAt": "2026-04-22T21:10:53.539Z",
|
||||
"generatedAt": "2026-04-22T21:32:31.052Z",
|
||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||
"commandIndex": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1776892253538,
|
||||
"atMs": 1776893551051,
|
||||
"commands": [
|
||||
"agent",
|
||||
"arch",
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user