@deepagents/context 6.1.0 → 6.1.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/README.md +3 -2
- package/dist/index.js +257 -31
- package/dist/index.js.map +3 -3
- package/dist/lib/chat.d.ts +2 -2
- package/dist/lib/chat.d.ts.map +1 -1
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/sandbox/agent-os-sandbox.d.ts +1 -1
- package/dist/lib/sandbox/agent-os-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/apple-container-sandbox.d.ts +3 -3
- package/dist/lib/sandbox/apple-container-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/container-sandbox.d.ts +1 -0
- package/dist/lib/sandbox/container-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/daytona-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/docker-sandbox.d.ts +3 -3
- package/dist/lib/sandbox/docker-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/microsandbox-sandbox.d.ts +3 -3
- package/dist/lib/sandbox/microsandbox-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/shell-quote.d.ts +1 -1
- package/dist/lib/sandbox/strace/index.d.ts +3 -3
- package/dist/lib/sandbox/strace/index.d.ts.map +1 -1
- package/dist/lib/sandbox/strace/index.js +2 -2
- package/dist/lib/sandbox/strace/index.js.map +2 -2
- package/dist/lib/sandbox/types.d.ts +5 -0
- package/dist/lib/sandbox/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -317,8 +317,9 @@ points.
|
|
|
317
317
|
For `target: 'tool-output'`, use `toolOutput(...)` or inspect
|
|
318
318
|
`ctx.toolOutcome`. The outcome is available after a tool reaches
|
|
319
319
|
`output-available`, `output-error`, or `output-denied`, but before the next model
|
|
320
|
-
generation. Assistant-history predicates such as `toolCalled(...)`
|
|
321
|
-
|
|
320
|
+
generation. Assistant-history predicates such as `toolCalled(...)` describe
|
|
321
|
+
tool parts visible in the current assistant segment; use `toolOutput(...)` when
|
|
322
|
+
you need the raw outcome currently being evaluated.
|
|
322
323
|
|
|
323
324
|
```ts
|
|
324
325
|
import {
|
package/dist/index.js
CHANGED
|
@@ -840,6 +840,7 @@ import { getErrorMessage } from "@ai-sdk/provider";
|
|
|
840
840
|
import {
|
|
841
841
|
convertToModelMessages as convertToModelMessages2,
|
|
842
842
|
generateId as generateId5,
|
|
843
|
+
isStaticToolUIPart as isStaticToolUIPart2,
|
|
843
844
|
validateUIMessages
|
|
844
845
|
} from "ai";
|
|
845
846
|
|
|
@@ -3959,6 +3960,58 @@ function toolOutcomesFromStep(content) {
|
|
|
3959
3960
|
}
|
|
3960
3961
|
return outcomes;
|
|
3961
3962
|
}
|
|
3963
|
+
function terminalToolPartsFromStep(content) {
|
|
3964
|
+
return content.flatMap((part) => {
|
|
3965
|
+
if (part.type === "tool-result" && part.dynamic !== true) {
|
|
3966
|
+
return [
|
|
3967
|
+
{
|
|
3968
|
+
type: `tool-${part.toolName}`,
|
|
3969
|
+
toolCallId: part.toolCallId,
|
|
3970
|
+
state: "output-available",
|
|
3971
|
+
input: part.input,
|
|
3972
|
+
output: part.output === void 0 ? null : part.output
|
|
3973
|
+
}
|
|
3974
|
+
];
|
|
3975
|
+
}
|
|
3976
|
+
if (part.type === "tool-error" && part.dynamic !== true) {
|
|
3977
|
+
return [
|
|
3978
|
+
{
|
|
3979
|
+
type: `tool-${part.toolName}`,
|
|
3980
|
+
toolCallId: part.toolCallId,
|
|
3981
|
+
state: "output-error",
|
|
3982
|
+
input: part.input,
|
|
3983
|
+
errorText: getErrorMessage(part.error)
|
|
3984
|
+
}
|
|
3985
|
+
];
|
|
3986
|
+
}
|
|
3987
|
+
if (part.type === "tool-approval-response" && part.approved === false && part.toolCall.dynamic !== true) {
|
|
3988
|
+
return [
|
|
3989
|
+
{
|
|
3990
|
+
type: `tool-${part.toolCall.toolName}`,
|
|
3991
|
+
toolCallId: part.toolCall.toolCallId,
|
|
3992
|
+
state: "output-denied",
|
|
3993
|
+
input: part.toolCall.input,
|
|
3994
|
+
approval: {
|
|
3995
|
+
id: part.approvalId,
|
|
3996
|
+
approved: false,
|
|
3997
|
+
...part.reason === void 0 ? {} : { reason: part.reason }
|
|
3998
|
+
}
|
|
3999
|
+
}
|
|
4000
|
+
];
|
|
4001
|
+
}
|
|
4002
|
+
return [];
|
|
4003
|
+
});
|
|
4004
|
+
}
|
|
4005
|
+
function mergeTerminalToolParts(message2, liveParts) {
|
|
4006
|
+
const remaining = new Map(liveParts);
|
|
4007
|
+
const parts = message2.parts.map((part) => {
|
|
4008
|
+
if (!isStaticToolUIPart2(part)) return part;
|
|
4009
|
+
remaining.delete(part.toolCallId);
|
|
4010
|
+
return part;
|
|
4011
|
+
});
|
|
4012
|
+
parts.push(...remaining.values());
|
|
4013
|
+
return { ...message2, parts };
|
|
4014
|
+
}
|
|
3962
4015
|
var ContextEngine = class _ContextEngine {
|
|
3963
4016
|
/** Non-message fragments (role, hints, etc.) - not persisted in graph */
|
|
3964
4017
|
#fragments = [];
|
|
@@ -4371,12 +4424,24 @@ var ContextEngine = class _ContextEngine {
|
|
|
4371
4424
|
const enableSteer = options.steer ?? true;
|
|
4372
4425
|
const session = {
|
|
4373
4426
|
firedOnceIds: /* @__PURE__ */ new Set(),
|
|
4374
|
-
|
|
4427
|
+
terminalToolParts: /* @__PURE__ */ new Map(),
|
|
4428
|
+
segments: [],
|
|
4429
|
+
initialStepStarts: null,
|
|
4430
|
+
stepOffset: 0,
|
|
4431
|
+
lastStepNumber: null
|
|
4375
4432
|
};
|
|
4376
4433
|
this.#currentReminderSession = session;
|
|
4377
4434
|
return async ({ steps, stepNumber, messages }) => {
|
|
4435
|
+
if (stepNumber === 0 && session.lastStepNumber !== null) {
|
|
4436
|
+
session.stepOffset += session.lastStepNumber + 1;
|
|
4437
|
+
}
|
|
4438
|
+
session.lastStepNumber = stepNumber;
|
|
4439
|
+
const completedSteps = session.stepOffset + stepNumber;
|
|
4378
4440
|
const priorStep = stepNumber >= 1 ? steps[stepNumber - 1] : void 0;
|
|
4379
4441
|
const hasSafeBoundary = (priorStep?.content?.length ?? 0) > 0;
|
|
4442
|
+
for (const part of terminalToolPartsFromStep(priorStep?.content ?? [])) {
|
|
4443
|
+
session.terminalToolParts.set(part.toolCallId, part);
|
|
4444
|
+
}
|
|
4380
4445
|
const canFire = enableSteer && hasSafeBoundary;
|
|
4381
4446
|
const steerConfigs = canFire ? this.#remindersFor("steer") : [];
|
|
4382
4447
|
const outcomes = toolOutcomesFromStep(steps.at(-1)?.content ?? []);
|
|
@@ -4435,18 +4500,24 @@ var ContextEngine = class _ContextEngine {
|
|
|
4435
4500
|
"createPrepareStep: expected an assistant message at chain head."
|
|
4436
4501
|
);
|
|
4437
4502
|
}
|
|
4438
|
-
const currentSegmentId =
|
|
4503
|
+
const currentSegmentId = head.id;
|
|
4439
4504
|
const currentSegment = await this.#store.getMessage(currentSegmentId);
|
|
4440
4505
|
if (!currentSegment || currentSegment.name !== "assistant") {
|
|
4441
4506
|
throw new Error(
|
|
4442
4507
|
"createPrepareStep: expected the open assistant segment to be persisted."
|
|
4443
4508
|
);
|
|
4444
4509
|
}
|
|
4445
|
-
|
|
4510
|
+
requireUIMessage(
|
|
4446
4511
|
currentSegment.data,
|
|
4447
4512
|
`Stored assistant message "${currentSegment.id}"`
|
|
4448
4513
|
);
|
|
4449
4514
|
const nextSegmentId = generateId5();
|
|
4515
|
+
if (session.segments.length === 0) {
|
|
4516
|
+
session.segments.push({
|
|
4517
|
+
id: currentSegmentId,
|
|
4518
|
+
startStep: 0
|
|
4519
|
+
});
|
|
4520
|
+
}
|
|
4450
4521
|
for (const input of inputs) this.set(user(input));
|
|
4451
4522
|
this.set(
|
|
4452
4523
|
assistant({
|
|
@@ -4456,8 +4527,11 @@ var ContextEngine = class _ContextEngine {
|
|
|
4456
4527
|
})
|
|
4457
4528
|
);
|
|
4458
4529
|
await this.save({ branch: false });
|
|
4459
|
-
session.
|
|
4460
|
-
|
|
4530
|
+
session.segments.push({
|
|
4531
|
+
id: nextSegmentId,
|
|
4532
|
+
startStep: completedSteps
|
|
4533
|
+
});
|
|
4534
|
+
session.terminalToolParts.clear();
|
|
4461
4535
|
return {
|
|
4462
4536
|
messages: [...messages, ...inputModel]
|
|
4463
4537
|
};
|
|
@@ -4482,14 +4556,81 @@ var ContextEngine = class _ContextEngine {
|
|
|
4482
4556
|
);
|
|
4483
4557
|
}
|
|
4484
4558
|
const session = this.#currentReminderSession;
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4559
|
+
let id = head.id;
|
|
4560
|
+
let parts = message2.parts;
|
|
4561
|
+
if (session) {
|
|
4562
|
+
if (session.initialStepStarts === null) {
|
|
4563
|
+
const initialId = session.segments[0]?.id ?? head.id;
|
|
4564
|
+
const initial = await this.#store.getMessage(initialId);
|
|
4565
|
+
if (!initial || initial.name !== "assistant") {
|
|
4566
|
+
throw new Error(
|
|
4567
|
+
`writeAssistantSegment: initial segment "${initialId}" was not found`
|
|
4568
|
+
);
|
|
4569
|
+
}
|
|
4570
|
+
session.initialStepStarts = requireUIMessage(
|
|
4571
|
+
initial.data,
|
|
4572
|
+
`Stored assistant message "${initial.id}"`
|
|
4573
|
+
).parts.filter((part) => part.type === "step-start").length;
|
|
4574
|
+
}
|
|
4575
|
+
const streamStepStarts = message2.parts.flatMap(
|
|
4576
|
+
(part, index) => part.type === "step-start" ? [index] : []
|
|
4577
|
+
);
|
|
4578
|
+
const completedSteps = streamStepStarts.length - session.initialStepStarts;
|
|
4579
|
+
if (completedSteps < 0) {
|
|
4580
|
+
throw new Error(
|
|
4581
|
+
"writeAssistantSegment: response lost an existing step boundary"
|
|
4582
|
+
);
|
|
4583
|
+
}
|
|
4584
|
+
const segmentIndex = session.segments.findLastIndex(
|
|
4585
|
+
(candidate) => candidate.startStep < completedSteps
|
|
4586
|
+
);
|
|
4587
|
+
if (segmentIndex >= 0) {
|
|
4588
|
+
const segment = session.segments[segmentIndex];
|
|
4589
|
+
id = segment.id;
|
|
4590
|
+
if (segmentIndex > 0) {
|
|
4591
|
+
const start = streamStepStarts[session.initialStepStarts + segment.startStep];
|
|
4592
|
+
if (start === void 0) {
|
|
4593
|
+
throw new Error(
|
|
4594
|
+
`writeAssistantSegment: response is missing step ${segment.startStep + 1}`
|
|
4595
|
+
);
|
|
4596
|
+
}
|
|
4597
|
+
parts = message2.parts.slice(start);
|
|
4598
|
+
}
|
|
4599
|
+
} else {
|
|
4600
|
+
const lastSegment = session.segments.at(-1);
|
|
4601
|
+
if (lastSegment) {
|
|
4602
|
+
id = lastSegment.id;
|
|
4603
|
+
parts = [];
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
}
|
|
4607
|
+
const fragment2 = assistant({
|
|
4608
|
+
...message2,
|
|
4609
|
+
id,
|
|
4610
|
+
parts
|
|
4611
|
+
});
|
|
4612
|
+
if (!session) {
|
|
4613
|
+
this.set(fragment2);
|
|
4614
|
+
await this.save({ branch: false });
|
|
4615
|
+
return;
|
|
4616
|
+
}
|
|
4617
|
+
const stored = await this.#store.getMessage(id);
|
|
4618
|
+
if (!stored) {
|
|
4619
|
+
throw new Error(
|
|
4620
|
+
`writeAssistantSegment: reserved segment "${id}" was not found`
|
|
4621
|
+
);
|
|
4622
|
+
}
|
|
4623
|
+
if (!fragment2.codec) {
|
|
4624
|
+
throw new Error("writeAssistantSegment: assistant codec is missing");
|
|
4625
|
+
}
|
|
4626
|
+
await this.#store.addMessages([
|
|
4627
|
+
{
|
|
4628
|
+
...stored,
|
|
4629
|
+
name: fragment2.name,
|
|
4630
|
+
type: fragment2.type,
|
|
4631
|
+
data: fragment2.codec.encode()
|
|
4632
|
+
}
|
|
4633
|
+
]);
|
|
4493
4634
|
}
|
|
4494
4635
|
#remindersFor(target) {
|
|
4495
4636
|
return this.#fragments.filter(isConditionalReminder).map((fragment2) => fragment2.metadata.reminder).filter((config) => config.target === target);
|
|
@@ -4590,8 +4731,16 @@ var ContextEngine = class _ContextEngine {
|
|
|
4590
4731
|
"steer reminders require a user message earlier in the turn"
|
|
4591
4732
|
);
|
|
4592
4733
|
}
|
|
4734
|
+
const lastAssistantMessage = chain.lastAssistantMessage;
|
|
4735
|
+
if (!lastAssistantMessage) {
|
|
4736
|
+
throw new Error("steer reminders require a completed assistant step");
|
|
4737
|
+
}
|
|
4593
4738
|
return {
|
|
4594
4739
|
...this.#buildWhenCtx(chain, currentMessage),
|
|
4740
|
+
lastAssistantMessage: mergeTerminalToolParts(
|
|
4741
|
+
lastAssistantMessage,
|
|
4742
|
+
session.terminalToolParts
|
|
4743
|
+
),
|
|
4595
4744
|
sandbox,
|
|
4596
4745
|
firedOnceIds: /* @__PURE__ */ new Set([...chain.firedOnceIds, ...session.firedOnceIds])
|
|
4597
4746
|
};
|
|
@@ -6557,7 +6706,7 @@ function startKernelProcess(os, command, options) {
|
|
|
6557
6706
|
const stderr = new PassThrough();
|
|
6558
6707
|
const onStdout = (chunk) => stdout.write(chunk);
|
|
6559
6708
|
const onStderr = (chunk) => stderr.write(chunk);
|
|
6560
|
-
const { pid } = os.spawn("
|
|
6709
|
+
const { pid } = os.spawn("bash", ["-lc", command], {
|
|
6561
6710
|
...options,
|
|
6562
6711
|
onStdout,
|
|
6563
6712
|
onStderr
|
|
@@ -6610,6 +6759,25 @@ async function createAgentOsSandbox(options = {}) {
|
|
|
6610
6759
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
6611
6760
|
throw new AgentOsCreationError(err.message, err);
|
|
6612
6761
|
}
|
|
6762
|
+
try {
|
|
6763
|
+
const probe = startKernelProcess(os, ":", {});
|
|
6764
|
+
const [, stderr, exitCode] = await Promise.all([
|
|
6765
|
+
readAll(probe.stdout),
|
|
6766
|
+
readAll(probe.stderr),
|
|
6767
|
+
probe.exit
|
|
6768
|
+
]);
|
|
6769
|
+
if (exitCode !== 0) {
|
|
6770
|
+
throw new Error(stderr.trim() || `exit code ${exitCode}`);
|
|
6771
|
+
}
|
|
6772
|
+
} catch (error) {
|
|
6773
|
+
await os.dispose().catch(() => {
|
|
6774
|
+
});
|
|
6775
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
6776
|
+
throw new AgentOsCreationError(
|
|
6777
|
+
`Bash is required to execute sandbox commands but could not be started: ${err.message}`,
|
|
6778
|
+
err
|
|
6779
|
+
);
|
|
6780
|
+
}
|
|
6613
6781
|
const sandbox = {
|
|
6614
6782
|
async executeCommand(command, { signal } = {}) {
|
|
6615
6783
|
if (signal?.aborted) {
|
|
@@ -7143,6 +7311,7 @@ var ContainerSandboxStrategy = class {
|
|
|
7143
7311
|
await this.engine.ensureWorkdir(this.context.containerId, this.workdir);
|
|
7144
7312
|
await this.configure();
|
|
7145
7313
|
}
|
|
7314
|
+
await this.assertBashAvailable();
|
|
7146
7315
|
} catch (error) {
|
|
7147
7316
|
if (acquired && !acquired.attached) {
|
|
7148
7317
|
await this.stopContainer(acquired.containerId);
|
|
@@ -7441,6 +7610,15 @@ var ContainerSandboxStrategy = class {
|
|
|
7441
7610
|
};
|
|
7442
7611
|
}
|
|
7443
7612
|
}
|
|
7613
|
+
async assertBashAvailable() {
|
|
7614
|
+
const result = await this.exec(":");
|
|
7615
|
+
if (result.exitCode === 0) return;
|
|
7616
|
+
const detail = result.stderr.trim() || result.stdout.trim();
|
|
7617
|
+
throw this.engine.errors.generic(
|
|
7618
|
+
`Bash is required to execute sandbox commands but could not be started${detail ? `: ${detail}` : "."}`,
|
|
7619
|
+
this.context.containerId
|
|
7620
|
+
);
|
|
7621
|
+
}
|
|
7444
7622
|
spawnProcess(command, options) {
|
|
7445
7623
|
const child = childSpawn(
|
|
7446
7624
|
this.engine.cli,
|
|
@@ -7632,7 +7810,7 @@ var appleEngine = {
|
|
|
7632
7810
|
flags.push("--env", `${key}=${value}`);
|
|
7633
7811
|
}
|
|
7634
7812
|
}
|
|
7635
|
-
return ["exec", ...flags, containerId, "
|
|
7813
|
+
return ["exec", ...flags, containerId, "bash", "-lc", command];
|
|
7636
7814
|
},
|
|
7637
7815
|
inspectArgs(containerId) {
|
|
7638
7816
|
return ["inspect", containerId];
|
|
@@ -7661,9 +7839,15 @@ var appleEngine = {
|
|
|
7661
7839
|
return /already exists/i.test(message2);
|
|
7662
7840
|
},
|
|
7663
7841
|
async ensureWorkdir(containerId, workdir) {
|
|
7664
|
-
await spawn3(CLI, [
|
|
7842
|
+
await spawn3(CLI, [
|
|
7843
|
+
"exec",
|
|
7844
|
+
containerId,
|
|
7845
|
+
"bash",
|
|
7846
|
+
"-lc",
|
|
7847
|
+
`mkdir -p ${shellQuote(workdir)}`
|
|
7848
|
+
]);
|
|
7665
7849
|
},
|
|
7666
|
-
defaultImage: "docker.io/library/
|
|
7850
|
+
defaultImage: "docker.io/library/bash:5.3-alpine3.24",
|
|
7667
7851
|
createInstallerContext: createAppleInstallerContext,
|
|
7668
7852
|
async imageExists(tag) {
|
|
7669
7853
|
try {
|
|
@@ -8313,6 +8497,7 @@ async function createDaytonaSandbox(client, options = {}) {
|
|
|
8313
8497
|
} catch (error) {
|
|
8314
8498
|
throw normalizeDaytonaError(error, sdk);
|
|
8315
8499
|
}
|
|
8500
|
+
await assertDaytonaBash(sandbox, options.commandTimeout);
|
|
8316
8501
|
const backend = createDaytonaSandboxMethods({
|
|
8317
8502
|
sandbox,
|
|
8318
8503
|
commandTimeout: options.commandTimeout
|
|
@@ -8328,6 +8513,24 @@ async function createDaytonaSandbox(client, options = {}) {
|
|
|
8328
8513
|
}
|
|
8329
8514
|
return backend;
|
|
8330
8515
|
}
|
|
8516
|
+
async function assertDaytonaBash(sandbox, commandTimeout) {
|
|
8517
|
+
try {
|
|
8518
|
+
const result = await sandbox.process.executeCommand(
|
|
8519
|
+
"bash -lc ':'",
|
|
8520
|
+
void 0,
|
|
8521
|
+
void 0,
|
|
8522
|
+
commandTimeout
|
|
8523
|
+
);
|
|
8524
|
+
if (result.exitCode === void 0 || result.exitCode === 0) return;
|
|
8525
|
+
throw new Error(result.result || `exit code ${result.exitCode}`);
|
|
8526
|
+
} catch (error) {
|
|
8527
|
+
const err = toError(error);
|
|
8528
|
+
throw new DaytonaCreationError(
|
|
8529
|
+
`Bash is required to execute sandbox commands but could not be started: ${err.message}`,
|
|
8530
|
+
err
|
|
8531
|
+
);
|
|
8532
|
+
}
|
|
8533
|
+
}
|
|
8331
8534
|
var UNRECOVERABLE_SANDBOX_STATES = /* @__PURE__ */ new Set([
|
|
8332
8535
|
"error",
|
|
8333
8536
|
"build_failed",
|
|
@@ -8464,7 +8667,7 @@ function createDaytonaSandboxMethods(args) {
|
|
|
8464
8667
|
return abortedCommandResult();
|
|
8465
8668
|
}
|
|
8466
8669
|
const response = await sandbox.process.executeCommand(
|
|
8467
|
-
command
|
|
8670
|
+
`bash -lc ${shellQuote(command)}`,
|
|
8468
8671
|
void 0,
|
|
8469
8672
|
void 0,
|
|
8470
8673
|
commandTimeout
|
|
@@ -8706,13 +8909,13 @@ function buildSessionCommand(command, options) {
|
|
|
8706
8909
|
const env = options.env ?? {};
|
|
8707
8910
|
const entries = Object.entries(env);
|
|
8708
8911
|
if (entries.length === 0) {
|
|
8709
|
-
return `
|
|
8912
|
+
return `bash -lc ${shellQuote(`${cwdPrefix}${command}`)}`;
|
|
8710
8913
|
}
|
|
8711
8914
|
for (const [key] of entries) {
|
|
8712
8915
|
validateEnvKey(key);
|
|
8713
8916
|
}
|
|
8714
8917
|
const exports = entries.map(([key, value]) => `export ${key}=${shellQuote(value)}`).join("; ");
|
|
8715
|
-
return `
|
|
8918
|
+
return `bash -lc ${shellQuote(`${exports}; ${cwdPrefix}${command}`)}`;
|
|
8716
8919
|
}
|
|
8717
8920
|
function validateEnvKey(key) {
|
|
8718
8921
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
@@ -8952,7 +9155,7 @@ var dockerEngine = {
|
|
|
8952
9155
|
flags.push("-e", `${key}=${value}`);
|
|
8953
9156
|
}
|
|
8954
9157
|
}
|
|
8955
|
-
return ["exec", ...flags, containerId, "
|
|
9158
|
+
return ["exec", ...flags, containerId, "bash", "-lc", command];
|
|
8956
9159
|
},
|
|
8957
9160
|
inspectArgs(containerId) {
|
|
8958
9161
|
return [
|
|
@@ -8995,7 +9198,7 @@ var dockerEngine = {
|
|
|
8995
9198
|
},
|
|
8996
9199
|
async ensureWorkdir() {
|
|
8997
9200
|
},
|
|
8998
|
-
defaultImage: "
|
|
9201
|
+
defaultImage: "bash:5.3-alpine3.24",
|
|
8999
9202
|
createInstallerContext,
|
|
9000
9203
|
async imageExists(tag) {
|
|
9001
9204
|
try {
|
|
@@ -9105,8 +9308,8 @@ var ComposeStrategy = class extends ContainerSandboxStrategy {
|
|
|
9105
9308
|
"exec",
|
|
9106
9309
|
"-T",
|
|
9107
9310
|
this.service,
|
|
9108
|
-
"
|
|
9109
|
-
"-
|
|
9311
|
+
"bash",
|
|
9312
|
+
"-lc",
|
|
9110
9313
|
command
|
|
9111
9314
|
],
|
|
9112
9315
|
{ signal: options?.signal }
|
|
@@ -9132,8 +9335,8 @@ var ComposeStrategy = class extends ContainerSandboxStrategy {
|
|
|
9132
9335
|
"-T",
|
|
9133
9336
|
...buildDockerExecFlags(options),
|
|
9134
9337
|
this.service,
|
|
9135
|
-
"
|
|
9136
|
-
"-
|
|
9338
|
+
"bash",
|
|
9339
|
+
"-lc",
|
|
9137
9340
|
command
|
|
9138
9341
|
]);
|
|
9139
9342
|
return toSandboxProcess(child, options?.signal);
|
|
@@ -9191,10 +9394,10 @@ import spawn6 from "nano-spawn";
|
|
|
9191
9394
|
import { posix as posix2 } from "node:path";
|
|
9192
9395
|
var STRACE_FLAGS = "-f -y -qq -e trace=%file,write,pwrite64,writev";
|
|
9193
9396
|
function buildStraceCommand(command, traceFile, traceDir) {
|
|
9194
|
-
return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} --
|
|
9397
|
+
return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} -- bash -lc ${shellQuote(command)}`;
|
|
9195
9398
|
}
|
|
9196
9399
|
function buildTracedCommand(command, traceFile, traceDir, sentinel) {
|
|
9197
|
-
return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} --
|
|
9400
|
+
return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} -- bash -lc ${shellQuote(command)}; __dat_rc=$?; printf '\\n%s\\n' ${shellQuote(sentinel)}; base64 ${shellQuote(traceFile)} 2>/dev/null; rm -f ${shellQuote(traceFile)} 2>/dev/null; exit $__dat_rc`;
|
|
9198
9401
|
}
|
|
9199
9402
|
function splitTracedOutput(stdout, sentinel) {
|
|
9200
9403
|
const marker = `
|
|
@@ -9817,7 +10020,7 @@ function formatVersion(version) {
|
|
|
9817
10020
|
// packages/context/src/lib/sandbox/microsandbox-sandbox.ts
|
|
9818
10021
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
9819
10022
|
var MICROSANDBOX_DEFAULT_DESTINATION = "/workspace";
|
|
9820
|
-
var MICROSANDBOX_DEFAULT_IMAGE = "
|
|
10023
|
+
var MICROSANDBOX_DEFAULT_IMAGE = "bash:5.3-alpine3.24";
|
|
9821
10024
|
var MICROSANDBOX_MAX_NAME_BYTES = 128;
|
|
9822
10025
|
var COMMAND_TIMEOUT_EXIT_CODE = 124;
|
|
9823
10026
|
var MicrosandboxSandboxError = class extends Error {
|
|
@@ -9857,8 +10060,17 @@ async function createMicrosandboxSandbox(options = {}) {
|
|
|
9857
10060
|
let vm;
|
|
9858
10061
|
try {
|
|
9859
10062
|
vm = await acquireSandbox(sdk, { ...options, name, ephemeral, workdir });
|
|
10063
|
+
} catch (error) {
|
|
10064
|
+
throw normalizeMicrosandboxError(error, sdk);
|
|
10065
|
+
}
|
|
10066
|
+
try {
|
|
9860
10067
|
await vm.fs().mkdir(workdir);
|
|
10068
|
+
await assertMicrosandboxBash(vm);
|
|
9861
10069
|
} catch (error) {
|
|
10070
|
+
await vm.stop().catch(() => {
|
|
10071
|
+
});
|
|
10072
|
+
if (ephemeral) await sdk.Sandbox.remove(name).catch(() => {
|
|
10073
|
+
});
|
|
9862
10074
|
throw normalizeMicrosandboxError(error, sdk);
|
|
9863
10075
|
}
|
|
9864
10076
|
const backend = createMicrosandboxMethods({
|
|
@@ -9932,10 +10144,24 @@ function buildSandbox(sdk, options) {
|
|
|
9932
10144
|
if (options.memory !== void 0) builder = builder.memory(options.memory);
|
|
9933
10145
|
if (options.env) builder = builder.envs(options.env);
|
|
9934
10146
|
if (options.configure) builder = options.configure(builder);
|
|
9935
|
-
return builder.create();
|
|
10147
|
+
return builder.shell("bash").create();
|
|
10148
|
+
}
|
|
10149
|
+
async function assertMicrosandboxBash(vm) {
|
|
10150
|
+
try {
|
|
10151
|
+
const result = await vm.exec("bash", ["-lc", ":"]);
|
|
10152
|
+
if (result.code === 0) return;
|
|
10153
|
+
throw new Error(result.stderr() || `exit code ${result.code}`);
|
|
10154
|
+
} catch (error) {
|
|
10155
|
+
const err = toError2(error);
|
|
10156
|
+
throw new MicrosandboxCreationError(
|
|
10157
|
+
`Bash is required to execute sandbox commands but could not be started: ${err.message}`,
|
|
10158
|
+
err
|
|
10159
|
+
);
|
|
10160
|
+
}
|
|
9936
10161
|
}
|
|
9937
10162
|
function normalizeMicrosandboxError(error, sdk) {
|
|
9938
10163
|
const err = toError2(error);
|
|
10164
|
+
if (err instanceof MicrosandboxSandboxError) return err;
|
|
9939
10165
|
if (err instanceof sdk.LibkrunfwNotFoundError) {
|
|
9940
10166
|
return new MicrosandboxNotAvailableError(err);
|
|
9941
10167
|
}
|
|
@@ -10050,7 +10276,7 @@ async function pumpExecStream(args) {
|
|
|
10050
10276
|
}
|
|
10051
10277
|
signal?.addEventListener("abort", abort, { once: true });
|
|
10052
10278
|
try {
|
|
10053
|
-
handle = await vm.execStreamWith("
|
|
10279
|
+
handle = await vm.execStreamWith("bash", (builder) => {
|
|
10054
10280
|
builder.args(["-lc", command]).stdinNull();
|
|
10055
10281
|
if (options.cwd) builder.cwd(options.cwd);
|
|
10056
10282
|
if (options.env) builder.envs(options.env);
|