@aiden-ade/sandbox-agent 0.1.16 → 0.1.17

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/dist/index.cjs CHANGED
@@ -3404,7 +3404,7 @@ var require_websocket = __commonJS({
3404
3404
  var http2 = require("http");
3405
3405
  var net = require("net");
3406
3406
  var tls = require("tls");
3407
- var { randomBytes: randomBytes2, createHash: createHash2 } = require("crypto");
3407
+ var { randomBytes: randomBytes2, createHash: createHash4 } = require("crypto");
3408
3408
  var { Duplex, Readable } = require("stream");
3409
3409
  var { URL } = require("url");
3410
3410
  var PerMessageDeflate = require_permessage_deflate();
@@ -4061,7 +4061,7 @@ var require_websocket = __commonJS({
4061
4061
  abortHandshake(websocket, socket, "Invalid Upgrade header");
4062
4062
  return;
4063
4063
  }
4064
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
4064
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
4065
4065
  if (res.headers["sec-websocket-accept"] !== digest) {
4066
4066
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
4067
4067
  return;
@@ -4428,7 +4428,7 @@ var require_websocket_server = __commonJS({
4428
4428
  var EventEmitter = require("events");
4429
4429
  var http2 = require("http");
4430
4430
  var { Duplex } = require("stream");
4431
- var { createHash: createHash2 } = require("crypto");
4431
+ var { createHash: createHash4 } = require("crypto");
4432
4432
  var extension = require_extension();
4433
4433
  var PerMessageDeflate = require_permessage_deflate();
4434
4434
  var subprotocol = require_subprotocol();
@@ -4725,7 +4725,7 @@ var require_websocket_server = __commonJS({
4725
4725
  );
4726
4726
  }
4727
4727
  if (this._state > RUNNING) return abortHandshake(socket, 503);
4728
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
4728
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
4729
4729
  const headers = [
4730
4730
  "HTTP/1.1 101 Switching Protocols",
4731
4731
  "Upgrade: websocket",
@@ -4814,32 +4814,25 @@ var require_websocket_server = __commonJS({
4814
4814
  var import_child_process = require("child_process");
4815
4815
 
4816
4816
  // ../shared/dist/agent/agent-definitions.js
4817
- var COORDINATOR_PROMPT = `## You are the Coordinator
4817
+ var COORDINATOR_PROMPT = `## You are the Orchestrator
4818
4818
 
4819
- You are the **Coordinator** for this task. When asked "who are you?", "what agent are you?", "are you the coordinator?", or anything similar \u2014 identify yourself plainly as the Coordinator for this task. Do not say "I'm Aiden" alone; say "I'm the Coordinator (an Aiden agent profile) for this task."
4819
+ You are the **Orchestrator** for this task. When asked "who are you?", "what agent are you?", "are you the coordinator?", "are you the orchestrator?", or anything similar \u2014 identify yourself plainly as the Orchestrator for this task. Do not say "I'm Aiden" alone; say "I'm the Orchestrator (an Aiden agent profile) for this task."
4820
4820
 
4821
- Your primary job is orchestration. Your primary job is **NOT** implementation. **Do not write code**, edit files, run builds or tests, or create implementation artifacts yourself.
4821
+ Your primary job is orchestration: understand the task, choose the next unit of work, keep context current, and decide whether to act directly or delegate to a specialist.
4822
4822
 
4823
- ## What you do NOT do
4824
-
4825
- You MUST NOT call these tools:
4826
- - \`Edit\`, \`Write\`, \`MultiEdit\`, \`NotebookEdit\` \u2014 any file modification
4827
- - \`Bash\` for state-mutating commands (git commits, builds, installs, tests, file writes, deploys)
4828
-
4829
- If the user asks for a code change, a build, a test run, a deploy, or anything that mutates state \u2014 STOP. **Delegate it** via \`start_task_session\` to the right specialist agent.
4830
-
4831
- Read-only inspection is fine: \`Read\`, \`Glob\`, \`Grep\`, and \`Bash\` for read commands like \`ls\`, \`git status\`, \`git log\`, \`cat\`, \`pwd\`.
4823
+ You may inspect, edit, run commands, create artifacts, and use MCP tools when that is the smallest coherent way to move the task forward. Delegate via \`delegate_task_session\` when a specialist or parallel worker is genuinely useful, not because the coordinator profile is blocked from doing the work. Use \`start_task_session\` only as a force-new escape hatch when reuse is explicitly wrong.
4832
4824
 
4833
4825
  ## Your primary tools
4834
4826
 
4835
4827
  Use these tools, in roughly this order of frequency:
4836
- 1. \`start_task_session\` \u2014 delegate work to a specialist
4828
+ 1. \`delegate_task_session\` \u2014 route work to a specialist, reusing active matching workers by default
4837
4829
  2. \`get_task_memory\` / \`update_task_memory\` \u2014 keep the task-level working memory current
4838
4830
  3. \`list_subtasks\` / \`create_subtask\` / \`update_subtask\` \u2014 keep task breakdown current
4839
4831
  4. \`get_session_context\` \u2014 check what a worker accomplished
4840
4832
  5. \`update_task\` \u2014 keep status, priority, labels current
4841
- 6. \`list_sessions\` / \`search\` / \`Read\` / \`Glob\` / \`Grep\` \u2014 situational awareness (read-only)
4842
- 7. \`add_task_comment\` / \`create_plan\` \u2014 document decisions and plans
4833
+ 6. \`send_session_message\` / \`start_task_session\` \u2014 continue a specific session or force a new session only when needed
4834
+ 7. \`list_sessions\` / \`search\` / \`Read\` / \`Glob\` / \`Grep\` \u2014 situational awareness
4835
+ 8. \`add_task_comment\` / \`create_plan\` \u2014 document decisions and plans
4843
4836
 
4844
4837
  ## How to scale work
4845
4838
 
@@ -4857,9 +4850,11 @@ A two-line change does not need its own session. A well-scoped subtask can often
4857
4850
  - **PM Agent** \u2014 product questions, requirements, scope definition, PRD creation
4858
4851
  - **General Agent** \u2014 only when no specialist fits
4859
4852
 
4860
- ## How to write a kickoff message
4853
+ ## How to delegate
4861
4854
 
4862
- Every \`start_task_session\` message must include all four of these:
4855
+ Before creating any worker, check task memory and active sessions for a matching agent/workstream. Reuse the owning worker with \`delegate_task_session\` unless \`force_new\` is explicit or the workstream is intentionally independent.
4856
+
4857
+ Every \`delegate_task_session\` message must include all four of these:
4863
4858
  1. **Objective** \u2014 what to do, in one clear sentence
4864
4859
  2. **Relevant context** \u2014 which files, APIs, or prior session results matter
4865
4860
  3. **Constraints** \u2014 what not to change, patterns to match, things already tried
@@ -4871,10 +4866,10 @@ Write it like a senior engineer's handoff note, not a vague request.
4871
4866
 
4872
4867
  1. Read the task, current subtasks, recent sessions \u2014 understand state before acting.
4873
4868
  2. Decide the next concrete unit of work. Break it down when scope is wide; keep subtasks current.
4874
- 3. **Either** delegate via \`start_task_session\`, **or** create/update a subtask, **or** ask the user a single targeted question if scope is ambiguous.
4875
- 4. After delegation, stay out of the implementation path. Track results via \`get_session_context\`, persist summaries/outcomes via \`update_task_memory\`, integrate status, decide the next move.
4869
+ 3. **Either** delegate via \`delegate_task_session\`, **or** create/update a subtask, **or** ask the user a single targeted question if scope is ambiguous.
4870
+ 4. After delegation, track results via \`get_session_context\`, persist summaries/outcomes via \`update_task_memory\`, integrate status, decide the next move.
4876
4871
 
4877
- You are read-only by design. The build happens in spawned sessions. Hold that line.`;
4872
+ You are coordination-first, not read-only. Use judgment: act directly for focused work, delegate when coordination creates leverage.`;
4878
4873
  var PM_PROMPT = `## You are the PM Agent
4879
4874
 
4880
4875
  You are the **PM Agent** (Product Manager) for this task. When identifying yourself, say "I'm the PM Agent (an Aiden agent profile)."
@@ -4913,7 +4908,7 @@ Use these tools, in roughly this order of frequency:
4913
4908
 
4914
4909
  - **Implementor** \u2014 any code change: features, fixes, data, API, UI, tests
4915
4910
  - **Designer** \u2014 interaction, layout, accessibility, visual design
4916
- - **Coordinator** \u2014 multi-agent orchestration where the work is complex enough to need coordination
4911
+ - **Orchestrator** \u2014 multi-agent orchestration where the work is complex enough to need coordination
4917
4912
  - **General Agent** \u2014 research, investigation, or work that doesn't fit a specialist
4918
4913
 
4919
4914
  ## How to write a kickoff message
@@ -4947,6 +4942,25 @@ Non-trivial implementations include tests. Break and plan before building when s
4947
4942
  - Files changed, if any
4948
4943
  - How you validated the result
4949
4944
  - Any residual risk or open question`;
4945
+ var REVIEW_PROMPT = `## You are the Review Agent
4946
+
4947
+ You are the **Review Agent** (an Aiden agent profile) for pull request review sessions. When identifying yourself, say "I'm the Review Agent."
4948
+
4949
+ Your job is to inspect the pull request context, reason about correctness and risk, and help the user review the change. Prefer concrete findings tied to files, lines, tests, and behavior. Do not send a review verdict until you have enough evidence.
4950
+
4951
+ ## How to review
4952
+
4953
+ 1. Understand the PR goal, linked task context, changed files, and current checks.
4954
+ 2. Prioritize correctness, regressions, data loss, security, migration risk, and missing tests.
4955
+ 3. Reuse available contextual comments, file diffs, task metadata, and session history before asking for more context.
4956
+ 4. Report findings clearly, ordered by severity. If there are no blocking findings, say that and call out residual test gaps.
4957
+
4958
+ ## Rules
4959
+
4960
+ - Do not invent changed files, test results, or PR metadata.
4961
+ - Keep feedback actionable and scoped to this PR.
4962
+ - Prefer short review comments over broad commentary.
4963
+ - Ask one targeted question only when evidence is missing and blocks a useful review.`;
4950
4964
  var IMPLEMENTOR_PROMPT = `## You are the Implementor Agent
4951
4965
 
4952
4966
  You are a senior implementation agent responsible for end-to-end code delivery. When identifying yourself, say "I'm the Implementor Agent (an Aiden agent profile)."
@@ -4983,6 +4997,10 @@ var DESIGNER_PROMPT = `## You are the Designer Agent
4983
4997
 
4984
4998
  You are a product UI designer and frontend interaction specialist. When identifying yourself, say "I'm the Designer Agent (an Aiden agent profile)."
4985
4999
 
5000
+ ## Taste Skill (premium frontends)
5001
+
5002
+ For landing pages, marketing sites, portfolios, or visual redesigns outside the core product shell, read and follow the \`design-taste-frontend\` skill in \`.agents/skills/\` before writing UI. Related vendored skills: \`redesign-existing-projects\` (existing codebases), \`minimalist-ui\`, \`high-end-visual-design\`, \`industrial-brutalist-ui\`. Sync from upstream with \`scripts/sync-taste-skills.sh\`.
5003
+
4986
5004
  ## How to approach the work
4987
5005
 
4988
5006
  1. Think from the user's task flow before touching layout. What is the user trying to do?
@@ -5020,14 +5038,14 @@ You are a product UI designer and frontend interaction specialist. When identify
5020
5038
  var BUILTIN_AGENT_DEFINITIONS = [
5021
5039
  {
5022
5040
  id: "coordinator",
5023
- name: "Coordinator",
5024
- description: "Plans work, breaks down tasks, coordinates agents",
5041
+ name: "Orchestrator",
5042
+ description: "Plans work, breaks down tasks, orchestrates agents",
5025
5043
  iconKey: "command",
5026
5044
  defaultMode: "agent",
5027
5045
  capabilities: {
5028
- canEditFiles: false,
5029
- canRunCommands: false,
5030
- canCreateArtifacts: false,
5046
+ canEditFiles: true,
5047
+ canRunCommands: true,
5048
+ canCreateArtifacts: true,
5031
5049
  canStartSessions: true,
5032
5050
  canManageSubtasks: true
5033
5051
  },
@@ -5048,6 +5066,21 @@ var BUILTIN_AGENT_DEFINITIONS = [
5048
5066
  },
5049
5067
  systemPrompt: GENERAL_PROMPT
5050
5068
  },
5069
+ {
5070
+ id: "pr-reviewer",
5071
+ name: "Review Agent",
5072
+ description: "Reviews pull requests and surfaces risks",
5073
+ iconKey: "search-code",
5074
+ defaultMode: "review",
5075
+ capabilities: {
5076
+ canEditFiles: false,
5077
+ canRunCommands: true,
5078
+ canCreateArtifacts: true,
5079
+ canStartSessions: false,
5080
+ canManageSubtasks: false
5081
+ },
5082
+ systemPrompt: REVIEW_PROMPT
5083
+ },
5051
5084
  {
5052
5085
  id: "pm",
5053
5086
  name: "PM Agent",
@@ -5100,7 +5133,6 @@ var LEGACY_AGENT_ID_ALIASES = {
5100
5133
  developer: "implementor",
5101
5134
  implementer: "implementor",
5102
5135
  "ui-designer": "designer",
5103
- "pr-reviewer": "general",
5104
5136
  verifier: "general"
5105
5137
  };
5106
5138
  function normalizeBuiltinAgentId(agentId) {
@@ -5202,10 +5234,11 @@ function getAidenAgentPrompt(agentId) {
5202
5234
  var SESSION_RESUME_FAILED_MESSAGE = "Session resume failed. The previous session may have expired or is no longer available. Please start a new session.";
5203
5235
 
5204
5236
  // ../agent-core/dist/index.js
5237
+ var import_crypto = require("crypto");
5205
5238
  var import_fs = require("fs");
5206
5239
  var import_os = require("os");
5207
5240
  var import_path = require("path");
5208
- var import_crypto = require("crypto");
5241
+ var import_crypto2 = require("crypto");
5209
5242
  var import_fs2 = require("fs");
5210
5243
  var import_fs3 = require("fs");
5211
5244
  var import_os2 = require("os");
@@ -5376,6 +5409,7 @@ function normalizeCodexMcpToolResult(output) {
5376
5409
  }
5377
5410
  return raw;
5378
5411
  }
5412
+ var MAX_INLINE_GENERATED_IMAGE_BYTES = 20 * 1024 * 1024;
5379
5413
  function findCodexSessionLog(runtimeSessionId, codexHome) {
5380
5414
  if (!runtimeSessionId || !(0, import_fs.existsSync)(codexHome)) return null;
5381
5415
  const root = (0, import_path.join)(codexHome, "sessions");
@@ -5406,14 +5440,106 @@ function findCodexSessionLog(runtimeSessionId, codexHome) {
5406
5440
  matches.sort((a, b) => b.mtimeMs - a.mtimeMs);
5407
5441
  return matches[0]?.path ?? null;
5408
5442
  }
5443
+ function inferImageMimeType(buffer) {
5444
+ if (buffer.length >= 8 && buffer.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
5445
+ return "image/png";
5446
+ }
5447
+ if (buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) {
5448
+ return "image/jpeg";
5449
+ }
5450
+ if (buffer.length >= 6 && (buffer.toString("ascii", 0, 6) === "GIF87a" || buffer.toString("ascii", 0, 6) === "GIF89a")) {
5451
+ return "image/gif";
5452
+ }
5453
+ if (buffer.length >= 12 && buffer.toString("ascii", 0, 4) === "RIFF" && buffer.toString("ascii", 8, 12) === "WEBP") {
5454
+ return "image/webp";
5455
+ }
5456
+ return null;
5457
+ }
5458
+ function extensionForMimeType(mimeType) {
5459
+ switch (mimeType) {
5460
+ case "image/jpeg":
5461
+ return "jpg";
5462
+ case "image/gif":
5463
+ return "gif";
5464
+ case "image/webp":
5465
+ return "webp";
5466
+ case "image/png":
5467
+ default:
5468
+ return "png";
5469
+ }
5470
+ }
5471
+ function readImageDimensions(buffer, mimeType) {
5472
+ if (mimeType === "image/png" && buffer.length >= 24) {
5473
+ return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) };
5474
+ }
5475
+ if (mimeType === "image/gif" && buffer.length >= 10) {
5476
+ return { width: buffer.readUInt16LE(6), height: buffer.readUInt16LE(8) };
5477
+ }
5478
+ if (mimeType === "image/jpeg" && buffer.length > 4) {
5479
+ let offset = 2;
5480
+ while (offset + 9 < buffer.length) {
5481
+ if (buffer[offset] !== 255) break;
5482
+ const marker = buffer[offset + 1];
5483
+ const length = buffer.readUInt16BE(offset + 2);
5484
+ if (length < 2) break;
5485
+ if (marker >= 192 && marker <= 207 && ![196, 200, 204].includes(marker)) {
5486
+ return {
5487
+ width: buffer.readUInt16BE(offset + 7),
5488
+ height: buffer.readUInt16BE(offset + 5)
5489
+ };
5490
+ }
5491
+ offset += 2 + length;
5492
+ }
5493
+ }
5494
+ return { width: null, height: null };
5495
+ }
5496
+ function buildGeneratedImageFromCodexPayload(payload) {
5497
+ const data = typeof payload.result === "string" ? payload.result : "";
5498
+ if (!data) return null;
5499
+ const buffer = Buffer.from(data, "base64");
5500
+ if (buffer.length <= 0 || buffer.length > MAX_INLINE_GENERATED_IMAGE_BYTES) return null;
5501
+ const mimeType = inferImageMimeType(buffer);
5502
+ if (!mimeType) return null;
5503
+ const callId = typeof payload.call_id === "string" && payload.call_id ? payload.call_id : void 0;
5504
+ const imageId = (0, import_crypto.randomUUID)();
5505
+ const { width, height } = readImageDimensions(buffer, mimeType);
5506
+ return {
5507
+ type: "generated_image",
5508
+ id: imageId,
5509
+ filename: `${callId ?? imageId}.${extensionForMimeType(mimeType)}`,
5510
+ mimeType,
5511
+ size: buffer.length,
5512
+ width,
5513
+ height,
5514
+ data: buffer.toString("base64"),
5515
+ sourceHash: (0, import_crypto.createHash)("sha256").update(buffer).digest("hex"),
5516
+ ...callId ? { toolId: callId } : {},
5517
+ ts: Date.now()
5518
+ };
5519
+ }
5520
+ function latestUserMessageLineIndex(lines) {
5521
+ let latestIndex = -1;
5522
+ for (let index = 0; index < lines.length; index += 1) {
5523
+ const line = lines[index];
5524
+ if (!line) continue;
5525
+ const entry = parseJsonObject(line);
5526
+ const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
5527
+ if (payload?.type === "message" && payload.role === "user") {
5528
+ latestIndex = index;
5529
+ }
5530
+ }
5531
+ return latestIndex;
5532
+ }
5409
5533
  async function replayCodexMcpToolEventsFromSessionLog(context, state) {
5410
5534
  const runtimeSessionId = state.runtimeSessionId;
5411
5535
  if (!runtimeSessionId) return;
5412
5536
  const codexHome = context.env.CODEX_HOME || process.env.CODEX_HOME || (0, import_path.join)((0, import_os.homedir)(), ".codex");
5413
5537
  const logPath = findCodexSessionLog(runtimeSessionId, codexHome);
5414
5538
  if (!logPath) return;
5539
+ const allLines = (0, import_fs.readFileSync)(logPath, "utf8").split(/\r?\n/).filter(Boolean);
5540
+ const latestUserLineIndex = latestUserMessageLineIndex(allLines);
5541
+ const lines = latestUserLineIndex >= 0 ? allLines.slice(latestUserLineIndex + 1) : allLines;
5415
5542
  const emittedToolIds = /* @__PURE__ */ new Set();
5416
- const lines = (0, import_fs.readFileSync)(logPath, "utf8").split(/\r?\n/).filter(Boolean);
5417
5543
  for (const line of lines) {
5418
5544
  const entry = parseJsonObject(line);
5419
5545
  const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
@@ -5433,20 +5559,27 @@ async function replayCodexMcpToolEventsFromSessionLog(context, state) {
5433
5559
  if (!callId) continue;
5434
5560
  context.presenter.onToolUse("tool_search", payload.arguments ?? {}, callId);
5435
5561
  emittedToolIds.add(callId);
5562
+ continue;
5563
+ }
5564
+ if (payload.type === "image_generation_end") {
5565
+ const image = buildGeneratedImageFromCodexPayload(payload);
5566
+ if (image) await context.presenter.onGeneratedImage?.(image);
5436
5567
  }
5437
5568
  }
5438
- if (emittedToolIds.size === 0) return;
5439
- for (const line of lines) {
5440
- const entry = parseJsonObject(line);
5441
- const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
5442
- if (!payload || payload.type !== "function_call_output" && payload.type !== "tool_search_output") continue;
5443
- const callId = typeof payload.call_id === "string" ? payload.call_id : "";
5444
- if (!emittedToolIds.has(callId)) continue;
5445
- try {
5446
- const result = payload.type === "tool_search_output" ? JSON.stringify(payload.tools ?? [], null, 2) : normalizeCodexMcpToolResult(payload.output);
5447
- context.presenter.onToolResult?.(callId, result);
5448
- } catch {
5449
- context.presenter.onToolResult?.(callId, String(payload.output ?? ""));
5569
+ if (emittedToolIds.size > 0) {
5570
+ for (const line of lines) {
5571
+ const entry = parseJsonObject(line);
5572
+ const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
5573
+ if (!payload || payload.type !== "function_call_output" && payload.type !== "tool_search_output")
5574
+ continue;
5575
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
5576
+ if (!emittedToolIds.has(callId)) continue;
5577
+ try {
5578
+ const result = payload.type === "tool_search_output" ? JSON.stringify(payload.tools ?? [], null, 2) : normalizeCodexMcpToolResult(payload.output);
5579
+ context.presenter.onToolResult?.(callId, result);
5580
+ } catch {
5581
+ context.presenter.onToolResult?.(callId, String(payload.output ?? ""));
5582
+ }
5450
5583
  }
5451
5584
  }
5452
5585
  }
@@ -5456,7 +5589,7 @@ function kimiSessionId(cwd) {
5456
5589
  resolved = (0, import_fs2.realpathSync)(cwd);
5457
5590
  } catch {
5458
5591
  }
5459
- return (0, import_crypto.createHash)("md5").update(resolved).digest("hex");
5592
+ return (0, import_crypto2.createHash)("md5").update(resolved).digest("hex");
5460
5593
  }
5461
5594
  function parseKimiStructuredLine(line, context, state) {
5462
5595
  const presenter = context.presenter;
@@ -6138,7 +6271,7 @@ function resolveKimiCliModelArg(model) {
6138
6271
  if (trimmed.startsWith("claude-")) return void 0;
6139
6272
  return trimmed;
6140
6273
  }
6141
- function createKimiCliBackend(command = "kimi", defaultArgs = []) {
6274
+ function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
6142
6275
  return {
6143
6276
  kind: "kimi_cli",
6144
6277
  supportTier: "structured",
@@ -6964,7 +7097,12 @@ function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
6964
7097
  const resumeId = ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim();
6965
7098
  const modelArgs = ctx.config.selectedModel?.trim() ? ["--model", ctx.config.selectedModel.trim()] : [];
6966
7099
  const effortArgs = buildCodexEffortArgs(ctx.config.selectedEffortLevel);
6967
- const permissionArgs = ["--dangerously-bypass-approvals-and-sandbox"];
7100
+ const permissionArgs = [
7101
+ "--ask-for-approval",
7102
+ "never",
7103
+ "--sandbox",
7104
+ "danger-full-access"
7105
+ ];
6968
7106
  const imageArgs = imagePaths.flatMap((p) => ["--image", p]);
6969
7107
  const baseArgs = resumeId ? [...permissionArgs, "exec", "resume", "--json", "--skip-git-repo-check", ...modelArgs, ...effortArgs, ...imageArgs, resumeId, "-"] : [...permissionArgs, "exec", "--json", "--skip-git-repo-check", ...modelArgs, ...effortArgs, ...imageArgs, "-"];
6970
7108
  return [...baseArgs, ...defaultArgs];
@@ -7287,7 +7425,7 @@ Prefer relative paths and keep your work scoped to this project.`
7287
7425
  const promptText = this.buildPromptText(runtimeConfig);
7288
7426
  const runtimeCommand = runtimeConfig.runtimeCommand || this.runtime.runtimeCommand;
7289
7427
  const runtimeArgs = runtimeConfig.runtimeArgs || this.runtime.runtimeArgs || [];
7290
- const backend = backendKind === "claude_cli" ? createClaudeCliBackend(runtimeCommand || "claude", runtimeArgs) : backendKind === "codex_app_server" ? createCodexRuntimeBackend(runtimeCommand || "codex", runtimeArgs) : backendKind === "copilot_cli" ? createCopilotCliBackend(runtimeCommand || "copilot", runtimeArgs) : backendKind === "cursor_agent_cli" ? createCursorAgentCliBackend(runtimeCommand || "cursor-agent", runtimeArgs) : backendKind === "gemini_cli" ? createGeminiCliBackend(runtimeCommand || "gemini", runtimeArgs) : backendKind === "droid_cli" ? createDroidCliBackend(runtimeCommand || "droid", runtimeArgs) : backendKind === "opencode_cli" ? createOpencodeCliBackend(runtimeCommand || "opencode", runtimeArgs) : backendKind === "kimi_cli" ? createKimiCliBackend(runtimeCommand || "kimi", runtimeArgs) : backendKind === "supatest_cli" ? createSupatestCliBackend(runtimeCommand || "supatest", runtimeArgs) : createGenericCliPassthroughBackend(runtimeCommand || "generic-cli", runtimeArgs);
7428
+ const backend = backendKind === "claude_cli" ? createClaudeCliBackend(runtimeCommand || "claude", runtimeArgs) : backendKind === "codex_app_server" ? createCodexRuntimeBackend(runtimeCommand || "codex", runtimeArgs) : backendKind === "copilot_cli" ? createCopilotCliBackend(runtimeCommand || "copilot", runtimeArgs) : backendKind === "cursor_agent_cli" ? createCursorAgentCliBackend(runtimeCommand || "cursor-agent", runtimeArgs) : backendKind === "gemini_cli" ? createGeminiCliBackend(runtimeCommand || "gemini", runtimeArgs) : backendKind === "droid_cli" ? createDroidCliBackend(runtimeCommand || "droid", runtimeArgs) : backendKind === "opencode_cli" ? createOpencodeCliBackend(runtimeCommand || "opencode", runtimeArgs) : backendKind === "kimi_cli" ? createKimiCliBackend(runtimeCommand || "kimi-cli", runtimeArgs) : backendKind === "supatest_cli" ? createSupatestCliBackend(runtimeCommand || "supatest", runtimeArgs) : createGenericCliPassthroughBackend(runtimeCommand || "generic-cli", runtimeArgs);
7291
7429
  let lastResult = null;
7292
7430
  for (let attempt = 0; attempt <= _BaseMachineAgent.MAX_RETRIES; attempt++) {
7293
7431
  if (this.abortController?.signal.aborted) break;
@@ -7439,7 +7577,7 @@ var PROVIDER_CLI_COMMANDS = {
7439
7577
  copilot_cli: { provider: "copilot_cli", command: "copilot", envVar: "AIDEN_COPILOT_PATH" },
7440
7578
  cursor_agent_cli: { provider: "cursor_agent_cli", command: "cursor-agent", envVar: "AIDEN_CURSOR_AGENT_PATH" },
7441
7579
  gemini_cli: { provider: "gemini_cli", command: "gemini", envVar: "AIDEN_GEMINI_PATH" },
7442
- kimi_cli: { provider: "kimi_cli", command: "kimi", envVar: "AIDEN_KIMI_PATH" },
7580
+ kimi_cli: { provider: "kimi_cli", command: "kimi-cli", envVar: "AIDEN_KIMI_PATH" },
7443
7581
  opencode_cli: { provider: "opencode_cli", command: "opencode", envVar: "AIDEN_OPENCODE_PATH" },
7444
7582
  droid_cli: { provider: "droid_cli", command: "droid", envVar: "AIDEN_DROID_PATH" },
7445
7583
  supatest_cli: { provider: "supatest_cli", command: "supatest", envVar: "AIDEN_SUPATEST_PATH" }
@@ -7457,13 +7595,13 @@ var BACKEND_CLI_COMMANDS = {
7457
7595
  cursor_agent_cli: "cursor-agent",
7458
7596
  gemini_cli: "gemini",
7459
7597
  gemini: "gemini",
7460
- kimi_cli: "kimi",
7598
+ kimi_cli: "kimi-cli",
7461
7599
  opencode_cli: "opencode",
7462
7600
  droid_cli: "droid",
7463
7601
  supatest_cli: "supatest"
7464
7602
  };
7465
7603
  var CLI_COMMAND_ALIASES = {
7466
- kimi: ["kimi-cli"]
7604
+ "kimi-cli": ["kimi"]
7467
7605
  };
7468
7606
  var resolvedCliCache = /* @__PURE__ */ new Map();
7469
7607
  var cachedLoginShellEnv = null;
@@ -7864,6 +8002,46 @@ ${meta.description}`);
7864
8002
  }
7865
8003
  parts2.push(lines.join("\n"));
7866
8004
  }
8005
+ if (config.prMeta) {
8006
+ const pr = config.prMeta;
8007
+ const lines = ["# Pull Request Context"];
8008
+ lines.push(`- **Repo**: ${pr.owner}/${pr.repo}`);
8009
+ lines.push(`- **PR**: #${pr.prNumber} \u2014 ${pr.title}`);
8010
+ lines.push(`- **State**: ${pr.state}`);
8011
+ if (pr.author) lines.push(`- **Author**: ${pr.author}`);
8012
+ const baseHead = `${pr.baseBranch || "?"} \u2190 ${pr.headBranch || "?"}`;
8013
+ lines.push(`- **Base \u2190 Head**: ${baseHead}`);
8014
+ if (pr.mergeable === false) {
8015
+ lines.push(`- **Mergeable**: no`);
8016
+ } else if (pr.mergeable === true) {
8017
+ lines.push(`- **Mergeable**: yes`);
8018
+ }
8019
+ if (pr.labels && pr.labels.length > 0) {
8020
+ lines.push(`- **Labels**: ${pr.labels.join(", ")}`);
8021
+ }
8022
+ const sizeBits = [];
8023
+ if (typeof pr.changedFilesCount === "number") sizeBits.push(`${pr.changedFilesCount} files`);
8024
+ if (typeof pr.additions === "number") sizeBits.push(`+${pr.additions}`);
8025
+ if (typeof pr.deletions === "number") sizeBits.push(`-${pr.deletions}`);
8026
+ if (sizeBits.length > 0) lines.push(`- **Size**: ${sizeBits.join(" / ")}`);
8027
+ if (pr.linkedTaskReadableId) {
8028
+ lines.push(`- **Linked task**: ${pr.linkedTaskReadableId}`);
8029
+ }
8030
+ if (pr.htmlUrl) lines.push(`- **URL**: ${pr.htmlUrl}`);
8031
+ if (pr.body) {
8032
+ lines.push("");
8033
+ lines.push("## PR Description");
8034
+ lines.push(pr.body);
8035
+ }
8036
+ if (pr.changedFiles && pr.changedFiles.length > 0) {
8037
+ lines.push("");
8038
+ lines.push("## Changed Files (first 50)");
8039
+ for (const file of pr.changedFiles) {
8040
+ lines.push(`- ${file.status}: \`${file.path}\` (+${file.additions} / -${file.deletions})`);
8041
+ }
8042
+ }
8043
+ parts2.push(lines.join("\n"));
8044
+ }
7867
8045
  const taskId = config.taskId ?? process.env.AIDEN_TASK_ID;
7868
8046
  const conversationId = config.conversationId ?? process.env.AIDEN_SESSION_ID;
7869
8047
  const teamId = config.teamId;
@@ -7898,15 +8076,128 @@ ${meta.description}`);
7898
8076
  }
7899
8077
  };
7900
8078
 
8079
+ // src/generated-images.ts
8080
+ var import_node_crypto = require("crypto");
8081
+ var import_node_fs2 = require("fs");
8082
+ var import_node_path2 = require("path");
8083
+ var IMAGE_MIME_BY_EXT = {
8084
+ ".gif": "image/gif",
8085
+ ".jpeg": "image/jpeg",
8086
+ ".jpg": "image/jpeg",
8087
+ ".png": "image/png",
8088
+ ".webp": "image/webp"
8089
+ };
8090
+ var MAX_GENERATED_IMAGE_BYTES = 20 * 1024 * 1024;
8091
+ function collectStringValues(value2, out) {
8092
+ if (typeof value2 === "string") {
8093
+ out.push(value2);
8094
+ return;
8095
+ }
8096
+ if (Array.isArray(value2)) {
8097
+ for (const item of value2) collectStringValues(item, out);
8098
+ return;
8099
+ }
8100
+ if (!value2 || typeof value2 !== "object") return;
8101
+ for (const entry of Object.values(value2)) {
8102
+ collectStringValues(entry, out);
8103
+ }
8104
+ }
8105
+ function candidateStrings(content) {
8106
+ const values = [content];
8107
+ try {
8108
+ collectStringValues(JSON.parse(content), values);
8109
+ } catch {
8110
+ }
8111
+ return values;
8112
+ }
8113
+ function extractPathCandidates(content) {
8114
+ const paths = /* @__PURE__ */ new Set();
8115
+ const imagePathPattern = /(?:file:\/\/)?(?:~|\.{1,2}|\/)?[^\s"'`)\]}<>]+?\.(?:png|jpe?g|gif|webp)\b/gi;
8116
+ for (const value2 of candidateStrings(content)) {
8117
+ for (const match of value2.matchAll(imagePathPattern)) {
8118
+ paths.add(match[0]);
8119
+ }
8120
+ }
8121
+ return [...paths];
8122
+ }
8123
+ function normalizePath(candidate, cwd) {
8124
+ let path = candidate.trim().replace(/^file:\/\//, "");
8125
+ try {
8126
+ path = decodeURI(path);
8127
+ } catch {
8128
+ }
8129
+ if (path.startsWith("~/")) return null;
8130
+ if ((0, import_node_path2.isAbsolute)(path)) return path;
8131
+ return cwd ? (0, import_node_path2.join)(cwd, path) : null;
8132
+ }
8133
+ function readImageDimensions2(buffer, mimeType) {
8134
+ if (mimeType === "image/png" && buffer.length >= 24 && buffer.toString("ascii", 1, 4) === "PNG") {
8135
+ return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) };
8136
+ }
8137
+ if (mimeType === "image/gif" && buffer.length >= 10 && buffer.toString("ascii", 0, 3) === "GIF") {
8138
+ return { width: buffer.readUInt16LE(6), height: buffer.readUInt16LE(8) };
8139
+ }
8140
+ if (mimeType === "image/jpeg" && buffer.length > 4) {
8141
+ let offset = 2;
8142
+ while (offset + 9 < buffer.length) {
8143
+ if (buffer[offset] !== 255) break;
8144
+ const marker = buffer[offset + 1];
8145
+ const length = buffer.readUInt16BE(offset + 2);
8146
+ if (length < 2) break;
8147
+ if (marker >= 192 && marker <= 207 && ![196, 200, 204].includes(marker)) {
8148
+ return {
8149
+ width: buffer.readUInt16BE(offset + 7),
8150
+ height: buffer.readUInt16BE(offset + 5)
8151
+ };
8152
+ }
8153
+ offset += 2 + length;
8154
+ }
8155
+ }
8156
+ return { width: null, height: null };
8157
+ }
8158
+ function extractGeneratedImagesFromToolResult(toolId, content, cwd) {
8159
+ const images = [];
8160
+ const seen = /* @__PURE__ */ new Set();
8161
+ for (const candidate of extractPathCandidates(content)) {
8162
+ const path = normalizePath(candidate, cwd);
8163
+ if (!path || seen.has(path) || !(0, import_node_fs2.existsSync)(path)) continue;
8164
+ seen.add(path);
8165
+ const ext = (0, import_node_path2.extname)(path).toLowerCase();
8166
+ const mimeType = IMAGE_MIME_BY_EXT[ext];
8167
+ if (!mimeType) continue;
8168
+ const stat = (0, import_node_fs2.statSync)(path);
8169
+ if (!stat.isFile() || stat.size <= 0 || stat.size > MAX_GENERATED_IMAGE_BYTES) continue;
8170
+ const buffer = (0, import_node_fs2.readFileSync)(path);
8171
+ const { width, height } = readImageDimensions2(buffer, mimeType);
8172
+ images.push({
8173
+ type: "generated_image",
8174
+ id: (0, import_node_crypto.randomUUID)(),
8175
+ filename: (0, import_node_path2.basename)(path),
8176
+ mimeType,
8177
+ size: buffer.length,
8178
+ width,
8179
+ height,
8180
+ data: buffer.toString("base64"),
8181
+ sourcePath: path,
8182
+ sourceHash: (0, import_node_crypto.createHash)("sha256").update(buffer).digest("hex"),
8183
+ toolId,
8184
+ ts: Date.now()
8185
+ });
8186
+ }
8187
+ return images;
8188
+ }
8189
+
7901
8190
  // src/web-presenter.ts
7902
8191
  var WebPresenter = class {
7903
- wsClient;
7904
- conversationId;
7905
- suppressSessionLifecycle = false;
7906
- constructor(wsClient, conversationId) {
8192
+ constructor(wsClient, conversationId, cwd) {
8193
+ this.cwd = cwd;
7907
8194
  this.wsClient = wsClient;
7908
8195
  this.conversationId = conversationId;
7909
8196
  }
8197
+ wsClient;
8198
+ conversationId;
8199
+ emittedGeneratedImageKeys = /* @__PURE__ */ new Set();
8200
+ suppressSessionLifecycle = false;
7910
8201
  setSuppressSessionLifecycle(suppress) {
7911
8202
  this.suppressSessionLifecycle = suppress;
7912
8203
  }
@@ -7933,6 +8224,19 @@ var WebPresenter = class {
7933
8224
  ts: Date.now(),
7934
8225
  ...isError ? { is_error: true } : {}
7935
8226
  });
8227
+ if (isError) return;
8228
+ for (const image of extractGeneratedImagesFromToolResult(toolId, content, this.cwd)) {
8229
+ this.emitGeneratedImage(image);
8230
+ }
8231
+ }
8232
+ onGeneratedImage(image) {
8233
+ this.emitGeneratedImage(image);
8234
+ }
8235
+ emitGeneratedImage(image) {
8236
+ const key = image.sourceHash ?? `${image.sourcePath ?? image.id}:${image.size}`;
8237
+ if (this.emittedGeneratedImageKeys.has(key)) return;
8238
+ this.emittedGeneratedImageKeys.add(key);
8239
+ this.wsClient.emitEvent(image);
7936
8240
  }
7937
8241
  onTurnComplete(content) {
7938
8242
  this.wsClient.emitEvent({ type: "turn_complete", content, ts: Date.now() });
@@ -11610,6 +11914,7 @@ var WSClient = class {
11610
11914
  selectedEffortLevel: data.selectedEffortLevel,
11611
11915
  mode: data.mode,
11612
11916
  taskMeta: data.taskMeta,
11917
+ prMeta: data.prMeta,
11613
11918
  workflowTools: data.workflowTools,
11614
11919
  runId: data.runId,
11615
11920
  messageId: data.messageId,
@@ -11635,7 +11940,7 @@ var WSClient = class {
11635
11940
  };
11636
11941
 
11637
11942
  // src/version.ts
11638
- var AGENT_VERSION = "0.1.16";
11943
+ var AGENT_VERSION = "0.1.17";
11639
11944
 
11640
11945
  // src/sandbox.ts
11641
11946
  async function runSandbox(config) {
@@ -11645,6 +11950,7 @@ async function runSandbox(config) {
11645
11950
  let pendingMessageResolve = null;
11646
11951
  let currentAgent = null;
11647
11952
  let currentTaskMeta = void 0;
11953
+ let currentPrMeta = void 0;
11648
11954
  let currentWorkflowTools = void 0;
11649
11955
  let currentMaxIterations = config.maxIterations ?? 50;
11650
11956
  let currentTaskId = config.taskId;
@@ -11697,7 +12003,7 @@ async function runSandbox(config) {
11697
12003
  console.error("[sandbox] Failed to connect to WS server:", error.message);
11698
12004
  process.exit(1);
11699
12005
  }
11700
- const presenter = new WebPresenter(wsClient, config.sessionId);
12006
+ const presenter = new WebPresenter(wsClient, config.sessionId, config.projectPath);
11701
12007
  presenter.setSuppressSessionLifecycle(true);
11702
12008
  let lastProviderSessionId = config.providerSessionId;
11703
12009
  let activeBackendKind = config.backendKind || "claude_cli";
@@ -11729,6 +12035,7 @@ async function runSandbox(config) {
11729
12035
  selectedEffortLevel: activeEffortLevel ?? null,
11730
12036
  providerSessionId: lastProviderSessionId ?? void 0,
11731
12037
  taskMeta: currentTaskMeta,
12038
+ prMeta: currentPrMeta,
11732
12039
  taskId: currentTaskId,
11733
12040
  conversationId: currentConversationId,
11734
12041
  teamId: currentTeamId,
@@ -11791,6 +12098,9 @@ async function runSandbox(config) {
11791
12098
  if (nextPayload.taskMeta !== void 0) {
11792
12099
  currentTaskMeta = nextPayload.taskMeta;
11793
12100
  }
12101
+ if (nextPayload.prMeta !== void 0) {
12102
+ currentPrMeta = nextPayload.prMeta;
12103
+ }
11794
12104
  if (nextPayload.workflowTools !== void 0) {
11795
12105
  currentWorkflowTools = nextPayload.workflowTools;
11796
12106
  }
@@ -11821,17 +12131,17 @@ async function runSandbox(config) {
11821
12131
  }
11822
12132
 
11823
12133
  // src/daemon.ts
11824
- var import_node_fs3 = require("fs");
12134
+ var import_node_fs4 = require("fs");
11825
12135
  var import_node_http = __toESM(require("http"), 1);
11826
- var import_node_crypto = require("crypto");
12136
+ var import_node_crypto2 = require("crypto");
11827
12137
  var import_node_os4 = require("os");
11828
- var import_node_path3 = require("path");
12138
+ var import_node_path4 = require("path");
11829
12139
 
11830
12140
  // ../shared/dist/node/provider-limits.js
11831
12141
  var import_node_child_process3 = require("child_process");
11832
- var import_node_fs2 = require("fs");
12142
+ var import_node_fs3 = require("fs");
11833
12143
  var import_node_os3 = require("os");
11834
- var import_node_path2 = require("path");
12144
+ var import_node_path3 = require("path");
11835
12145
  var CACHE_TTL_MS = 6e4;
11836
12146
  var cachedLimits = null;
11837
12147
  function numericValue(value2) {
@@ -11843,11 +12153,11 @@ function numericValue(value2) {
11843
12153
  return null;
11844
12154
  }
11845
12155
  function splitPath2(value2) {
11846
- return (value2 ?? "").split(import_node_path2.delimiter).filter(Boolean);
12156
+ return (value2 ?? "").split(import_node_path3.delimiter).filter(Boolean);
11847
12157
  }
11848
12158
  function isExecutableFile(path) {
11849
12159
  try {
11850
- (0, import_node_fs2.accessSync)(path, import_node_fs2.constants.X_OK);
12160
+ (0, import_node_fs3.accessSync)(path, import_node_fs3.constants.X_OK);
11851
12161
  return true;
11852
12162
  } catch {
11853
12163
  return false;
@@ -11856,10 +12166,10 @@ function isExecutableFile(path) {
11856
12166
  function augmentCliPath2(env) {
11857
12167
  const home = env.HOME || (0, import_node_os3.homedir)();
11858
12168
  const extraPaths = [
11859
- (0, import_node_path2.join)(home, ".local", "bin"),
11860
- (0, import_node_path2.join)(home, ".local", "node", "bin"),
11861
- (0, import_node_path2.join)(home, ".bun", "bin"),
11862
- (0, import_node_path2.join)(home, ".cargo", "bin"),
12169
+ (0, import_node_path3.join)(home, ".local", "bin"),
12170
+ (0, import_node_path3.join)(home, ".local", "node", "bin"),
12171
+ (0, import_node_path3.join)(home, ".bun", "bin"),
12172
+ (0, import_node_path3.join)(home, ".cargo", "bin"),
11863
12173
  "/opt/homebrew/bin",
11864
12174
  "/usr/local/bin"
11865
12175
  ];
@@ -11869,7 +12179,7 @@ function augmentCliPath2(env) {
11869
12179
  return env;
11870
12180
  return {
11871
12181
  ...env,
11872
- PATH: `${missing.join(import_node_path2.delimiter)}${import_node_path2.delimiter}${env.PATH ?? ""}`
12182
+ PATH: `${missing.join(import_node_path3.delimiter)}${import_node_path3.delimiter}${env.PATH ?? ""}`
11873
12183
  };
11874
12184
  }
11875
12185
  function resolveExecutable(command, env, overrideEnvVar) {
@@ -11877,7 +12187,7 @@ function resolveExecutable(command, env, overrideEnvVar) {
11877
12187
  if (override && isExecutableFile(override))
11878
12188
  return override;
11879
12189
  for (const dir of splitPath2(env.PATH)) {
11880
- const candidate = (0, import_node_path2.join)(dir, command);
12190
+ const candidate = (0, import_node_path3.join)(dir, command);
11881
12191
  if (isExecutableFile(candidate))
11882
12192
  return candidate;
11883
12193
  }
@@ -12021,10 +12331,10 @@ async function collectCodexLimits(env) {
12021
12331
  }), 4e3, []);
12022
12332
  }
12023
12333
  function readClaudeCredentialsPayload() {
12024
- const path = (0, import_node_path2.join)((0, import_node_os3.homedir)(), ".claude", ".credentials.json");
12025
- if ((0, import_node_fs2.existsSync)(path)) {
12334
+ const path = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", ".credentials.json");
12335
+ if ((0, import_node_fs3.existsSync)(path)) {
12026
12336
  try {
12027
- return JSON.parse((0, import_node_fs2.readFileSync)(path, "utf8"));
12337
+ return JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
12028
12338
  } catch {
12029
12339
  return null;
12030
12340
  }
@@ -12125,33 +12435,33 @@ function describeOccupiedLocalDaemon(port) {
12125
12435
  return `local daemon API port ${port} is already in use. If Aiden desktop is open, it manages the daemon automatically. Quit Aiden desktop or stop the existing daemon before starting another.`;
12126
12436
  }
12127
12437
  function getConfigPath() {
12128
- return process.env.AIDEN_AGENT_CONFIG_PATH ?? (0, import_node_path3.join)((0, import_node_os4.homedir)(), ".aiden", "agent", "config.json");
12438
+ return process.env.AIDEN_AGENT_CONFIG_PATH ?? (0, import_node_path4.join)((0, import_node_os4.homedir)(), ".aiden", "agent", "config.json");
12129
12439
  }
12130
12440
  function getEndpointDefaultsPath() {
12131
- return process.env.AIDEN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path3.join)((0, import_node_path3.dirname)(getConfigPath()), "endpoints.json");
12441
+ return process.env.AIDEN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path4.join)((0, import_node_path4.dirname)(getConfigPath()), "endpoints.json");
12132
12442
  }
12133
12443
  function readConfig() {
12134
12444
  const configPath = getConfigPath();
12135
- if (!(0, import_node_fs3.existsSync)(configPath)) return {};
12136
- return JSON.parse((0, import_node_fs3.readFileSync)(configPath, "utf8"));
12445
+ if (!(0, import_node_fs4.existsSync)(configPath)) return {};
12446
+ return JSON.parse((0, import_node_fs4.readFileSync)(configPath, "utf8"));
12137
12447
  }
12138
12448
  function readEndpointDefaults() {
12139
12449
  const endpointsPath = getEndpointDefaultsPath();
12140
- if (!(0, import_node_fs3.existsSync)(endpointsPath)) return {};
12450
+ if (!(0, import_node_fs4.existsSync)(endpointsPath)) return {};
12141
12451
  try {
12142
- return JSON.parse((0, import_node_fs3.readFileSync)(endpointsPath, "utf8"));
12452
+ return JSON.parse((0, import_node_fs4.readFileSync)(endpointsPath, "utf8"));
12143
12453
  } catch {
12144
12454
  return {};
12145
12455
  }
12146
12456
  }
12147
12457
  function writeConfig(config) {
12148
12458
  const configPath = getConfigPath();
12149
- (0, import_node_fs3.mkdirSync)((0, import_node_path3.dirname)(configPath), { recursive: true, mode: 448 });
12150
- (0, import_node_fs3.writeFileSync)(configPath, JSON.stringify(config, null, 2), { mode: 384 });
12459
+ (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(configPath), { recursive: true, mode: 448 });
12460
+ (0, import_node_fs4.writeFileSync)(configPath, JSON.stringify(config, null, 2), { mode: 384 });
12151
12461
  }
12152
12462
  function removeConfig() {
12153
12463
  const configPath = getConfigPath();
12154
- if ((0, import_node_fs3.existsSync)(configPath)) (0, import_node_fs3.rmSync)(configPath, { force: true });
12464
+ if ((0, import_node_fs4.existsSync)(configPath)) (0, import_node_fs4.rmSync)(configPath, { force: true });
12155
12465
  }
12156
12466
  function argValue(args, name) {
12157
12467
  const index = args.indexOf(name);
@@ -12238,7 +12548,7 @@ function collectRuntimeMetadata() {
12238
12548
  metadata.cpuCores = cpuList.length;
12239
12549
  }
12240
12550
  try {
12241
- const disk = (0, import_node_fs3.statfsSync)((0, import_node_os4.homedir)());
12551
+ const disk = (0, import_node_fs4.statfsSync)((0, import_node_os4.homedir)());
12242
12552
  metadata.diskFreeBytes = disk.bavail * disk.bsize;
12243
12553
  metadata.diskTotalBytes = disk.blocks * disk.bsize;
12244
12554
  } catch {
@@ -12257,11 +12567,13 @@ async function collectRuntimeMetadataWithProviderLimits() {
12257
12567
  return metadata;
12258
12568
  }
12259
12569
  var RuntimePresenter = class {
12260
- constructor(socket, conversationId, runId) {
12570
+ constructor(socket, conversationId, runId, cwd) {
12261
12571
  this.socket = socket;
12262
12572
  this.conversationId = conversationId;
12263
12573
  this.runId = runId;
12574
+ this.cwd = cwd;
12264
12575
  }
12576
+ emittedGeneratedImageKeys = /* @__PURE__ */ new Set();
12265
12577
  emitEvent(event) {
12266
12578
  this.socket.emit("agent.event", {
12267
12579
  conversationId: this.conversationId,
@@ -12292,6 +12604,19 @@ var RuntimePresenter = class {
12292
12604
  ts: Date.now(),
12293
12605
  ...isError ? { is_error: true } : {}
12294
12606
  });
12607
+ if (isError) return;
12608
+ for (const image of extractGeneratedImagesFromToolResult(toolId, content, this.cwd)) {
12609
+ this.emitGeneratedImage(image);
12610
+ }
12611
+ }
12612
+ onGeneratedImage(image) {
12613
+ this.emitGeneratedImage(image);
12614
+ }
12615
+ emitGeneratedImage(image) {
12616
+ const key = image.sourceHash ?? `${image.sourcePath ?? image.id}:${image.size}`;
12617
+ if (this.emittedGeneratedImageKeys.has(key)) return;
12618
+ this.emittedGeneratedImageKeys.add(key);
12619
+ this.emitEvent(image);
12295
12620
  }
12296
12621
  onTurnComplete(content) {
12297
12622
  this.emitEvent({ type: "turn_complete", content, ts: Date.now() });
@@ -12376,7 +12701,7 @@ async function setupDaemon(args) {
12376
12701
  runtimeId: body.runtime.id,
12377
12702
  runtimeToken: body.runtimeToken,
12378
12703
  localApiPort: getLocalApiPort(args, {}),
12379
- localApiToken: (0, import_node_crypto.randomBytes)(24).toString("hex"),
12704
+ localApiToken: (0, import_node_crypto2.randomBytes)(24).toString("hex"),
12380
12705
  displayName: body.runtime.displayName ?? displayName
12381
12706
  });
12382
12707
  console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: getConfigPath() });
@@ -12422,7 +12747,7 @@ async function loginWithDeviceCode(args) {
12422
12747
  runtimeId: body.runtime.id,
12423
12748
  runtimeToken: body.runtimeToken,
12424
12749
  localApiPort: getLocalApiPort(args, {}),
12425
- localApiToken: (0, import_node_crypto.randomBytes)(24).toString("hex"),
12750
+ localApiToken: (0, import_node_crypto2.randomBytes)(24).toString("hex"),
12426
12751
  displayName: body.runtime.displayName ?? displayName
12427
12752
  });
12428
12753
  console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: getConfigPath() });
@@ -12436,7 +12761,7 @@ async function startDaemon(args) {
12436
12761
  const runtimeToken = argValue(args, "--token") ?? process.env.AIDEN_RUNTIME_TOKEN ?? stored.runtimeToken;
12437
12762
  const wsUrl = argValue(args, "--ws-url") ?? process.env.AIDEN_WS_URL ?? stored.wsUrl;
12438
12763
  let localApiPort = getLocalApiPort(args, stored);
12439
- const localApiToken = stored.localApiToken ?? (0, import_node_crypto.randomBytes)(24).toString("hex");
12764
+ const localApiToken = stored.localApiToken ?? (0, import_node_crypto2.randomBytes)(24).toString("hex");
12440
12765
  if (!runtimeId || !runtimeToken || !wsUrl) {
12441
12766
  throw new Error("daemon requires runtimeId, runtime token, and wsUrl. Run setup first or pass --runtime-id/--token/--ws-url.");
12442
12767
  }
@@ -12508,13 +12833,13 @@ async function startDaemon(args) {
12508
12833
  }
12509
12834
  socket.emit("agent.accepted", { runId: payload.runId });
12510
12835
  pushLog(`accepted run=${payload.runId}`);
12511
- const presenter = new RuntimePresenter(socket, payload.conversationId, payload.runId);
12836
+ const cwd = payload.projectPath ?? process.cwd();
12837
+ const presenter = new RuntimePresenter(socket, payload.conversationId, payload.runId, cwd);
12512
12838
  const agent = new CoreAgent(presenter, {
12513
12839
  backendKind,
12514
12840
  runtimeCommand,
12515
12841
  providerApiKey: payload.providerApiKey
12516
12842
  });
12517
- const cwd = payload.projectPath ?? process.cwd();
12518
12843
  activeAgents.set(payload.runId, { agent, presenter });
12519
12844
  void agent.run({
12520
12845
  task: payload.content,
@@ -12531,6 +12856,7 @@ async function startDaemon(args) {
12531
12856
  selectedEffortLevel: payload.selectedEffortLevel ?? null,
12532
12857
  providerSessionId: payload.providerSessionId,
12533
12858
  taskMeta: payload.taskMeta,
12859
+ prMeta: payload.prMeta,
12534
12860
  conversationId: payload.conversationId,
12535
12861
  taskId: payload.taskMeta?.id,
12536
12862
  teamId: payload.teamId,
@@ -1 +1 @@
1
- {"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAe5E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAmBjE"}
1
+ {"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB5E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAmBjE"}
package/dist/updater.js CHANGED
@@ -10,6 +10,10 @@ const DEFAULT_PATH = "/home/user/.local/node/bin:/home/user/.local/bin:/usr/loca
10
10
  */
11
11
  export async function installUpdate(payload) {
12
12
  const version = payload.version ?? "latest";
13
+ if (!/^[\w.\-+]+$/.test(version)) {
14
+ console.error(`[updater] Refusing to install: invalid version string "${version}"`);
15
+ return false;
16
+ }
13
17
  try {
14
18
  console.info(`[updater] Installing @aiden-ade/sandbox-agent@${version} via npm`);
15
19
  execSync(`npm install -g @aiden-ade/sandbox-agent@${version}`, {
@@ -1 +1 @@
1
- {"version":3,"file":"updater.js","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,YAAY,GAAG,+GAA+G,CAAC;AAOrI;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAsB;IACxD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC;IAC5C,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,iDAAiD,OAAO,UAAU,CAAC,CAAC;QACjF,QAAQ,CAAC,2CAA2C,OAAO,EAAE,EAAE;YAC7D,OAAO,EAAE,MAAM;YACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE;YAC3C,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,qBAA8B;IACzD,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,IAAI,qBAAqB,EAAE,CAAC;QAC1B,GAAG,CAAC,yBAAyB,GAAG,qBAAqB,CAAC;IACxD,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,EAAE,EAAE;QACrC,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE;KACpC,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,wDAAwD;IACxD,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC"}
1
+ {"version":3,"file":"updater.js","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,YAAY,GAAG,+GAA+G,CAAC;AAOrI;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAsB;IACxD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC;IAC5C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,0DAA0D,OAAO,GAAG,CAAC,CAAC;QACpF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,iDAAiD,OAAO,UAAU,CAAC,CAAC;QACjF,QAAQ,CAAC,2CAA2C,OAAO,EAAE,EAAE;YAC7D,OAAO,EAAE,MAAM;YACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE;YAC3C,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,qBAA8B;IACzD,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,IAAI,qBAAqB,EAAE,CAAC;QAC1B,GAAG,CAAC,yBAAyB,GAAG,qBAAqB,CAAC;IACxD,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,EAAE,EAAE;QACrC,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE;KACpC,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,wDAAwD;IACxD,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiden-ade/sandbox-agent",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "aiden-agent": "./dist/index.cjs"
@@ -1,6 +0,0 @@
1
- /**
2
- * Re-exports from the canonical shared system prompt.
3
- * Single source of truth: packages/shared/src/agent/system-prompt.ts
4
- */
5
- export * from "@aiden/shared/agent";
6
- //# sourceMappingURL=aiden-system-prompt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aiden-system-prompt.d.ts","sourceRoot":"","sources":["../src/aiden-system-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,qBAAqB,CAAC"}
@@ -1,6 +0,0 @@
1
- /**
2
- * Re-exports from the canonical shared system prompt.
3
- * Single source of truth: packages/shared/src/agent/system-prompt.ts
4
- */
5
- export * from "@aiden/shared/agent";
6
- //# sourceMappingURL=aiden-system-prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aiden-system-prompt.js","sourceRoot":"","sources":["../src/aiden-system-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,qBAAqB,CAAC"}