@aiden-ade/sandbox-agent 0.1.24 → 0.1.26

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 (77) hide show
  1. package/dist/__tests__/cli-executable.test.d.ts +2 -0
  2. package/dist/__tests__/cli-executable.test.d.ts.map +1 -0
  3. package/dist/__tests__/cli-executable.test.js +83 -0
  4. package/dist/__tests__/cli-executable.test.js.map +1 -0
  5. package/dist/__tests__/cli-help.test.d.ts +2 -0
  6. package/dist/__tests__/cli-help.test.d.ts.map +1 -0
  7. package/dist/__tests__/cli-help.test.js +33 -0
  8. package/dist/__tests__/cli-help.test.js.map +1 -0
  9. package/dist/__tests__/core-agent-workflow-context.test.d.ts +2 -0
  10. package/dist/__tests__/core-agent-workflow-context.test.d.ts.map +1 -0
  11. package/dist/__tests__/core-agent-workflow-context.test.js +50 -0
  12. package/dist/__tests__/core-agent-workflow-context.test.js.map +1 -0
  13. package/dist/__tests__/daemon-socket.integration.test.d.ts +2 -0
  14. package/dist/__tests__/daemon-socket.integration.test.d.ts.map +1 -0
  15. package/dist/__tests__/daemon-socket.integration.test.js +156 -0
  16. package/dist/__tests__/daemon-socket.integration.test.js.map +1 -0
  17. package/dist/__tests__/daemon.test.d.ts +2 -0
  18. package/dist/__tests__/daemon.test.d.ts.map +1 -0
  19. package/dist/__tests__/daemon.test.js +1014 -0
  20. package/dist/__tests__/daemon.test.js.map +1 -0
  21. package/dist/__tests__/generated-images.test.d.ts +2 -0
  22. package/dist/__tests__/generated-images.test.d.ts.map +1 -0
  23. package/dist/__tests__/generated-images.test.js +50 -0
  24. package/dist/__tests__/generated-images.test.js.map +1 -0
  25. package/dist/__tests__/sandbox-workflow-context.test.d.ts +2 -0
  26. package/dist/__tests__/sandbox-workflow-context.test.d.ts.map +1 -0
  27. package/dist/__tests__/sandbox-workflow-context.test.js +66 -0
  28. package/dist/__tests__/sandbox-workflow-context.test.js.map +1 -0
  29. package/dist/aiden-system-prompt.d.ts +6 -0
  30. package/dist/aiden-system-prompt.d.ts.map +1 -0
  31. package/dist/aiden-system-prompt.js +6 -0
  32. package/dist/aiden-system-prompt.js.map +1 -0
  33. package/dist/cli-executable.d.ts +58 -0
  34. package/dist/cli-executable.d.ts.map +1 -0
  35. package/dist/cli-executable.js +301 -0
  36. package/dist/cli-executable.js.map +1 -0
  37. package/dist/cli-help.d.ts +7 -0
  38. package/dist/cli-help.d.ts.map +1 -0
  39. package/dist/cli-help.js +45 -0
  40. package/dist/cli-help.js.map +1 -0
  41. package/dist/core-agent.d.ts +6 -2
  42. package/dist/core-agent.d.ts.map +1 -1
  43. package/dist/core-agent.js +140 -21
  44. package/dist/core-agent.js.map +1 -1
  45. package/dist/daemon.d.ts +46 -0
  46. package/dist/daemon.d.ts.map +1 -0
  47. package/dist/daemon.js +876 -0
  48. package/dist/daemon.js.map +1 -0
  49. package/dist/generated-images.d.ts +4 -0
  50. package/dist/generated-images.d.ts.map +1 -0
  51. package/dist/generated-images.js +142 -0
  52. package/dist/generated-images.js.map +1 -0
  53. package/dist/index.cjs +363 -42
  54. package/dist/index.d.ts +4 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +107 -42
  57. package/dist/index.js.map +1 -1
  58. package/dist/sandbox.d.ts +6 -0
  59. package/dist/sandbox.d.ts.map +1 -1
  60. package/dist/sandbox.js +40 -10
  61. package/dist/sandbox.js.map +1 -1
  62. package/dist/updater.d.ts.map +1 -1
  63. package/dist/updater.js +0 -4
  64. package/dist/updater.js.map +1 -1
  65. package/dist/version.d.ts +1 -1
  66. package/dist/version.d.ts.map +1 -1
  67. package/dist/version.js +1 -1
  68. package/dist/version.js.map +1 -1
  69. package/dist/web-presenter.d.ts +7 -4
  70. package/dist/web-presenter.d.ts.map +1 -1
  71. package/dist/web-presenter.js +29 -4
  72. package/dist/web-presenter.js.map +1 -1
  73. package/dist/ws-client.d.ts +35 -0
  74. package/dist/ws-client.d.ts.map +1 -1
  75. package/dist/ws-client.js +32 -9
  76. package/dist/ws-client.js.map +1 -1
  77. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -9598,7 +9598,7 @@ var PRIORITY_OPTIONS = [
9598
9598
  detail: "Low",
9599
9599
  color: CATEGORICAL_COLORS.blueBright,
9600
9600
  iconClass: "text-blue-500/70 dark:text-blue-400/70",
9601
- flagClass: "text-primary"
9601
+ flagClass: "text-blue-600 dark:text-blue-400"
9602
9602
  },
9603
9603
  {
9604
9604
  value: "none",
@@ -10225,10 +10225,7 @@ function createClaudeCliBackend(command = "claude", defaultArgs = []) {
10225
10225
  stdin.write(`${message}
10226
10226
  `);
10227
10227
  },
10228
- keepStdinOpen: true,
10229
- allowContinuation: true,
10230
- continuationIdleMs: 10 * 60 * 1e3
10231
- // 10 minutes
10228
+ keepStdinOpen: true
10232
10229
  }).run(context);
10233
10230
  }
10234
10231
  };
@@ -10251,6 +10248,10 @@ function createImageTempDirectory(cwd) {
10251
10248
  }
10252
10249
  return (0, import_fs2.mkdtempSync)((0, import_path2.join)((0, import_os2.tmpdir)(), "aiden-images-"));
10253
10250
  }
10251
+ function safeFilename(filename) {
10252
+ const safe = filename.replace(/[^a-zA-Z0-9._-]/g, "_").replace(/^_+/, "");
10253
+ return safe || "attachment";
10254
+ }
10254
10255
  function writeImagesToTempFiles(images, cwd) {
10255
10256
  if (!images?.length) return { paths: [], files: [], cleanup: () => {
10256
10257
  } };
@@ -10281,6 +10282,48 @@ function writeImagesToTempFiles(images, cwd) {
10281
10282
  }
10282
10283
  };
10283
10284
  }
10285
+ function writeFilesToTempFiles(files, cwd) {
10286
+ if (!files?.length) return { paths: [], files: [], cleanup: () => {
10287
+ } };
10288
+ const dataFiles = files.filter((file) => file.data !== void 0);
10289
+ const existingFiles = files.filter((file) => file.tempPath && file.data === void 0);
10290
+ const directory = dataFiles.length > 0 ? createImageTempDirectory(cwd) : null;
10291
+ const paths = [];
10292
+ const tempFiles = [];
10293
+ for (const file of existingFiles) {
10294
+ if (!file.tempPath) continue;
10295
+ paths.push(file.tempPath);
10296
+ tempFiles.push({
10297
+ filename: file.filename,
10298
+ mimeType: file.mimeType,
10299
+ label: file.label,
10300
+ path: file.tempPath
10301
+ });
10302
+ }
10303
+ for (const file of dataFiles) {
10304
+ if (!directory || file.data === void 0) continue;
10305
+ const filePath = (0, import_path2.join)(directory, `${file.id}-${safeFilename(file.filename)}`);
10306
+ (0, import_fs2.writeFileSync)(filePath, Buffer.from(file.data, "base64"));
10307
+ paths.push(filePath);
10308
+ tempFiles.push({
10309
+ filename: file.filename,
10310
+ mimeType: file.mimeType,
10311
+ label: file.label,
10312
+ path: filePath
10313
+ });
10314
+ }
10315
+ return {
10316
+ paths,
10317
+ files: tempFiles,
10318
+ cleanup: () => {
10319
+ if (!directory) return;
10320
+ try {
10321
+ (0, import_fs2.rmSync)(directory, { recursive: true, force: true });
10322
+ } catch {
10323
+ }
10324
+ }
10325
+ };
10326
+ }
10284
10327
  function appendImagePathReferences(prompt, images) {
10285
10328
  if (images.length === 0) return prompt;
10286
10329
  const imageLines = images.map((img) => {
@@ -11452,6 +11495,17 @@ function isOpenCodeToolError(parsed, part) {
11452
11495
  const state = getRecord(part?.state) ?? getRecord(parsed.state);
11453
11496
  return part?.is_error === true || part?.isError === true || state?.status === "error" || Boolean(getOpenCodeToolError(parsed, part));
11454
11497
  }
11498
+ function getOpenCodePartId(parsed, part) {
11499
+ return getString(part?.id) || getString(parsed.id) || getString(parsed.partID);
11500
+ }
11501
+ function resolveOpenCodeTextDelta(text, partId, state) {
11502
+ if (!partId) return text;
11503
+ state.opencodeTextByPartId ??= /* @__PURE__ */ new Map();
11504
+ const previous = state.opencodeTextByPartId.get(partId) ?? "";
11505
+ state.opencodeTextByPartId.set(partId, text);
11506
+ if (!previous || !text.startsWith(previous)) return text;
11507
+ return text.slice(previous.length);
11508
+ }
11455
11509
  function parseOpencodeStructuredLine(line, context, state) {
11456
11510
  const presenter = context.presenter;
11457
11511
  let parsed = null;
@@ -11475,8 +11529,10 @@ function parseOpencodeStructuredLine(line, context, state) {
11475
11529
  case "text": {
11476
11530
  const text = part && typeof part.text === "string" ? part.text : "";
11477
11531
  if (text) {
11478
- state.summary += text;
11479
- void presenter.onAssistantText(text);
11532
+ const delta = resolveOpenCodeTextDelta(text, getOpenCodePartId(parsed, part), state);
11533
+ if (!delta) break;
11534
+ state.summary += delta;
11535
+ void presenter.onAssistantText(delta);
11480
11536
  }
11481
11537
  break;
11482
11538
  }
@@ -11614,6 +11670,10 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
11614
11670
  context.config.images,
11615
11671
  context.cwd
11616
11672
  );
11673
+ const { paths: filePaths, cleanup: cleanupFiles } = writeFilesToTempFiles(
11674
+ context.config.files,
11675
+ context.cwd
11676
+ );
11617
11677
  try {
11618
11678
  const runContext = withAutonomousOpenCodePermissions(context);
11619
11679
  return await createGenericCliBackend({
@@ -11630,7 +11690,8 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
11630
11690
  if (resumeId) args.push("--session", resumeId);
11631
11691
  const model = ctx.config.selectedModel?.trim();
11632
11692
  if (model?.includes("/")) args.push("--model", model);
11633
- const fileArgs = imagePaths.flatMap((p) => ["--file", p]);
11693
+ const attachmentPaths = [...imagePaths, ...filePaths];
11694
+ const fileArgs = attachmentPaths.flatMap((p) => ["--file", p]);
11634
11695
  if (fileArgs.length > 0) {
11635
11696
  return [...args, ...fileArgs, ...defaultArgs, "--", prompt];
11636
11697
  }
@@ -11644,6 +11705,7 @@ function createOpencodeCliBackend(command = "opencode", defaultArgs = []) {
11644
11705
  }).run(runContext);
11645
11706
  } finally {
11646
11707
  cleanup();
11708
+ cleanupFiles();
11647
11709
  }
11648
11710
  }
11649
11711
  };
@@ -11849,7 +11911,8 @@ function canonicalizePath(inputPath) {
11849
11911
  }
11850
11912
  function buildPromptWithFiles(task, files) {
11851
11913
  if (!files || files.length === 0) return task;
11852
- const fileList = files.map((file) => `- ${file.filename} (${file.label}): ${file.tempPath}`).join("\n");
11914
+ const fileList = files.filter((file) => file.tempPath).map((file) => `- ${file.filename} (${file.label}): ${file.tempPath}`).join("\n");
11915
+ if (!fileList) return task;
11853
11916
  return `${task}
11854
11917
 
11855
11918
  The user has attached the following files. You can read them using your available tools:
@@ -12607,7 +12670,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName) {
12607
12670
  }
12608
12671
 
12609
12672
  // src/version.ts
12610
- var AGENT_VERSION = "0.1.24";
12673
+ var AGENT_VERSION = "0.1.26";
12611
12674
 
12612
12675
  // src/daemon.ts
12613
12676
  var OPENCODE_FREE_MODEL_IDS = [
@@ -12621,6 +12684,23 @@ var PRODUCTION_API_URL = "https://api.aiden-platform.com";
12621
12684
  var PRODUCTION_WS_URL = "wss://ws.aiden-platform.com";
12622
12685
  var LOCAL_API_URL = "http://localhost:8400";
12623
12686
  var LOCAL_WS_URL = "ws://localhost:8401";
12687
+ function correlationLogFields(input) {
12688
+ return Object.fromEntries(
12689
+ Object.entries({
12690
+ taskId: input.taskId,
12691
+ conversationId: input.conversationId,
12692
+ runId: input.runId,
12693
+ messageId: input.messageId,
12694
+ cloudEnvironmentId: input.cloudEnvironmentId,
12695
+ provider: input.backendKind,
12696
+ backendKind: input.backendKind,
12697
+ agentVersion: input.agentVersion
12698
+ }).filter((entry) => {
12699
+ const value2 = entry[1];
12700
+ return typeof value2 === "string" && value2.trim().length > 0;
12701
+ }).map(([key, value2]) => [key, value2.trim()])
12702
+ );
12703
+ }
12624
12704
  async function probeLocalDaemonEndpoint(port, token, timeoutMs = 750) {
12625
12705
  try {
12626
12706
  const headers = {};
@@ -12857,12 +12937,13 @@ async function collectRuntimeMetadataWithProviderLimits() {
12857
12937
  return metadata;
12858
12938
  }
12859
12939
  var RuntimePresenter = class {
12860
- constructor(socket, conversationId, runId, cwd, touchRunnerActivity) {
12940
+ constructor(socket, conversationId, runId, cwd, touchRunnerActivity, onRunComplete) {
12861
12941
  this.socket = socket;
12862
12942
  this.conversationId = conversationId;
12863
12943
  this.runId = runId;
12864
12944
  this.cwd = cwd;
12865
12945
  this.touchRunnerActivity = touchRunnerActivity;
12946
+ this.onRunComplete = onRunComplete;
12866
12947
  }
12867
12948
  emittedGeneratedImageKeys = /* @__PURE__ */ new Set();
12868
12949
  toolNamesById = /* @__PURE__ */ new Map();
@@ -12949,6 +13030,7 @@ var RuntimePresenter = class {
12949
13030
  }
12950
13031
  onComplete(result) {
12951
13032
  this.emitEvent({ type: "query_complete", result, ts: Date.now() });
13033
+ this.onRunComplete?.();
12952
13034
  }
12953
13035
  };
12954
13036
  async function setupDaemon(args) {
@@ -12957,7 +13039,6 @@ async function setupDaemon(args) {
12957
13039
  const setupToken = argValue(args, "--setup-token") ?? process.env.AIDEN_RUNTIME_SETUP_TOKEN;
12958
13040
  const token = argValue(args, "--token") ?? process.env.AIDEN_SETUP_TOKEN;
12959
13041
  const displayName = argValue(args, "--name") ?? (0, import_node_os4.hostname)();
12960
- const legacyLocalMachineId = argValue(args, "--legacy-local-machine-id") ?? process.env.AIDEN_LEGACY_LOCAL_MACHINE_ID;
12961
13042
  const scope = argValue(args, "--scope") ?? process.env.AIDEN_RUNTIME_SCOPE ?? "team";
12962
13043
  if (scope !== "team" && scope !== "user") {
12963
13044
  throw new Error("setup --scope must be either 'team' or 'user'");
@@ -12980,7 +13061,6 @@ async function setupDaemon(args) {
12980
13061
  ...setupToken ? { setupToken } : {},
12981
13062
  displayName,
12982
13063
  hostname: (0, import_node_os4.hostname)(),
12983
- ...legacyLocalMachineId ? { legacyLocalMachineId } : {},
12984
13064
  runtimeKind: "machine",
12985
13065
  managementKind: "user_managed",
12986
13066
  hostKind: "daemon",
@@ -13149,19 +13229,34 @@ async function startDaemon(args) {
13149
13229
  return;
13150
13230
  }
13151
13231
  socket.emit("agent.accepted", { runId: payload.runId });
13232
+ const correlation = correlationLogFields({
13233
+ taskId: payload.taskId ?? payload.taskMeta?.id,
13234
+ conversationId: payload.conversationId,
13235
+ runId: payload.runId,
13236
+ messageId: payload.messageId,
13237
+ cloudEnvironmentId: payload.cloudEnvironmentId,
13238
+ backendKind,
13239
+ agentVersion: AGENT_VERSION
13240
+ });
13152
13241
  pushLog(`accepted run=${payload.runId}`);
13242
+ console.info("[aiden-agent] Agent run accepted", correlation);
13153
13243
  const cwd = payload.projectPath ?? process.cwd();
13154
13244
  const nowMs = Date.now();
13155
13245
  const touchActivity = () => {
13156
13246
  const entry = activeAgents.get(payload.runId);
13157
13247
  if (entry) entry.lastActivityAtMs = Date.now();
13158
13248
  };
13249
+ const releaseActiveRun = () => {
13250
+ if (!activeAgents.delete(payload.runId)) return;
13251
+ console.info("[aiden-agent] Agent run finished", correlation);
13252
+ };
13159
13253
  const presenter = new RuntimePresenter(
13160
13254
  socket,
13161
13255
  payload.conversationId,
13162
13256
  payload.runId,
13163
13257
  cwd,
13164
- touchActivity
13258
+ touchActivity,
13259
+ releaseActiveRun
13165
13260
  );
13166
13261
  const agent = new CoreAgent(presenter, {
13167
13262
  backendKind,
@@ -13190,21 +13285,26 @@ async function startDaemon(args) {
13190
13285
  taskMeta: payload.taskMeta,
13191
13286
  prMeta: payload.prMeta,
13192
13287
  conversationId: payload.conversationId,
13193
- taskId: payload.taskMeta?.id,
13288
+ taskId: payload.taskId ?? payload.taskMeta?.id,
13194
13289
  teamId: payload.teamId,
13195
13290
  currentUser: payload.currentUser,
13196
13291
  workflowTools: payload.workflowTools,
13197
- images: payload.images
13292
+ images: payload.images,
13293
+ files: payload.files
13198
13294
  }).catch((error) => {
13199
13295
  const message = error instanceof Error ? error.message : String(error);
13200
13296
  pushLog(`failed run=${payload.runId} ${message}`);
13297
+ console.error("[aiden-agent] Agent run failed", {
13298
+ ...correlation,
13299
+ error: message
13300
+ });
13201
13301
  socket.emit("agent.event", {
13202
13302
  conversationId: payload.conversationId,
13203
13303
  runId: payload.runId,
13204
13304
  event: { type: "session_error", error: message }
13205
13305
  });
13206
13306
  }).finally(() => {
13207
- activeAgents.delete(payload.runId);
13307
+ releaseActiveRun();
13208
13308
  });
13209
13309
  });
13210
13310
  socket.on("agent.abort", (payload) => {
@@ -13214,6 +13314,10 @@ async function startDaemon(args) {
13214
13314
  abortActiveAgent(entry);
13215
13315
  activeAgents.delete(payload.runId);
13216
13316
  pushLog(`aborted run=${payload.runId}`);
13317
+ console.info("[aiden-agent] Agent run aborted", {
13318
+ runId: payload.runId,
13319
+ agentVersion: AGENT_VERSION
13320
+ });
13217
13321
  });
13218
13322
  socket.on(
13219
13323
  "agent.tool_response",
@@ -13542,6 +13646,78 @@ async function printDoctor(args = []) {
13542
13646
  );
13543
13647
  }
13544
13648
 
13649
+ // src/lifecycle-logger.ts
13650
+ var AgentLifecycleLogger = class _AgentLifecycleLogger {
13651
+ context;
13652
+ constructor(context = {}) {
13653
+ this.context = normalizeContext(context);
13654
+ }
13655
+ setContext(context) {
13656
+ this.context = normalizeContext({ ...this.context, ...context });
13657
+ }
13658
+ child(context) {
13659
+ return new _AgentLifecycleLogger({ ...this.context, ...context });
13660
+ }
13661
+ debug(event, fields = {}) {
13662
+ this.log("debug", event, fields);
13663
+ }
13664
+ info(event, fields = {}) {
13665
+ this.log("info", event, fields);
13666
+ }
13667
+ warn(event, fields = {}) {
13668
+ this.log("warn", event, fields);
13669
+ }
13670
+ error(event, fields = {}) {
13671
+ this.log("error", event, fields);
13672
+ }
13673
+ log(level, event, fields) {
13674
+ const record = omitUndefined({
13675
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
13676
+ level,
13677
+ component: "sandbox-agent",
13678
+ event,
13679
+ ...this.context,
13680
+ ...normalizeFields(fields)
13681
+ });
13682
+ console[level](JSON.stringify(record));
13683
+ }
13684
+ };
13685
+ function lifecycleContextFromEnv(env) {
13686
+ return normalizeContext({
13687
+ taskId: env.AIDEN_TASK_ID,
13688
+ conversationId: env.AIDEN_SESSION_ID,
13689
+ runId: env.AIDEN_RUN_ID,
13690
+ sandboxId: env.AIDEN_SANDBOX_ID,
13691
+ provider: env.AIDEN_SANDBOX_PROVIDER,
13692
+ backendKind: env.AIDEN_BACKEND_KIND,
13693
+ agentVersion: AGENT_VERSION
13694
+ });
13695
+ }
13696
+ function normalizeContext(context) {
13697
+ return omitUndefined({
13698
+ ...context,
13699
+ agentVersion: context.agentVersion ?? AGENT_VERSION
13700
+ });
13701
+ }
13702
+ function normalizeFields(fields) {
13703
+ const normalized = {};
13704
+ for (const [key, value2] of Object.entries(fields)) {
13705
+ if (value2 instanceof Error) {
13706
+ normalized[key] = {
13707
+ name: value2.name,
13708
+ message: value2.message,
13709
+ stack: value2.stack
13710
+ };
13711
+ } else {
13712
+ normalized[key] = value2;
13713
+ }
13714
+ }
13715
+ return normalized;
13716
+ }
13717
+ function omitUndefined(record) {
13718
+ return Object.fromEntries(Object.entries(record).filter(([, value2]) => value2 !== void 0));
13719
+ }
13720
+
13545
13721
  // src/web-presenter.ts
13546
13722
  var WebPresenter = class {
13547
13723
  constructor(wsClient, _conversationId, cwd) {
@@ -13660,8 +13836,9 @@ var WebPresenter = class {
13660
13836
 
13661
13837
  // src/ws-client.ts
13662
13838
  var WSClient = class {
13663
- socket;
13664
- constructor(wsUrl, sessionId, taskId, token, callbacks, agentVersion) {
13839
+ constructor(wsUrl, sessionId, taskId, token, callbacks, agentVersion, lifecycle) {
13840
+ this.lifecycle = lifecycle;
13841
+ this.lifecycle?.info("sandbox_agent_ws_socket_create", { wsUrl });
13665
13842
  this.socket = lookup(wsUrl, {
13666
13843
  query: { type: "agent", sessionId, taskId, agentVersion: agentVersion ?? "" },
13667
13844
  auth: { token },
@@ -13676,6 +13853,7 @@ var WSClient = class {
13676
13853
  });
13677
13854
  this.setupListeners(callbacks);
13678
13855
  }
13856
+ socket;
13679
13857
  emitEvent(event) {
13680
13858
  this.socket.emit("agent_event", event);
13681
13859
  }
@@ -13702,20 +13880,26 @@ var WSClient = class {
13702
13880
  get connected() {
13703
13881
  return this.socket.connected;
13704
13882
  }
13883
+ setLifecycleContext(context) {
13884
+ this.lifecycle?.setContext(context);
13885
+ }
13705
13886
  close() {
13887
+ this.lifecycle?.info("sandbox_agent_ws_close_requested");
13706
13888
  this.socket.disconnect();
13707
13889
  }
13708
13890
  setupListeners(callbacks) {
13709
13891
  this.socket.on("connect", () => {
13710
- console.debug("[WSClient] Connected to WS server");
13892
+ this.lifecycle?.info("sandbox_agent_ws_socket_connected", { socketId: this.socket.id });
13711
13893
  callbacks.onConnect?.();
13712
13894
  });
13713
13895
  this.socket.on("disconnect", (reason) => {
13714
- console.debug(`[WSClient] Disconnected: ${reason}`);
13896
+ this.lifecycle?.info("sandbox_agent_ws_socket_disconnected", { reason });
13715
13897
  callbacks.onDisconnect?.(reason);
13716
13898
  });
13717
13899
  this.socket.on("connect_error", (error) => {
13718
- console.warn(`[WSClient] Connection error: ${error.message}`);
13900
+ this.lifecycle?.warn("sandbox_agent_ws_socket_connect_error", {
13901
+ error: error instanceof Error ? error : new Error(String(error))
13902
+ });
13719
13903
  });
13720
13904
  this.socket.on(
13721
13905
  "user_message",
@@ -13724,6 +13908,7 @@ var WSClient = class {
13724
13908
  callbacks.onUserMessage({
13725
13909
  text: data.text,
13726
13910
  images: data.images,
13911
+ files: data.files,
13727
13912
  providerSessionId: data.providerSessionId,
13728
13913
  backendKind: data.backendKind,
13729
13914
  agentId: data.agentId,
@@ -13739,6 +13924,7 @@ var WSClient = class {
13739
13924
  messageId: data.messageId,
13740
13925
  maxIterations: data.maxIterations,
13741
13926
  taskId: data.taskId,
13927
+ cloudEnvironmentId: data.cloudEnvironmentId,
13742
13928
  conversationId: data.conversationId,
13743
13929
  teamId: data.teamId,
13744
13930
  currentUser: data.currentUser
@@ -13754,17 +13940,39 @@ var WSClient = class {
13754
13940
  }
13755
13941
  });
13756
13942
  this.socket.on("error", (data) => {
13757
- console.error(`[WSClient] Server error: ${data.message} (${data.code})`);
13943
+ this.lifecycle?.error("sandbox_agent_ws_server_error", {
13944
+ message: data.message,
13945
+ code: data.code
13946
+ });
13758
13947
  });
13759
13948
  }
13760
13949
  };
13761
13950
 
13762
13951
  // src/sandbox.ts
13952
+ function correlationLogFields2(input) {
13953
+ return Object.fromEntries(
13954
+ Object.entries({
13955
+ taskId: input.taskId,
13956
+ conversationId: input.conversationId,
13957
+ runId: input.runId,
13958
+ messageId: input.messageId,
13959
+ cloudEnvironmentId: input.cloudEnvironmentId,
13960
+ provider: input.backendKind,
13961
+ backendKind: input.backendKind,
13962
+ agentVersion: input.agentVersion
13963
+ }).filter((entry) => {
13964
+ const value2 = entry[1];
13965
+ return typeof value2 === "string" && value2.trim().length > 0;
13966
+ }).map(([key, value2]) => [key, value2.trim()])
13967
+ );
13968
+ }
13763
13969
  async function runSandbox(config) {
13764
13970
  let currentTask = config.task;
13765
13971
  let currentImages = [];
13972
+ let currentFiles = [];
13766
13973
  const stopped = false;
13767
13974
  let pendingMessageResolve = null;
13975
+ const queuedMessages = [];
13768
13976
  let currentAgent = null;
13769
13977
  let currentTaskMeta;
13770
13978
  let currentPrMeta;
@@ -13772,15 +13980,26 @@ async function runSandbox(config) {
13772
13980
  let currentMaxIterations = config.maxIterations ?? 50;
13773
13981
  let currentTaskId = config.taskId;
13774
13982
  let currentConversationId = config.sessionId;
13983
+ let currentRunId;
13984
+ let currentMessageId;
13985
+ let currentCloudEnvironmentId;
13775
13986
  let currentTeamId = config.teamId;
13776
13987
  const workflowId = config.workflowId;
13777
13988
  const workflowExecutionId = config.workflowExecutionId;
13778
13989
  let currentUser = config.currentUser;
13779
13990
  let currentTerminalContextRefs;
13780
13991
  let currentTerminalSnapshots;
13781
- console.info("[sandbox] Connecting to WS server", {
13782
- wsUrl: config.wsUrl,
13783
- sessionId: config.sessionId
13992
+ const lifecycle = config.lifecycle ?? new AgentLifecycleLogger({
13993
+ taskId: config.taskId,
13994
+ conversationId: config.sessionId,
13995
+ runId: config.runId,
13996
+ sandboxId: config.sandboxId,
13997
+ provider: config.provider,
13998
+ backendKind: config.backendKind,
13999
+ agentVersion: AGENT_VERSION
14000
+ });
14001
+ lifecycle.info("sandbox_agent_ws_connect_attempt", {
14002
+ wsUrl: config.wsUrl
13784
14003
  });
13785
14004
  const wsClient = new WSClient(
13786
14005
  config.wsUrl,
@@ -13789,16 +14008,41 @@ async function runSandbox(config) {
13789
14008
  config.sessionToken,
13790
14009
  {
13791
14010
  onUserMessage: (payload) => {
14011
+ if (payload === null) {
14012
+ if (pendingMessageResolve) {
14013
+ const resolve2 = pendingMessageResolve;
14014
+ pendingMessageResolve = null;
14015
+ resolve2(null);
14016
+ }
14017
+ return;
14018
+ }
14019
+ lifecycle.setContext({
14020
+ runId: payload.runId,
14021
+ taskId: payload.taskId,
14022
+ conversationId: payload.conversationId,
14023
+ backendKind: payload.backendKind
14024
+ });
14025
+ wsClient.setLifecycleContext({
14026
+ runId: payload.runId,
14027
+ taskId: payload.taskId,
14028
+ conversationId: payload.conversationId,
14029
+ backendKind: payload.backendKind
14030
+ });
14031
+ lifecycle.info("sandbox_agent_user_message_received", {
14032
+ messageId: payload.messageId,
14033
+ hasImages: Boolean(payload.images?.length),
14034
+ fileCount: payload.files?.length ?? 0
14035
+ });
13792
14036
  if (pendingMessageResolve) {
13793
14037
  const resolve2 = pendingMessageResolve;
13794
14038
  pendingMessageResolve = null;
13795
14039
  resolve2(payload);
13796
14040
  } else {
13797
- console.warn("[sandbox] No handler for user message \u2014 dropped");
14041
+ queuedMessages.push(payload);
13798
14042
  }
13799
14043
  },
13800
14044
  onStop: () => {
13801
- console.info("[sandbox] Stop signal received");
14045
+ lifecycle.info("sandbox_agent_stop_received");
13802
14046
  if (currentAgent) {
13803
14047
  const killed = currentAgent.kill();
13804
14048
  if (!killed) currentAgent.abort();
@@ -13808,21 +14052,24 @@ async function runSandbox(config) {
13808
14052
  if (currentAgent) {
13809
14053
  const sent = currentAgent.sendToolResponse(toolId, response);
13810
14054
  if (!sent) {
13811
- console.warn("[sandbox] Failed to deliver tool_response to agent stdin", { toolId });
14055
+ lifecycle.warn("sandbox_agent_tool_response_delivery_failed", { toolId });
13812
14056
  }
13813
14057
  } else {
13814
- console.warn("[sandbox] No active agent for tool_response", { toolId });
14058
+ lifecycle.warn("sandbox_agent_tool_response_without_active_agent", { toolId });
13815
14059
  }
13816
14060
  },
13817
- onConnect: () => console.info("[sandbox] WS connected"),
13818
- onDisconnect: (reason) => console.info(`[sandbox] WS disconnected: ${reason}`)
14061
+ onConnect: () => lifecycle.info("sandbox_agent_ws_connected"),
14062
+ onDisconnect: (reason) => lifecycle.info("sandbox_agent_ws_disconnected", { reason })
13819
14063
  },
13820
- AGENT_VERSION
14064
+ AGENT_VERSION,
14065
+ lifecycle
13821
14066
  );
13822
14067
  try {
13823
14068
  await wsClient.waitForConnection();
13824
14069
  } catch (error) {
13825
- console.error("[sandbox] Failed to connect to WS server:", error.message);
14070
+ lifecycle.error("sandbox_agent_ws_connect_failed", {
14071
+ error: error instanceof Error ? error : new Error(String(error))
14072
+ });
13826
14073
  process.exit(1);
13827
14074
  }
13828
14075
  const presenter = new WebPresenter(wsClient, config.sessionId, config.projectPath);
@@ -13841,8 +14088,33 @@ async function runSandbox(config) {
13841
14088
  backendKind: activeBackendKind
13842
14089
  });
13843
14090
  currentAgent = agent;
14091
+ const correlation = correlationLogFields2({
14092
+ taskId: currentTaskId,
14093
+ conversationId: currentConversationId,
14094
+ runId: currentRunId,
14095
+ messageId: currentMessageId,
14096
+ cloudEnvironmentId: currentCloudEnvironmentId,
14097
+ backendKind: activeBackendKind,
14098
+ agentVersion: AGENT_VERSION
14099
+ });
14100
+ console.info("[sandbox] Agent run started", correlation);
13844
14101
  let result;
13845
14102
  try {
14103
+ lifecycle.setContext({
14104
+ taskId: currentTaskId,
14105
+ conversationId: currentConversationId,
14106
+ backendKind: activeBackendKind
14107
+ });
14108
+ wsClient.setLifecycleContext({
14109
+ taskId: currentTaskId,
14110
+ conversationId: currentConversationId,
14111
+ backendKind: activeBackendKind
14112
+ });
14113
+ lifecycle.info("sandbox_agent_run_start", {
14114
+ mode: activeMode,
14115
+ model: activeModel,
14116
+ maxIterations: currentMaxIterations
14117
+ });
13846
14118
  result = await agent.run({
13847
14119
  task: currentTask,
13848
14120
  maxIterations: currentMaxIterations,
@@ -13874,11 +14146,25 @@ async function runSandbox(config) {
13874
14146
  filename: img.filename,
13875
14147
  width: 0,
13876
14148
  height: 0
14149
+ })) : void 0,
14150
+ files: currentFiles.length > 0 ? currentFiles.map((file) => ({
14151
+ id: file.id,
14152
+ data: file.data,
14153
+ mimeType: file.mimeType,
14154
+ filename: file.filename,
14155
+ size: file.size,
14156
+ label: file.label
13877
14157
  })) : void 0
13878
14158
  });
13879
14159
  } catch (error) {
13880
14160
  const errorMessage = error instanceof Error ? error.message : String(error);
13881
- console.error("[sandbox] Agent run failed:", errorMessage);
14161
+ console.error("[sandbox] Agent run failed", {
14162
+ ...correlation,
14163
+ error: errorMessage
14164
+ });
14165
+ lifecycle.error("sandbox_agent_run_failed", {
14166
+ error: error instanceof Error ? error : new Error(errorMessage)
14167
+ });
13882
14168
  result = {
13883
14169
  success: false,
13884
14170
  summary: "Agent run failed",
@@ -13889,12 +14175,22 @@ async function runSandbox(config) {
13889
14175
  };
13890
14176
  }
13891
14177
  currentAgent = null;
14178
+ lifecycle.info("sandbox_agent_run_complete", {
14179
+ success: result.success,
14180
+ iterations: result.iterations,
14181
+ error: result.error
14182
+ });
13892
14183
  if (result?.providerSessionId) {
13893
14184
  lastProviderSessionId = result.providerSessionId;
13894
14185
  }
14186
+ console.info("[sandbox] Agent run finished", {
14187
+ ...correlation,
14188
+ success: String(result.success),
14189
+ iterations: String(result.iterations)
14190
+ });
13895
14191
  if (stopped) break;
13896
14192
  }
13897
- const nextPayload = await new Promise((resolve2) => {
14193
+ const nextPayload = queuedMessages.shift() ?? await new Promise((resolve2) => {
13898
14194
  pendingMessageResolve = resolve2;
13899
14195
  });
13900
14196
  if (nextPayload === null || stopped) {
@@ -13902,6 +14198,7 @@ async function runSandbox(config) {
13902
14198
  }
13903
14199
  currentTask = nextPayload.text;
13904
14200
  currentImages = nextPayload.images ?? [];
14201
+ currentFiles = nextPayload.files ?? [];
13905
14202
  if (nextPayload.providerSessionId) {
13906
14203
  lastProviderSessionId = nextPayload.providerSessionId;
13907
14204
  }
@@ -13941,6 +14238,15 @@ async function runSandbox(config) {
13941
14238
  if (nextPayload.taskId !== void 0) {
13942
14239
  currentTaskId = nextPayload.taskId;
13943
14240
  }
14241
+ if (nextPayload.runId !== void 0) {
14242
+ currentRunId = nextPayload.runId;
14243
+ }
14244
+ if (nextPayload.messageId !== void 0) {
14245
+ currentMessageId = nextPayload.messageId;
14246
+ }
14247
+ if (nextPayload.cloudEnvironmentId !== void 0) {
14248
+ currentCloudEnvironmentId = nextPayload.cloudEnvironmentId;
14249
+ }
13944
14250
  if (nextPayload.conversationId !== void 0) {
13945
14251
  currentConversationId = nextPayload.conversationId;
13946
14252
  }
@@ -13958,6 +14264,7 @@ async function runSandbox(config) {
13958
14264
  }
13959
14265
  }
13960
14266
  presenter.setSuppressSessionLifecycle(false);
14267
+ lifecycle.info("sandbox_agent_process_exit");
13961
14268
  wsClient.close();
13962
14269
  }
13963
14270
 
@@ -13980,20 +14287,28 @@ async function runSessionFromEnv() {
13980
14287
  const providerSessionId = process.env.AIDEN_PROVIDER_SESSION_ID || void 0;
13981
14288
  const workflowId = process.env.AIDEN_WORKFLOW_ID || void 0;
13982
14289
  const workflowExecutionId = process.env.AIDEN_WORKFLOW_EXECUTION_ID || void 0;
14290
+ const sandboxId = process.env.AIDEN_SANDBOX_ID || void 0;
14291
+ const provider = process.env.AIDEN_SANDBOX_PROVIDER || void 0;
14292
+ const runId = process.env.AIDEN_RUN_ID || void 0;
14293
+ const lifecycle = new AgentLifecycleLogger(lifecycleContextFromEnv(process.env));
13983
14294
  if (!wsUrl || !sessionId || !taskId || !sessionToken || task == null) {
14295
+ lifecycle.error("sandbox_agent_bootstrap_missing_env", {
14296
+ hasWsUrl: Boolean(wsUrl),
14297
+ hasConversationId: Boolean(sessionId),
14298
+ hasTaskId: Boolean(taskId),
14299
+ hasSessionToken: Boolean(sessionToken),
14300
+ hasTask: task != null
14301
+ });
13984
14302
  throw new Error(
13985
14303
  "run-session is an internal Aiden sandbox/session command and must be launched by Aiden with session env vars. Missing required env vars: AIDEN_WS_URL, AIDEN_SESSION_ID, AIDEN_TASK_ID, AIDEN_SESSION_TOKEN, AIDEN_TASK"
13986
14304
  );
13987
14305
  }
13988
- console.info("[aiden-agent] Starting", {
14306
+ lifecycle.info("sandbox_agent_process_start", {
13989
14307
  sessionId,
13990
- taskId,
13991
14308
  projectPath,
13992
- backendKind,
13993
14309
  agentId,
13994
14310
  mode,
13995
- model,
13996
- version: AGENT_VERSION
14311
+ model
13997
14312
  });
13998
14313
  await runSandbox({
13999
14314
  wsUrl,
@@ -14013,6 +14328,10 @@ async function runSessionFromEnv() {
14013
14328
  providerSessionId,
14014
14329
  workflowId,
14015
14330
  workflowExecutionId,
14331
+ sandboxId,
14332
+ provider,
14333
+ runId,
14334
+ lifecycle,
14016
14335
  maxIterations: 50
14017
14336
  });
14018
14337
  }
@@ -14072,7 +14391,9 @@ async function main() {
14072
14391
  ${HELP_TEXT}`);
14073
14392
  }
14074
14393
  main().catch((error) => {
14075
- console.error("[aiden-agent] Fatal error:", error instanceof Error ? error.message : error);
14394
+ new AgentLifecycleLogger(lifecycleContextFromEnv(process.env)).error("sandbox_agent_fatal", {
14395
+ error: error instanceof Error ? error : new Error(String(error))
14396
+ });
14076
14397
  process.exit(1);
14077
14398
  });
14078
14399
  /*! Bundled license information: