@deepagents/context 2.1.0 → 2.3.0

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.
Files changed (42) hide show
  1. package/README.md +18 -14
  2. package/dist/browser.js +37 -2
  3. package/dist/browser.js.map +3 -3
  4. package/dist/index.js +845 -112
  5. package/dist/index.js.map +4 -4
  6. package/dist/lib/guardrail.d.ts +2 -6
  7. package/dist/lib/guardrail.d.ts.map +1 -1
  8. package/dist/lib/sandbox/abort.d.ts.map +1 -1
  9. package/dist/lib/sandbox/agent-os-sandbox.d.ts +5 -1
  10. package/dist/lib/sandbox/agent-os-sandbox.d.ts.map +1 -1
  11. package/dist/lib/sandbox/daytona-sandbox.d.ts +63 -0
  12. package/dist/lib/sandbox/daytona-sandbox.d.ts.map +1 -0
  13. package/dist/lib/sandbox/docker-sandbox-errors.d.ts +9 -4
  14. package/dist/lib/sandbox/docker-sandbox-errors.d.ts.map +1 -1
  15. package/dist/lib/sandbox/docker-sandbox.d.ts +24 -1
  16. package/dist/lib/sandbox/docker-sandbox.d.ts.map +1 -1
  17. package/dist/lib/sandbox/file-events.d.ts +10 -1
  18. package/dist/lib/sandbox/file-events.d.ts.map +1 -1
  19. package/dist/lib/sandbox/index.d.ts +1 -1
  20. package/dist/lib/sandbox/index.d.ts.map +1 -1
  21. package/dist/lib/sandbox/installers/bin.d.ts +40 -0
  22. package/dist/lib/sandbox/installers/bin.d.ts.map +1 -0
  23. package/dist/lib/sandbox/installers/index.d.ts +1 -0
  24. package/dist/lib/sandbox/installers/index.d.ts.map +1 -1
  25. package/dist/lib/save/save-pipeline.d.ts.map +1 -1
  26. package/dist/lib/skills/fragments.d.ts +2 -2
  27. package/dist/lib/store/sqlite.store.d.ts +1 -0
  28. package/dist/lib/store/sqlite.store.d.ts.map +1 -1
  29. package/dist/lib/store/store.d.ts +8 -0
  30. package/dist/lib/store/store.d.ts.map +1 -1
  31. package/dist/lib/stream/postgres.stream-store.d.ts.map +1 -1
  32. package/dist/lib/stream/sqlite.stream-store.d.ts.map +1 -1
  33. package/dist/lib/stream/stream-manager.d.ts +1 -1
  34. package/dist/lib/stream/stream-manager.d.ts.map +1 -1
  35. package/dist/lib/stream/stream-store.d.ts +8 -1
  36. package/dist/lib/stream/stream-store.d.ts.map +1 -1
  37. package/dist/lib/stream/types.d.ts +7 -0
  38. package/dist/lib/stream/types.d.ts.map +1 -0
  39. package/dist/lib/stream-buffer.d.ts.map +1 -1
  40. package/package.json +7 -3
  41. package/dist/lib/sandbox/container-tool.d.ts +0 -190
  42. package/dist/lib/sandbox/container-tool.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -2623,6 +2623,8 @@ var SavePipeline = class {
2623
2623
  async persist() {
2624
2624
  let parentId = this.#engine.getActiveBranch().headMessageId;
2625
2625
  const now = Date.now();
2626
+ const messages = [];
2627
+ const pendingMessagesById = /* @__PURE__ */ new Map();
2626
2628
  for (const fragment2 of this.#pending) {
2627
2629
  if (!fragment2.codec) {
2628
2630
  throw new Error(`Fragment "${fragment2.name}" is missing codec.`);
@@ -2630,7 +2632,7 @@ var SavePipeline = class {
2630
2632
  const msgId = fragment2.id ?? crypto.randomUUID();
2631
2633
  let msgParentId = parentId;
2632
2634
  if (!this.#shouldBranch && msgId === parentId) {
2633
- const existing = await this.#engine.store.getMessage(msgId);
2635
+ const existing = pendingMessagesById.get(msgId) ?? await this.#engine.store.getMessage(msgId);
2634
2636
  if (existing) msgParentId = existing.parentId;
2635
2637
  }
2636
2638
  const messageData = {
@@ -2642,7 +2644,8 @@ var SavePipeline = class {
2642
2644
  data: fragment2.codec.encode(),
2643
2645
  createdAt: now
2644
2646
  };
2645
- await this.#engine.store.addMessage(messageData);
2647
+ messages.push(messageData);
2648
+ pendingMessagesById.set(messageData.id, messageData);
2646
2649
  parentId = messageData.id;
2647
2650
  }
2648
2651
  if (parentId === null) {
@@ -2650,6 +2653,7 @@ var SavePipeline = class {
2650
2653
  "Pipeline persisted no messages but pending was not empty"
2651
2654
  );
2652
2655
  }
2656
+ await this.#engine.store.addMessages(messages);
2653
2657
  await this.#engine.commitHead(parentId);
2654
2658
  return { headMessageId: parentId };
2655
2659
  }
@@ -2765,6 +2769,18 @@ var ddl_sqlite_default = "-- Context Store DDL for SQLite\n-- This schema implem
2765
2769
 
2766
2770
  // packages/context/src/lib/store/store.ts
2767
2771
  var ContextStore = class {
2772
+ /**
2773
+ * Add multiple messages to the graph.
2774
+ *
2775
+ * Stores can override this for atomic/batched persistence. The default keeps
2776
+ * the single-message contract for implementations that do not need a custom
2777
+ * batch path.
2778
+ */
2779
+ async addMessages(messages) {
2780
+ for (const message2 of messages) {
2781
+ await this.addMessage(message2);
2782
+ }
2783
+ }
2768
2784
  };
2769
2785
 
2770
2786
  // packages/context/src/lib/store/sqlite.store.ts
@@ -2972,7 +2988,7 @@ var SqliteContextStore = class extends ContextStore {
2972
2988
  // ==========================================================================
2973
2989
  // Message Operations (Graph Nodes)
2974
2990
  // ==========================================================================
2975
- async addMessage(message2) {
2991
+ #insertMessage(message2) {
2976
2992
  if (message2.parentId === message2.id) {
2977
2993
  throw new Error(`Message ${message2.id} cannot be its own parent`);
2978
2994
  }
@@ -2999,6 +3015,17 @@ var SqliteContextStore = class extends ContextStore {
2999
3015
  VALUES (?, ?, ?, ?)`
3000
3016
  ).run(message2.id, message2.chatId, message2.name, content);
3001
3017
  }
3018
+ async addMessage(message2) {
3019
+ this.#insertMessage(message2);
3020
+ }
3021
+ async addMessages(messages) {
3022
+ if (messages.length === 0) return;
3023
+ this.#useTransaction(() => {
3024
+ for (const message2 of messages) {
3025
+ this.#insertMessage(message2);
3026
+ }
3027
+ });
3028
+ }
3002
3029
  async getMessage(messageId) {
3003
3030
  const row = this.#stmt("SELECT * FROM messages WHERE id = ?").get(
3004
3031
  messageId
@@ -5836,7 +5863,7 @@ function runWithAbortSignal(signal, fn) {
5836
5863
  return ambientAbortSignal.run(signal, fn);
5837
5864
  }
5838
5865
  function withAbortSignal(sandbox) {
5839
- return {
5866
+ const decorated = {
5840
5867
  ...sandbox,
5841
5868
  async executeCommand(command, options) {
5842
5869
  const signal = options?.signal ?? ambientAbortSignal.getStore();
@@ -5846,11 +5873,20 @@ function withAbortSignal(sandbox) {
5846
5873
  );
5847
5874
  }
5848
5875
  };
5876
+ if (sandbox.spawn) {
5877
+ const innerSpawn = sandbox.spawn.bind(sandbox);
5878
+ decorated.spawn = (command, options) => {
5879
+ const signal = options?.signal ?? ambientAbortSignal.getStore();
5880
+ return innerSpawn(command, signal ? { ...options, signal } : options);
5881
+ };
5882
+ }
5883
+ return decorated;
5849
5884
  }
5850
5885
 
5851
5886
  // packages/context/src/lib/sandbox/agent-os-sandbox.ts
5852
5887
  import "bash-tool";
5853
- var textDecoder = new TextDecoder();
5888
+ import { PassThrough, Readable } from "node:stream";
5889
+ var decoder = new TextDecoder();
5854
5890
  var AgentOsSandboxError = class extends Error {
5855
5891
  constructor(message2) {
5856
5892
  super(message2);
@@ -5882,6 +5918,49 @@ async function importAgentOs() {
5882
5918
  );
5883
5919
  }
5884
5920
  }
5921
+ var SIGKILL_EXIT_CODE = 9;
5922
+ function startKernelProcess(os, command, options) {
5923
+ const { pid } = os.spawn("sh", ["-c", command], options);
5924
+ const stdout = new PassThrough();
5925
+ const stderr = new PassThrough();
5926
+ const unsubOut = os.onProcessStdout(pid, (chunk) => stdout.write(chunk));
5927
+ const unsubErr = os.onProcessStderr(pid, (chunk) => stderr.write(chunk));
5928
+ let killSignalled = false;
5929
+ const exit = os.waitProcess(pid).finally(() => {
5930
+ unsubOut();
5931
+ unsubErr();
5932
+ stdout.end();
5933
+ stderr.end();
5934
+ });
5935
+ return {
5936
+ pid,
5937
+ stdout,
5938
+ stderr,
5939
+ exit,
5940
+ kill: () => {
5941
+ if (killSignalled) return;
5942
+ killSignalled = true;
5943
+ os.killProcess(pid);
5944
+ },
5945
+ wasKilled: (exitCode) => killSignalled && exitCode === SIGKILL_EXIT_CODE
5946
+ };
5947
+ }
5948
+ async function readAll(stream) {
5949
+ const chunks = [];
5950
+ for await (const chunk of stream) chunks.push(chunk);
5951
+ return Buffer.concat(chunks).toString("utf8");
5952
+ }
5953
+ function bindAbort(signal, onAbort) {
5954
+ if (!signal) return () => {
5955
+ };
5956
+ if (signal.aborted) {
5957
+ onAbort();
5958
+ return () => {
5959
+ };
5960
+ }
5961
+ signal.addEventListener("abort", onAbort, { once: true });
5962
+ return () => signal.removeEventListener("abort", onAbort);
5963
+ }
5885
5964
  async function createAgentOsSandbox(options = {}) {
5886
5965
  const { AgentOs } = await importAgentOs();
5887
5966
  let os;
@@ -5892,27 +5971,56 @@ async function createAgentOsSandbox(options = {}) {
5892
5971
  throw new AgentOsCreationError(err.message, err);
5893
5972
  }
5894
5973
  return {
5895
- async executeCommand(command) {
5974
+ async executeCommand(command, { signal } = {}) {
5975
+ if (signal?.aborted) {
5976
+ return { stdout: "", stderr: "", exitCode: SIGKILL_EXIT_CODE };
5977
+ }
5978
+ const proc = startKernelProcess(os, command, {});
5979
+ const unbind = bindAbort(signal, proc.kill);
5896
5980
  try {
5897
- const result = await os.exec(command);
5981
+ const [stdout, stderr, exitCode] = await Promise.all([
5982
+ readAll(proc.stdout),
5983
+ readAll(proc.stderr),
5984
+ proc.exit
5985
+ ]);
5986
+ return { stdout, stderr, exitCode };
5987
+ } finally {
5988
+ unbind();
5989
+ }
5990
+ },
5991
+ spawn(command, { signal, env, cwd } = {}) {
5992
+ if (signal?.aborted) {
5993
+ const empty = () => new ReadableStream({ start: (c) => c.close() });
5898
5994
  return {
5899
- stdout: result.stdout,
5900
- stderr: result.stderr,
5901
- exitCode: result.exitCode
5995
+ stdout: empty(),
5996
+ stderr: empty(),
5997
+ exit: Promise.resolve({
5998
+ code: null,
5999
+ signal: "SIGKILL",
6000
+ success: false
6001
+ })
5902
6002
  };
5903
- } catch (error) {
5904
- const err = error;
6003
+ }
6004
+ const proc = startKernelProcess(os, command, { env, cwd });
6005
+ const unbind = bindAbort(signal, proc.kill);
6006
+ const exit = proc.exit.then((code) => {
6007
+ const killed = proc.wasKilled(code);
5905
6008
  return {
5906
- stdout: err.stdout || "",
5907
- stderr: err.stderr || err.message || "",
5908
- exitCode: err.exitCode ?? 1
6009
+ code: killed ? null : code,
6010
+ signal: killed ? "SIGKILL" : null,
6011
+ success: !killed && code === 0
5909
6012
  };
5910
- }
6013
+ }).finally(unbind);
6014
+ return {
6015
+ stdout: Readable.toWeb(proc.stdout),
6016
+ stderr: Readable.toWeb(proc.stderr),
6017
+ exit
6018
+ };
5911
6019
  },
5912
6020
  async readFile(path5) {
5913
6021
  try {
5914
6022
  const bytes = await os.readFile(path5);
5915
- return textDecoder.decode(bytes);
6023
+ return decoder.decode(bytes);
5916
6024
  } catch (error) {
5917
6025
  throw new Error(
5918
6026
  `Failed to read file "${path5}": ${error instanceof Error ? error.message : String(error)}`
@@ -6017,6 +6125,28 @@ async function snapshot(execute, destination) {
6017
6125
  }
6018
6126
  return snap;
6019
6127
  }
6128
+ function lazyReadable(innerPromise) {
6129
+ let reader = null;
6130
+ return new ReadableStream({
6131
+ async pull(controller) {
6132
+ if (!reader) {
6133
+ const inner = await innerPromise;
6134
+ reader = inner.getReader();
6135
+ }
6136
+ const { done, value } = await reader.read();
6137
+ if (done) controller.close();
6138
+ else controller.enqueue(value);
6139
+ },
6140
+ async cancel(reason) {
6141
+ if (reader) {
6142
+ await reader.cancel(reason);
6143
+ } else {
6144
+ const inner = await innerPromise;
6145
+ await inner.cancel(reason);
6146
+ }
6147
+ }
6148
+ });
6149
+ }
6020
6150
  function diff(before, after) {
6021
6151
  const events = [];
6022
6152
  const ts = Date.now();
@@ -6074,6 +6204,41 @@ function observeSandboxFileEvents(sandbox, options) {
6074
6204
  },
6075
6205
  dispose: sandbox.dispose.bind(sandbox)
6076
6206
  };
6207
+ if (sandbox.spawn) {
6208
+ const innerSpawn = sandbox.spawn.bind(sandbox);
6209
+ decorated.spawn = (command, options2) => {
6210
+ const started = (async () => {
6211
+ const before = await snapshot(innerExecute, destination).catch(
6212
+ () => /* @__PURE__ */ new Map()
6213
+ );
6214
+ const child = innerSpawn(command, options2);
6215
+ return { before, child };
6216
+ })();
6217
+ const exit = (async () => {
6218
+ const { before, child } = await started;
6219
+ try {
6220
+ return await child.exit;
6221
+ } finally {
6222
+ try {
6223
+ const after = await snapshot(innerExecute, destination);
6224
+ buffer.push(...diff(before, after));
6225
+ } catch {
6226
+ }
6227
+ }
6228
+ })();
6229
+ const stdoutPromise = started.then((s) => s.child.stdout);
6230
+ const stderrPromise = started.then((s) => s.child.stderr);
6231
+ stdoutPromise.catch(() => {
6232
+ });
6233
+ stderrPromise.catch(() => {
6234
+ });
6235
+ return {
6236
+ stdout: lazyReadable(stdoutPromise),
6237
+ stderr: lazyReadable(stderrPromise),
6238
+ exit
6239
+ };
6240
+ };
6241
+ }
6077
6242
  return {
6078
6243
  sandbox: decorated,
6079
6244
  drain() {
@@ -6406,13 +6571,513 @@ function resolveRealCwd(ctx) {
6406
6571
  return realCwd;
6407
6572
  }
6408
6573
 
6574
+ // packages/context/src/lib/sandbox/daytona-sandbox.ts
6575
+ import "bash-tool";
6576
+ import { randomUUID } from "node:crypto";
6577
+ import { createRequire } from "node:module";
6578
+ var DAYTONA_DEFAULT_DESTINATION = "/home/daytona";
6579
+ var DAYTONA_EXIT_POLL_INTERVAL_MS = 250;
6580
+ var DAYTONA_EXIT_POLL_TIMEOUT_MS = 3e4;
6581
+ var requireOptional = createRequire(import.meta.url);
6582
+ var DaytonaSandboxError = class extends Error {
6583
+ constructor(message2, cause) {
6584
+ super(message2);
6585
+ this.name = "DaytonaSandboxError";
6586
+ this.cause = cause;
6587
+ }
6588
+ };
6589
+ var DaytonaNotAvailableError = class extends DaytonaSandboxError {
6590
+ constructor(cause) {
6591
+ super(
6592
+ "@daytona/sdk is not installed. Install it with: npm install @daytona/sdk",
6593
+ cause
6594
+ );
6595
+ this.name = "DaytonaNotAvailableError";
6596
+ }
6597
+ };
6598
+ var DaytonaCreationError = class extends DaytonaSandboxError {
6599
+ constructor(message2, cause) {
6600
+ super(`Failed to create Daytona sandbox: ${message2}`, cause);
6601
+ this.name = "DaytonaCreationError";
6602
+ }
6603
+ };
6604
+ var DaytonaCommandError = class extends DaytonaSandboxError {
6605
+ constructor(message2, cause) {
6606
+ super(message2, cause);
6607
+ this.name = "DaytonaCommandError";
6608
+ }
6609
+ };
6610
+ async function createDaytonaSandbox(options = {}) {
6611
+ validateDaytonaOptions(options);
6612
+ const { Daytona } = await importDaytonaSdk();
6613
+ let client;
6614
+ try {
6615
+ client = new Daytona(createDaytonaConfig(options));
6616
+ } catch (error) {
6617
+ const err = toError(error);
6618
+ throw new DaytonaCreationError(err.message, err);
6619
+ }
6620
+ const attached = options.sandboxId !== void 0;
6621
+ const deleteOnDispose = options.deleteOnDispose ?? !attached;
6622
+ let sandbox;
6623
+ try {
6624
+ sandbox = attached ? await client.get(options.sandboxId) : await client.create(createDaytonaParams(options), {
6625
+ timeout: options.createTimeout,
6626
+ onSnapshotCreateLogs: options.onSnapshotCreateLogs
6627
+ });
6628
+ if (attached && sandbox.state && sandbox.state !== "started") {
6629
+ await sandbox.start?.(options.startTimeout ?? options.createTimeout);
6630
+ }
6631
+ } catch (error) {
6632
+ const err = toError(error);
6633
+ throw new DaytonaCreationError(err.message, err);
6634
+ }
6635
+ return createDaytonaSandboxMethods({
6636
+ client,
6637
+ sandbox,
6638
+ commandTimeout: options.commandTimeout,
6639
+ deleteOnDispose,
6640
+ deleteTimeout: options.deleteTimeout
6641
+ });
6642
+ }
6643
+ async function importDaytonaSdk() {
6644
+ try {
6645
+ const mod = requireOptional("@daytona/sdk");
6646
+ if (typeof mod.Daytona !== "function") {
6647
+ throw new DaytonaSandboxError(
6648
+ "@daytona/sdk did not export a Daytona constructor"
6649
+ );
6650
+ }
6651
+ return { Daytona: mod.Daytona };
6652
+ } catch (error) {
6653
+ if (error instanceof DaytonaSandboxError) {
6654
+ throw error;
6655
+ }
6656
+ const err = toError(error);
6657
+ if (isMissingDaytonaSdk(err)) {
6658
+ throw new DaytonaNotAvailableError(err);
6659
+ }
6660
+ throw err;
6661
+ }
6662
+ }
6663
+ function createDaytonaConfig(options) {
6664
+ return compactObject({
6665
+ apiKey: options.apiKey,
6666
+ jwtToken: options.jwtToken,
6667
+ organizationId: options.organizationId,
6668
+ apiUrl: options.apiUrl,
6669
+ target: options.target,
6670
+ otelEnabled: options.otelEnabled,
6671
+ _experimental: options.experimental
6672
+ });
6673
+ }
6674
+ function createDaytonaParams(options) {
6675
+ const base = compactObject({
6676
+ name: options.name,
6677
+ user: options.user,
6678
+ language: options.language,
6679
+ envVars: options.envVars,
6680
+ labels: options.labels,
6681
+ public: options.public,
6682
+ autoStopInterval: options.autoStopInterval,
6683
+ autoArchiveInterval: options.autoArchiveInterval,
6684
+ autoDeleteInterval: options.autoDeleteInterval,
6685
+ volumes: options.volumes,
6686
+ networkBlockAll: options.networkBlockAll,
6687
+ networkAllowList: options.networkAllowList,
6688
+ ephemeral: options.ephemeral
6689
+ });
6690
+ if (options.image) {
6691
+ return compactObject({
6692
+ ...base,
6693
+ image: options.image,
6694
+ resources: options.resources
6695
+ });
6696
+ }
6697
+ const params = compactObject({
6698
+ ...base,
6699
+ snapshot: options.snapshot
6700
+ });
6701
+ return Object.keys(params).length > 0 ? params : void 0;
6702
+ }
6703
+ function validateDaytonaOptions(options) {
6704
+ if (options.image && options.snapshot) {
6705
+ throw new DaytonaSandboxError(
6706
+ 'Daytona sandbox options cannot include both "image" and "snapshot". Choose one environment source.'
6707
+ );
6708
+ }
6709
+ if (options.resources && !options.image) {
6710
+ throw new DaytonaSandboxError(
6711
+ 'Daytona sandbox options can only include "resources" when creating from "image". The Daytona SDK does not apply resources during default or snapshot creation.'
6712
+ );
6713
+ }
6714
+ if (!options.sandboxId) {
6715
+ return;
6716
+ }
6717
+ const creationOnlyFields = [
6718
+ "name",
6719
+ "user",
6720
+ "snapshot",
6721
+ "image",
6722
+ "language",
6723
+ "envVars",
6724
+ "labels",
6725
+ "public",
6726
+ "resources",
6727
+ "volumes",
6728
+ "networkAllowList",
6729
+ "networkBlockAll",
6730
+ "autoStopInterval",
6731
+ "autoArchiveInterval",
6732
+ "autoDeleteInterval",
6733
+ "ephemeral",
6734
+ "onSnapshotCreateLogs"
6735
+ ];
6736
+ const present = creationOnlyFields.filter((field) => {
6737
+ return options[field] !== void 0;
6738
+ });
6739
+ if (present.length > 0) {
6740
+ throw new DaytonaSandboxError(
6741
+ `Daytona sandbox options cannot combine "sandboxId" with creation options: ${present.join(", ")}`
6742
+ );
6743
+ }
6744
+ }
6745
+ function createDaytonaSandboxMethods(args) {
6746
+ const { client, sandbox, commandTimeout, deleteOnDispose, deleteTimeout } = args;
6747
+ let disposed = false;
6748
+ const executeCommand = async (command, options) => {
6749
+ if (options?.signal?.aborted) {
6750
+ return abortedCommandResult();
6751
+ }
6752
+ let aborted = false;
6753
+ const abort = () => {
6754
+ aborted = true;
6755
+ };
6756
+ options?.signal?.addEventListener("abort", abort, { once: true });
6757
+ try {
6758
+ if (aborted || options?.signal?.aborted) {
6759
+ return abortedCommandResult();
6760
+ }
6761
+ const response = await sandbox.process.executeCommand(
6762
+ command,
6763
+ void 0,
6764
+ void 0,
6765
+ commandTimeout
6766
+ );
6767
+ if (aborted) return abortedCommandResult();
6768
+ return {
6769
+ stdout: response.result ?? response.artifacts?.stdout ?? "",
6770
+ stderr: "",
6771
+ exitCode: response.exitCode ?? 0
6772
+ };
6773
+ } catch (error) {
6774
+ if (aborted) return abortedCommandResult();
6775
+ const err = error;
6776
+ return {
6777
+ stdout: err.stdout ?? "",
6778
+ stderr: err.stderr ?? err.message ?? String(error),
6779
+ exitCode: err.exitCode ?? 1
6780
+ };
6781
+ } finally {
6782
+ options?.signal?.removeEventListener("abort", abort);
6783
+ }
6784
+ };
6785
+ return {
6786
+ executeCommand,
6787
+ spawn(command, options) {
6788
+ return spawnDaytonaProcess(sandbox, command, {
6789
+ ...options,
6790
+ commandTimeout
6791
+ });
6792
+ },
6793
+ async readFile(path5) {
6794
+ try {
6795
+ const bytes = await sandbox.fs.downloadFile(path5);
6796
+ return Buffer.from(bytes).toString("utf-8");
6797
+ } catch (error) {
6798
+ throw new DaytonaCommandError(
6799
+ `Failed to read file "${path5}": ${toError(error).message}`,
6800
+ toError(error)
6801
+ );
6802
+ }
6803
+ },
6804
+ async writeFiles(files) {
6805
+ try {
6806
+ for (const dir of uniqueParentDirectories(files.map((f) => f.path))) {
6807
+ const result = await executeCommand(`mkdir -p ${shellQuote2(dir)}`);
6808
+ if (result.exitCode !== 0) {
6809
+ throw new DaytonaCommandError(
6810
+ `Failed to create directory "${dir}": ${result.stderr}`
6811
+ );
6812
+ }
6813
+ }
6814
+ await sandbox.fs.uploadFiles(
6815
+ files.map((file) => ({
6816
+ source: Buffer.from(file.content),
6817
+ destination: file.path
6818
+ }))
6819
+ );
6820
+ } catch (error) {
6821
+ if (error instanceof DaytonaSandboxError) throw error;
6822
+ const err = toError(error);
6823
+ throw new DaytonaCommandError(
6824
+ `Failed to write files: ${err.message}`,
6825
+ err
6826
+ );
6827
+ }
6828
+ },
6829
+ async dispose() {
6830
+ if (disposed) return;
6831
+ disposed = true;
6832
+ try {
6833
+ if (deleteOnDispose) {
6834
+ if (sandbox.delete) await sandbox.delete(deleteTimeout);
6835
+ else if (client.delete) await client.delete(sandbox, deleteTimeout);
6836
+ }
6837
+ } finally {
6838
+ await client[Symbol.asyncDispose]?.().catch(() => {
6839
+ });
6840
+ }
6841
+ }
6842
+ };
6843
+ }
6844
+ function spawnDaytonaProcess(sandbox, command, options = {}) {
6845
+ const sessionId = createSessionId("spawn");
6846
+ const stdout = createTextReadable();
6847
+ const stderr = createTextReadable();
6848
+ const exit = runSpawnedSession({
6849
+ sandbox,
6850
+ sessionId,
6851
+ command: buildSessionCommand(command, options),
6852
+ signal: options.signal,
6853
+ commandTimeout: options.commandTimeout,
6854
+ stdout,
6855
+ stderr
6856
+ });
6857
+ return {
6858
+ stdout: stdout.stream,
6859
+ stderr: stderr.stream,
6860
+ exit
6861
+ };
6862
+ }
6863
+ async function runSpawnedSession(args) {
6864
+ const {
6865
+ sandbox,
6866
+ sessionId,
6867
+ command,
6868
+ signal,
6869
+ commandTimeout,
6870
+ stdout,
6871
+ stderr
6872
+ } = args;
6873
+ let sessionCreated = false;
6874
+ let aborted = signal?.aborted ?? false;
6875
+ let resolveAbort;
6876
+ const abortPromise = new Promise((resolve4) => {
6877
+ resolveAbort = () => resolve4("aborted");
6878
+ });
6879
+ const abort = () => {
6880
+ aborted = true;
6881
+ resolveAbort?.();
6882
+ if (sessionCreated) {
6883
+ sandbox.process.deleteSession(sessionId).catch(() => {
6884
+ });
6885
+ }
6886
+ };
6887
+ if (signal) {
6888
+ if (signal.aborted) abort();
6889
+ else signal.addEventListener("abort", abort, { once: true });
6890
+ }
6891
+ try {
6892
+ await sandbox.process.createSession(sessionId);
6893
+ sessionCreated = true;
6894
+ if (aborted) return abortedExitInfo();
6895
+ const response = await sandbox.process.executeSessionCommand(
6896
+ sessionId,
6897
+ {
6898
+ command,
6899
+ runAsync: true,
6900
+ suppressInputEcho: true
6901
+ },
6902
+ commandTimeout
6903
+ );
6904
+ const commandId = response.cmdId;
6905
+ if (!commandId) {
6906
+ throw new DaytonaCommandError(
6907
+ "Daytona did not return a command id for the spawned session command."
6908
+ );
6909
+ }
6910
+ if (aborted) return abortedExitInfo();
6911
+ const logsTask = sandbox.process.getSessionCommandLogs(
6912
+ sessionId,
6913
+ commandId,
6914
+ (chunk) => stdout.enqueue(chunk),
6915
+ (chunk) => stderr.enqueue(chunk)
6916
+ );
6917
+ logsTask.catch(() => {
6918
+ });
6919
+ const winner = await Promise.race([
6920
+ logsTask.then(() => "logs"),
6921
+ abortPromise
6922
+ ]);
6923
+ if (winner === "aborted") {
6924
+ await sandbox.process.deleteSession(sessionId).catch(() => {
6925
+ });
6926
+ return abortedExitInfo();
6927
+ }
6928
+ await logsTask;
6929
+ const code = await waitForSessionCommandExitCode({
6930
+ sandbox,
6931
+ sessionId,
6932
+ commandId,
6933
+ timeoutMs: sessionExitPollTimeoutMs(commandTimeout),
6934
+ isAborted: () => aborted
6935
+ });
6936
+ return { code, signal: null, success: code === 0 };
6937
+ } catch (error) {
6938
+ if (aborted) return abortedExitInfo();
6939
+ const err = toError(error);
6940
+ stdout.error(err);
6941
+ stderr.error(err);
6942
+ throw err;
6943
+ } finally {
6944
+ if (signal) {
6945
+ signal.removeEventListener("abort", abort);
6946
+ }
6947
+ stdout.close();
6948
+ stderr.close();
6949
+ if (sessionCreated) {
6950
+ await sandbox.process.deleteSession(sessionId).catch(() => {
6951
+ });
6952
+ }
6953
+ }
6954
+ }
6955
+ async function waitForSessionCommandExitCode(args) {
6956
+ const { sandbox, sessionId, commandId, timeoutMs, isAborted } = args;
6957
+ const deadline = Date.now() + timeoutMs;
6958
+ while (true) {
6959
+ if (isAborted()) throw new DaytonaCommandError("Daytona command aborted.");
6960
+ const info = await sandbox.process.getSessionCommand(sessionId, commandId);
6961
+ if (typeof info.exitCode === "number") {
6962
+ return info.exitCode;
6963
+ }
6964
+ if (Date.now() >= deadline) {
6965
+ throw new DaytonaCommandError(
6966
+ `Daytona session command "${commandId}" logs closed before an exit code became available.`
6967
+ );
6968
+ }
6969
+ await delay(DAYTONA_EXIT_POLL_INTERVAL_MS);
6970
+ }
6971
+ }
6972
+ function sessionExitPollTimeoutMs(commandTimeout) {
6973
+ if (commandTimeout === void 0 || commandTimeout === 0) {
6974
+ return DAYTONA_EXIT_POLL_TIMEOUT_MS;
6975
+ }
6976
+ return Math.max(commandTimeout * 1e3, DAYTONA_EXIT_POLL_TIMEOUT_MS);
6977
+ }
6978
+ function delay(ms) {
6979
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
6980
+ }
6981
+ function createTextReadable() {
6982
+ const encoder = new TextEncoder();
6983
+ let controller;
6984
+ let closed = false;
6985
+ return {
6986
+ stream: new ReadableStream({
6987
+ start(streamController) {
6988
+ controller = streamController;
6989
+ }
6990
+ }),
6991
+ enqueue(chunk) {
6992
+ if (closed || !chunk) return;
6993
+ controller?.enqueue(encoder.encode(chunk));
6994
+ },
6995
+ close() {
6996
+ if (closed) return;
6997
+ closed = true;
6998
+ controller?.close();
6999
+ },
7000
+ error(error) {
7001
+ if (closed) return;
7002
+ closed = true;
7003
+ controller?.error(error);
7004
+ }
7005
+ };
7006
+ }
7007
+ function buildSessionCommand(command, options) {
7008
+ const cwdPrefix = options.cwd ? `cd ${shellQuote2(options.cwd)} && ` : "";
7009
+ const env = options.env ?? {};
7010
+ const entries = Object.entries(env);
7011
+ if (entries.length === 0) {
7012
+ return `sh -lc ${shellQuote2(`${cwdPrefix}${command}`)}`;
7013
+ }
7014
+ for (const [key] of entries) {
7015
+ validateEnvKey(key);
7016
+ }
7017
+ const exports = entries.map(([key, value]) => `export ${key}=${shellQuote2(value)}`).join("; ");
7018
+ return `sh -lc ${shellQuote2(`${exports}; ${cwdPrefix}${command}`)}`;
7019
+ }
7020
+ function validateEnvKey(key) {
7021
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
7022
+ throw new DaytonaSandboxError(
7023
+ `Invalid environment variable key: "${key}". Use shell-compatible environment variable names.`
7024
+ );
7025
+ }
7026
+ }
7027
+ function createSessionId(kind) {
7028
+ return `deepagents-${kind}-${randomUUID()}`;
7029
+ }
7030
+ function abortedCommandResult() {
7031
+ return {
7032
+ stdout: "",
7033
+ stderr: "Command aborted",
7034
+ exitCode: 1
7035
+ };
7036
+ }
7037
+ function abortedExitInfo() {
7038
+ return {
7039
+ code: null,
7040
+ signal: "SIGKILL",
7041
+ success: false
7042
+ };
7043
+ }
7044
+ function shellQuote2(value) {
7045
+ return `'${value.replace(/'/g, `'\\''`)}'`;
7046
+ }
7047
+ function uniqueParentDirectories(paths) {
7048
+ const dirs = /* @__PURE__ */ new Set();
7049
+ for (const path5 of paths) {
7050
+ const index = path5.lastIndexOf("/");
7051
+ if (index > 0) {
7052
+ dirs.add(path5.slice(0, index));
7053
+ }
7054
+ }
7055
+ return [...dirs];
7056
+ }
7057
+ function compactObject(input) {
7058
+ const output = {};
7059
+ for (const [key, value] of Object.entries(input)) {
7060
+ if (value !== void 0) {
7061
+ output[key] = value;
7062
+ }
7063
+ }
7064
+ return output;
7065
+ }
7066
+ function isMissingDaytonaSdk(error) {
7067
+ const maybeCode = error.code;
7068
+ return maybeCode === "ERR_MODULE_NOT_FOUND" || maybeCode === "MODULE_NOT_FOUND" || error.message.includes("@daytona/sdk");
7069
+ }
7070
+ function toError(error) {
7071
+ return error instanceof Error ? error : new Error(String(error));
7072
+ }
7073
+
6409
7074
  // packages/context/src/lib/sandbox/docker-sandbox.ts
6410
7075
  import "bash-tool";
6411
7076
  import spawn3 from "nano-spawn";
6412
7077
  import { spawn as childSpawn } from "node:child_process";
6413
7078
  import { createHash } from "node:crypto";
6414
7079
  import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
6415
- import { Readable } from "node:stream";
7080
+ import { Readable as Readable2 } from "node:stream";
6416
7081
 
6417
7082
  // packages/context/src/lib/sandbox/docker-sandbox-errors.ts
6418
7083
  var DockerSandboxError = class extends Error {
@@ -6559,7 +7224,7 @@ function isDebianBased(image) {
6559
7224
  const debianPatterns = ["debian", "ubuntu", "node", "python"];
6560
7225
  return debianPatterns.some((pattern) => lower.includes(pattern));
6561
7226
  }
6562
- function shellQuote2(s) {
7227
+ function shellQuote3(s) {
6563
7228
  return `'${s.replace(/'/g, `'\\''`)}'`;
6564
7229
  }
6565
7230
  function createInstallerContext(containerId, image) {
@@ -6607,7 +7272,7 @@ function createInstallerContext(containerId, image) {
6607
7272
  };
6608
7273
  const installPackages = async (packages) => {
6609
7274
  if (packages.length === 0) return;
6610
- const quoted = packages.map(shellQuote2).join(" ");
7275
+ const quoted = packages.map(shellQuote3).join(" ");
6611
7276
  let cmd;
6612
7277
  if (packageManager === "apt-get") {
6613
7278
  cmd = aptUpdated ? `apt-get install -y ${quoted}` : `apt-get update && apt-get install -y ${quoted}`;
@@ -6629,7 +7294,7 @@ function createInstallerContext(containerId, image) {
6629
7294
  const ensureTool = async (checkName, installName) => {
6630
7295
  const cacheKey = installName ?? checkName;
6631
7296
  if (ensuredTools.has(cacheKey)) return;
6632
- const check = await exec(`which ${shellQuote2(checkName)}`);
7297
+ const check = await exec(`which ${shellQuote3(checkName)}`);
6633
7298
  if (check.exitCode === 0) {
6634
7299
  ensuredTools.add(cacheKey);
6635
7300
  return;
@@ -6662,11 +7327,12 @@ var DockerSandboxStrategy = class {
6662
7327
  resources;
6663
7328
  env;
6664
7329
  name;
7330
+ command;
6665
7331
  createdVolumes = /* @__PURE__ */ new Set();
6666
7332
  constructor(args = {}) {
6667
- const { volumes = [], resources = {}, env = {}, name } = args;
7333
+ const { volumes = [], resources = {}, env = {}, name, command } = args;
6668
7334
  for (const key of Object.keys(env)) {
6669
- validateEnvKey(key);
7335
+ validateEnvKey2(key);
6670
7336
  }
6671
7337
  if (name !== void 0 && !CONTAINER_NAME_PATTERN.test(name)) {
6672
7338
  throw new DockerSandboxError(
@@ -6677,6 +7343,7 @@ var DockerSandboxStrategy = class {
6677
7343
  this.resources = resources;
6678
7344
  this.env = env;
6679
7345
  this.name = name;
7346
+ this.command = command;
6680
7347
  }
6681
7348
  async create() {
6682
7349
  const image = await this.getImage();
@@ -6884,7 +7551,12 @@ var DockerSandboxStrategy = class {
6884
7551
  for (const volume of this.volumes) {
6885
7552
  args.push("--mount", this.buildVolumeMountArg(volume));
6886
7553
  }
6887
- args.push(image, "tail", "-f", "/dev/null");
7554
+ args.push(image);
7555
+ if (this.command === void 0) {
7556
+ args.push("tail", "-f", "/dev/null");
7557
+ } else if (this.command !== null) {
7558
+ args.push(...this.command);
7559
+ }
6888
7560
  return args;
6889
7561
  }
6890
7562
  buildVolumeMountArg(volume) {
@@ -7071,7 +7743,7 @@ var DockerSandboxStrategy = class {
7071
7743
  return sandbox;
7072
7744
  }
7073
7745
  };
7074
- function validateEnvKey(key) {
7746
+ function validateEnvKey2(key) {
7075
7747
  if (key.length === 0 || key.includes("=")) {
7076
7748
  throw new DockerSandboxError(`Invalid environment variable key: "${key}"`);
7077
7749
  }
@@ -7083,7 +7755,7 @@ function buildDockerExecFlags(options) {
7083
7755
  }
7084
7756
  if (options?.env) {
7085
7757
  for (const [key, value] of Object.entries(options.env)) {
7086
- validateEnvKey(key);
7758
+ validateEnvKey2(key);
7087
7759
  flags.push("-e", `${key}=${value}`);
7088
7760
  }
7089
7761
  }
@@ -7100,8 +7772,8 @@ function toSandboxProcess(child, abortSignal) {
7100
7772
  else abortSignal.addEventListener("abort", onAbort, { once: true });
7101
7773
  }
7102
7774
  return {
7103
- stdout: Readable.toWeb(child.stdout),
7104
- stderr: Readable.toWeb(child.stderr),
7775
+ stdout: Readable2.toWeb(child.stdout),
7776
+ stderr: Readable2.toWeb(child.stderr),
7105
7777
  exit: new Promise((resolve4, reject) => {
7106
7778
  const settle = () => {
7107
7779
  child.removeListener("exit", onExitEvent);
@@ -7131,7 +7803,8 @@ var RuntimeStrategy = class extends DockerSandboxStrategy {
7131
7803
  volumes: args.volumes,
7132
7804
  resources: args.resources,
7133
7805
  env: args.env,
7134
- name: args.name
7806
+ name: args.name,
7807
+ command: args.command
7135
7808
  });
7136
7809
  this.image = args.image ?? "alpine:latest";
7137
7810
  this.installers = args.installers ?? [];
@@ -7155,7 +7828,8 @@ var DockerfileStrategy = class extends DockerSandboxStrategy {
7155
7828
  volumes: args.volumes,
7156
7829
  resources: args.resources,
7157
7830
  env: args.env,
7158
- name: args.name
7831
+ name: args.name,
7832
+ command: args.command
7159
7833
  });
7160
7834
  this.dockerfile = args.dockerfile;
7161
7835
  this.dockerContext = args.context ?? ".";
@@ -7324,7 +7998,8 @@ async function createDockerSandbox(options = {}) {
7324
7998
  volumes: options.volumes,
7325
7999
  resources: options.resources,
7326
8000
  env: options.env,
7327
- name: options.name
8001
+ name: options.name,
8002
+ command: options.command
7328
8003
  });
7329
8004
  } else {
7330
8005
  strategy = new RuntimeStrategy({
@@ -7333,7 +8008,8 @@ async function createDockerSandbox(options = {}) {
7333
8008
  volumes: options.volumes,
7334
8009
  resources: options.resources,
7335
8010
  env: options.env,
7336
- name: options.name
8011
+ name: options.name,
8012
+ command: options.command
7337
8013
  });
7338
8014
  }
7339
8015
  return strategy.create();
@@ -7347,60 +8023,6 @@ async function useSandbox(options, fn) {
7347
8023
  }
7348
8024
  }
7349
8025
 
7350
- // packages/context/src/lib/sandbox/container-tool.ts
7351
- async function createContainerTool(options = {}) {
7352
- let sandboxOptions;
7353
- let bashOptions;
7354
- let skillInputs = [];
7355
- if (isComposeOptions(options)) {
7356
- const { compose, service, resources, skills: skills2 = [], ...rest } = options;
7357
- sandboxOptions = { compose, service, resources };
7358
- bashOptions = rest;
7359
- skillInputs = skills2;
7360
- } else if (isDockerfileOptions(options)) {
7361
- const {
7362
- dockerfile,
7363
- context,
7364
- volumes,
7365
- resources,
7366
- env,
7367
- name,
7368
- skills: skills2 = [],
7369
- ...rest
7370
- } = options;
7371
- sandboxOptions = { dockerfile, context, volumes, resources, env, name };
7372
- bashOptions = rest;
7373
- skillInputs = skills2;
7374
- } else {
7375
- const {
7376
- image,
7377
- installers,
7378
- volumes,
7379
- resources,
7380
- env,
7381
- name,
7382
- skills: skills2 = [],
7383
- ...rest
7384
- } = options;
7385
- sandboxOptions = { image, installers, volumes, resources, env, name };
7386
- bashOptions = rest;
7387
- skillInputs = skills2;
7388
- }
7389
- const backend = await createDockerSandbox(sandboxOptions);
7390
- const toolkit = await createBashTool({
7391
- ...bashOptions,
7392
- sandbox: backend,
7393
- skills: skillInputs
7394
- });
7395
- return {
7396
- bash: toolkit.bash,
7397
- tools: toolkit.tools,
7398
- sandbox: toolkit.sandbox,
7399
- skills: toolkit.skills,
7400
- drainFileEvents: toolkit.drainFileEvents
7401
- };
7402
- }
7403
-
7404
8026
  // packages/context/src/lib/sandbox/installers/package-manager.ts
7405
8027
  var PackageInstaller = class extends Installer {
7406
8028
  kind;
@@ -7473,9 +8095,9 @@ async function downloadAndInstall(ctx, name, url, binaryPath, source = "url") {
7473
8095
  function buildTarGzInstallCmd(name, url, binaryPathInArchive) {
7474
8096
  return `
7475
8097
  set -e
7476
- NAME=${shellQuote2(name)}
7477
- URL=${shellQuote2(url)}
7478
- BIN_IN_ARCHIVE=${shellQuote2(binaryPathInArchive)}
8098
+ NAME=${shellQuote3(name)}
8099
+ URL=${shellQuote3(url)}
8100
+ BIN_IN_ARCHIVE=${shellQuote3(binaryPathInArchive)}
7479
8101
  TMPDIR=$(mktemp -d)
7480
8102
  cd "$TMPDIR"
7481
8103
  curl -fsSL "$URL" -o archive.tar.gz
@@ -7494,8 +8116,8 @@ function buildTarGzInstallCmd(name, url, binaryPathInArchive) {
7494
8116
  }
7495
8117
  function buildRawInstallCmd(name, url) {
7496
8118
  return `
7497
- NAME=${shellQuote2(name)}
7498
- URL=${shellQuote2(url)}
8119
+ NAME=${shellQuote3(name)}
8120
+ URL=${shellQuote3(url)}
7499
8121
  curl -fsSL "$URL" -o "/usr/local/bin/$NAME"
7500
8122
  chmod +x "/usr/local/bin/$NAME"
7501
8123
  `;
@@ -7548,6 +8170,59 @@ async function ensureNodeRuntime(ctx, ensure) {
7548
8170
  }
7549
8171
  }
7550
8172
 
8173
+ // packages/context/src/lib/sandbox/installers/bin.ts
8174
+ import { basename, posix } from "node:path";
8175
+ var NOT_FOUND_EXIT = 11;
8176
+ var CHMOD_FAILED_EXIT = 12;
8177
+ var BinInstaller = class extends Installer {
8178
+ kind;
8179
+ binary;
8180
+ options;
8181
+ #name;
8182
+ #target;
8183
+ constructor(binary, options = {}) {
8184
+ super();
8185
+ this.binary = binary;
8186
+ this.options = options;
8187
+ this.#name = resolveName(binary, options);
8188
+ this.#target = options.target ?? posix.join("/usr/local/bin", this.#name);
8189
+ this.kind = `bin:${this.#name}`;
8190
+ }
8191
+ async install(ctx) {
8192
+ const b = shellQuote3(this.binary);
8193
+ const t = shellQuote3(this.#target);
8194
+ const dir = shellQuote3(posix.dirname(this.#target));
8195
+ const result = await ctx.exec(
8196
+ `test -f ${b} || { echo "binary not found at ${this.binary}" >&2; exit ${NOT_FOUND_EXIT}; }; if ! test -x ${b}; then chmod +x ${b} || exit ${CHMOD_FAILED_EXIT}; fi; mkdir -p ${dir} && ln -sf ${b} ${t}`
8197
+ );
8198
+ if (result.exitCode === 0) return;
8199
+ throw new InstallError({
8200
+ target: this.#name,
8201
+ source: "bin",
8202
+ reason: explainFailure(result.exitCode, result.stderr, this.binary),
8203
+ containerId: ctx.containerId
8204
+ });
8205
+ }
8206
+ };
8207
+ function bin(binary, options) {
8208
+ return new BinInstaller(binary, options);
8209
+ }
8210
+ function explainFailure(exitCode, stderr, binary) {
8211
+ if (exitCode === NOT_FOUND_EXIT) {
8212
+ return `binary not found at ${binary}`;
8213
+ }
8214
+ if (exitCode === CHMOD_FAILED_EXIT && /read-only file system/i.test(stderr)) {
8215
+ return `${binary} is not executable and the bind mount is read-only \u2014 run \`chmod +x\` on the host, or mount with \`readOnly: false\`. (${stderr.trim()})`;
8216
+ }
8217
+ return stderr || `bin installer failed with exit code ${exitCode}`;
8218
+ }
8219
+ function resolveName(binary, options) {
8220
+ if (options.name) return options.name;
8221
+ const base = basename(binary);
8222
+ const dot = base.lastIndexOf(".");
8223
+ return dot > 0 ? base.slice(0, dot) : base;
8224
+ }
8225
+
7551
8226
  // packages/context/src/lib/sandbox/installers/pip.ts
7552
8227
  var PYTHON_BINARIES = ["python3", "pip3"];
7553
8228
  var PipInstaller = class extends Installer {
@@ -7811,7 +8486,7 @@ function soul() {
7811
8486
  }
7812
8487
 
7813
8488
  // packages/context/src/lib/store/postgres.store.ts
7814
- import { createRequire } from "node:module";
8489
+ import { createRequire as createRequire2 } from "node:module";
7815
8490
 
7816
8491
  // packages/context/src/lib/store/ddl.postgres.ts
7817
8492
  function storeDDL(schema) {
@@ -7923,7 +8598,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
7923
8598
  }
7924
8599
  static #requirePg() {
7925
8600
  try {
7926
- const require2 = createRequire(import.meta.url);
8601
+ const require2 = createRequire2(import.meta.url);
7927
8602
  return require2("pg");
7928
8603
  } catch {
7929
8604
  throw new Error(
@@ -8519,7 +9194,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
8519
9194
  };
8520
9195
 
8521
9196
  // packages/context/src/lib/store/sqlserver.store.ts
8522
- import { createRequire as createRequire2 } from "node:module";
9197
+ import { createRequire as createRequire3 } from "node:module";
8523
9198
 
8524
9199
  // packages/context/src/lib/store/ddl.sqlserver.ts
8525
9200
  function storeDDL2(schema) {
@@ -8661,7 +9336,7 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
8661
9336
  }
8662
9337
  static #requireMssql() {
8663
9338
  try {
8664
- const require2 = createRequire2(import.meta.url);
9339
+ const require2 = createRequire3(import.meta.url);
8665
9340
  return require2("mssql");
8666
9341
  } catch {
8667
9342
  throw new Error(
@@ -9371,11 +10046,12 @@ async function persistedWriter(options) {
9371
10046
  } = options;
9372
10047
  let seq = 0;
9373
10048
  let buffer = [];
10049
+ let failedByErrorChunk = false;
9374
10050
  async function flush() {
9375
10051
  if (buffer.length === 0) return;
9376
10052
  const batch = buffer;
9377
10053
  buffer = [];
9378
- await store2.appendChunks(batch);
10054
+ await appendBatch(batch);
9379
10055
  }
9380
10056
  function makeChunk(part) {
9381
10057
  return {
@@ -9385,9 +10061,19 @@ async function persistedWriter(options) {
9385
10061
  createdAt: Date.now()
9386
10062
  };
9387
10063
  }
10064
+ function isStreamErrorPart(part) {
10065
+ return part.type === "error";
10066
+ }
10067
+ async function appendBatch(batch) {
10068
+ const hasErrorPart = !failedByErrorChunk && batch.map((chunk) => chunk.data).some(isStreamErrorPart);
10069
+ await store2.appendChunks(batch);
10070
+ if (hasErrorPart) {
10071
+ failedByErrorChunk = true;
10072
+ }
10073
+ }
9388
10074
  async function persistChunk(chunk) {
9389
10075
  if (strategy === "immediate") {
9390
- await store2.appendChunks([chunk]);
10076
+ await appendBatch([chunk]);
9391
10077
  } else {
9392
10078
  buffer.push(chunk);
9393
10079
  if (buffer.length >= flushSize) {
@@ -9417,10 +10103,12 @@ async function persistedWriter(options) {
9417
10103
  flush,
9418
10104
  async complete() {
9419
10105
  await flush();
10106
+ if (failedByErrorChunk) return;
9420
10107
  await store2.updateStreamStatus(streamId, "completed");
9421
10108
  },
9422
10109
  async fail(error) {
9423
10110
  await flush();
10111
+ if (failedByErrorChunk) return;
9424
10112
  await store2.updateStreamStatus(streamId, "failed", { error });
9425
10113
  },
9426
10114
  async cleanup() {
@@ -9430,7 +10118,7 @@ async function persistedWriter(options) {
9430
10118
  }
9431
10119
 
9432
10120
  // packages/context/src/lib/stream/polling-change-source.ts
9433
- import { setTimeout as delay } from "node:timers/promises";
10121
+ import { setTimeout as delay2 } from "node:timers/promises";
9434
10122
 
9435
10123
  // packages/context/src/lib/stream/polling-policy.ts
9436
10124
  var DEFAULT_WATCH_POLLING = {
@@ -9475,7 +10163,7 @@ function nextAdaptivePollingDelay(state) {
9475
10163
  state.config.minMs,
9476
10164
  state.config.maxMs
9477
10165
  );
9478
- const delay2 = applyJitter(
10166
+ const delay3 = applyJitter(
9479
10167
  current,
9480
10168
  state.config.jitterRatio,
9481
10169
  state.config.minMs,
@@ -9486,7 +10174,7 @@ function nextAdaptivePollingDelay(state) {
9486
10174
  state.config.minMs,
9487
10175
  state.config.maxMs
9488
10176
  );
9489
- return delay2;
10177
+ return delay3;
9490
10178
  }
9491
10179
  function normalizeAdaptivePolling(polling, fallback) {
9492
10180
  const merged = {
@@ -9586,7 +10274,7 @@ function isTerminal(status) {
9586
10274
  return status !== "queued" && status !== "running";
9587
10275
  }
9588
10276
  function waitForDelay(ms, signal) {
9589
- return delay(ms, true, { signal }).catch((err) => {
10277
+ return delay2(ms, true, { signal }).catch((err) => {
9590
10278
  if (signal.aborted) return false;
9591
10279
  throw err;
9592
10280
  });
@@ -9638,7 +10326,7 @@ function asStaticWordPartText(parts, options = {}) {
9638
10326
  }
9639
10327
 
9640
10328
  // packages/context/src/lib/stream/postgres-notify-change-source.ts
9641
- import { createRequire as createRequire3 } from "node:module";
10329
+ import { createRequire as createRequire4 } from "node:module";
9642
10330
 
9643
10331
  // packages/context/src/lib/stream/ddl.stream.postgres-notify.ts
9644
10332
  var DEFAULT_POSTGRES_STREAM_CHANGES_CHANNEL = "deepagents_stream_changes";
@@ -9740,7 +10428,7 @@ var PostgresNotifyChangeSource = class _PostgresNotifyChangeSource {
9740
10428
  }
9741
10429
  static #requirePg() {
9742
10430
  try {
9743
- const require2 = createRequire3(import.meta.url);
10431
+ const require2 = createRequire4(import.meta.url);
9744
10432
  return require2("pg");
9745
10433
  } catch {
9746
10434
  throw new Error(
@@ -9995,7 +10683,7 @@ function assertIdentifier(value, label) {
9995
10683
  }
9996
10684
 
9997
10685
  // packages/context/src/lib/stream/postgres.stream-store.ts
9998
- import { createRequire as createRequire4 } from "node:module";
10686
+ import { createRequire as createRequire5 } from "node:module";
9999
10687
 
10000
10688
  // packages/context/src/lib/stream/ddl.stream.postgres.ts
10001
10689
  function postgresStreamDDL(schema) {
@@ -10031,6 +10719,15 @@ CREATE INDEX IF NOT EXISTS "idx_${schema}_streams_status_created_at_id"
10031
10719
  }
10032
10720
 
10033
10721
  // packages/context/src/lib/stream/stream-store.ts
10722
+ function collectStreamFailures(chunks) {
10723
+ const failures = /* @__PURE__ */ new Map();
10724
+ for (const chunk of chunks) {
10725
+ if (chunk.data.type === "error" && !failures.has(chunk.streamId)) {
10726
+ failures.set(chunk.streamId, chunk.data.errorText);
10727
+ }
10728
+ }
10729
+ return [...failures].map(([streamId, error]) => ({ streamId, error }));
10730
+ }
10034
10731
  var StreamStore = class {
10035
10732
  async listRunningStreamIds() {
10036
10733
  return this.listStreamIds({ status: "running" });
@@ -10060,7 +10757,7 @@ var PostgresStreamStore = class _PostgresStreamStore extends StreamStore {
10060
10757
  }
10061
10758
  static #requirePg() {
10062
10759
  try {
10063
- const require2 = createRequire4(import.meta.url);
10760
+ const require2 = createRequire5(import.meta.url);
10064
10761
  return require2("pg");
10065
10762
  } catch {
10066
10763
  throw new Error(
@@ -10214,13 +10911,31 @@ var PostgresStreamStore = class _PostgresStreamStore extends StreamStore {
10214
10911
  data: chunk.data,
10215
10912
  created_at: chunk.createdAt
10216
10913
  }));
10217
- await this.#query(
10218
- `INSERT INTO ${this.#t("stream_chunks")} (stream_id, seq, data, created_at)
10914
+ const params = [JSON.stringify(rows)];
10915
+ const insertSql = `INSERT INTO ${this.#t("stream_chunks")} (stream_id, seq, data, created_at)
10219
10916
  SELECT stream_id, seq, data, created_at
10220
10917
  FROM jsonb_to_recordset($1::jsonb)
10221
- AS rows(stream_id TEXT, seq INTEGER, data JSONB, created_at BIGINT)`,
10222
- [JSON.stringify(rows)]
10223
- );
10918
+ AS rows(stream_id TEXT, seq INTEGER, data JSONB, created_at BIGINT)`;
10919
+ const failures = collectStreamFailures(chunks);
10920
+ if (failures.length === 0) {
10921
+ await this.#query(insertSql, params);
10922
+ return;
10923
+ }
10924
+ await this.#useTransaction(async (client) => {
10925
+ await client.query(insertSql, params);
10926
+ const failedAt = Date.now();
10927
+ for (const failure of failures) {
10928
+ const result = await client.query(
10929
+ `UPDATE ${this.#t("streams")}
10930
+ SET status = $1, finished_at = $2, error = $3
10931
+ WHERE id = $4`,
10932
+ ["failed", failedAt, failure.error, failure.streamId]
10933
+ );
10934
+ if (result.rowCount !== 1) {
10935
+ throw new Error(`Stream "${failure.streamId}" not found`);
10936
+ }
10937
+ }
10938
+ });
10224
10939
  }
10225
10940
  async getChunks(streamId, fromSeq, limit) {
10226
10941
  const params = [streamId];
@@ -10467,6 +11182,7 @@ var SqliteStreamStore = class extends StreamStore {
10467
11182
  }
10468
11183
  async appendChunks(chunks) {
10469
11184
  if (chunks.length === 0) return;
11185
+ const failures = collectStreamFailures(chunks);
10470
11186
  this.#db.exec("BEGIN TRANSACTION");
10471
11187
  try {
10472
11188
  for (const chunk of chunks) {
@@ -10480,6 +11196,15 @@ var SqliteStreamStore = class extends StreamStore {
10480
11196
  chunk.createdAt
10481
11197
  );
10482
11198
  }
11199
+ const failedAt = Date.now();
11200
+ for (const failure of failures) {
11201
+ const result = this.#stmt(
11202
+ "UPDATE streams SET status = ?, finishedAt = ?, error = ? WHERE id = ?"
11203
+ ).run("failed", failedAt, failure.error, failure.streamId);
11204
+ if (result.changes !== 1) {
11205
+ throw new Error(`Stream "${failure.streamId}" not found`);
11206
+ }
11207
+ }
10483
11208
  this.#db.exec("COMMIT");
10484
11209
  } catch (error) {
10485
11210
  this.#db.exec("ROLLBACK");
@@ -10881,14 +11606,20 @@ export {
10881
11606
  AsyncResolver,
10882
11607
  BM25Classifier,
10883
11608
  BashException,
11609
+ BinInstaller,
10884
11610
  ComposeStartError,
10885
11611
  ComposeStrategy,
10886
11612
  ContainerCreationError,
10887
11613
  ContextEngine,
10888
11614
  ContextRenderer,
10889
11615
  ContextStore,
11616
+ DAYTONA_DEFAULT_DESTINATION,
10890
11617
  DEFAULT_CANCEL_POLLING,
10891
11618
  DEFAULT_WATCH_POLLING,
11619
+ DaytonaCommandError,
11620
+ DaytonaCreationError,
11621
+ DaytonaNotAvailableError,
11622
+ DaytonaSandboxError,
10892
11623
  DockerNotAvailableError,
10893
11624
  DockerSandboxError,
10894
11625
  DockerSandboxStrategy,
@@ -10950,11 +11681,13 @@ export {
10950
11681
  assertCountSpec,
10951
11682
  assistant,
10952
11683
  assistantText,
11684
+ bin,
10953
11685
  buildSubcommandRepair,
10954
11686
  chat,
10955
11687
  checkCount,
10956
11688
  clarification,
10957
11689
  classifies,
11690
+ collectStreamFailures,
10958
11691
  contentIncludes,
10959
11692
  contentMatches,
10960
11693
  contentPattern,
@@ -10963,7 +11696,7 @@ export {
10963
11696
  createAgentOsSandbox,
10964
11697
  createBashTool,
10965
11698
  createBinaryBridges,
10966
- createContainerTool,
11699
+ createDaytonaSandbox,
10967
11700
  createDockerSandbox,
10968
11701
  createInstallerContext,
10969
11702
  createRepairToolCall,
@@ -11054,7 +11787,7 @@ export {
11054
11787
  seasonChanged,
11055
11788
  seasonReminder,
11056
11789
  selfCritique,
11057
- shellQuote2 as shellQuote,
11790
+ shellQuote3 as shellQuote,
11058
11791
  skills,
11059
11792
  skillsReminder,
11060
11793
  socraticPrompting,