@aiden-ade/sandbox-agent 0.1.15 → 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/core-agent.d.ts +33 -0
- package/dist/core-agent.d.ts.map +1 -0
- package/dist/core-agent.js +218 -0
- package/dist/core-agent.js.map +1 -0
- package/dist/index.cjs +722 -106
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime-backends.d.ts +2 -0
- package/dist/runtime-backends.d.ts.map +1 -0
- package/dist/runtime-backends.js +2 -0
- package/dist/runtime-backends.js.map +1 -0
- package/dist/sandbox.d.ts +25 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +185 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/updater.d.ts +15 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +54 -0
- package/dist/updater.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/dist/web-presenter.d.ts +33 -0
- package/dist/web-presenter.d.ts.map +1 -0
- package/dist/web-presenter.js +100 -0
- package/dist/web-presenter.js.map +1 -0
- package/dist/ws-client.d.ts +79 -0
- package/dist/ws-client.d.ts.map +1 -0
- package/dist/ws-client.js +74 -0
- package/dist/ws-client.js.map +1 -0
- package/package.json +11 -12
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ var require_XMLHttpRequest = __commonJS({
|
|
|
36
36
|
"use strict";
|
|
37
37
|
var fs = require("fs");
|
|
38
38
|
var Url = require("url");
|
|
39
|
-
var
|
|
39
|
+
var spawn3 = require("child_process").spawn;
|
|
40
40
|
module2.exports = XMLHttpRequest3;
|
|
41
41
|
XMLHttpRequest3.XMLHttpRequest = XMLHttpRequest3;
|
|
42
42
|
function XMLHttpRequest3(opts) {
|
|
@@ -332,7 +332,7 @@ var require_XMLHttpRequest = __commonJS({
|
|
|
332
332
|
var syncFile = ".node-xmlhttprequest-sync-" + process.pid;
|
|
333
333
|
fs.writeFileSync(syncFile, "", "utf8");
|
|
334
334
|
var execString = "var http = require('http'), https = require('https'), fs = require('fs');var doRequest = http" + (ssl ? "s" : "") + ".request;var options = " + JSON.stringify(options) + ";var responseText = '';var responseData = Buffer.alloc(0);var req = doRequest(options, function(response) {response.on('data', function(chunk) { var data = Buffer.from(chunk); responseText += data.toString('utf8'); responseData = Buffer.concat([responseData, data]);});response.on('end', function() {fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText, data: responseData.toString('base64')}}), 'utf8');fs.unlinkSync('" + syncFile + "');});response.on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});}).on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});" + (data ? "req.write('" + JSON.stringify(data).slice(1, -1).replace(/'/g, "\\'") + "');" : "") + "req.end();";
|
|
335
|
-
var syncProc =
|
|
335
|
+
var syncProc = spawn3(process.argv[0], ["-e", execString]);
|
|
336
336
|
var statusText;
|
|
337
337
|
while (fs.existsSync(syncFile)) {
|
|
338
338
|
}
|
|
@@ -645,8 +645,8 @@ var require_common = __commonJS({
|
|
|
645
645
|
}
|
|
646
646
|
return debug12;
|
|
647
647
|
}
|
|
648
|
-
function extend(namespace,
|
|
649
|
-
const newDebug = createDebug(this.namespace + (typeof
|
|
648
|
+
function extend(namespace, delimiter2) {
|
|
649
|
+
const newDebug = createDebug(this.namespace + (typeof delimiter2 === "undefined" ? ":" : delimiter2) + namespace);
|
|
650
650
|
newDebug.log = this.log;
|
|
651
651
|
return newDebug;
|
|
652
652
|
}
|
|
@@ -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:
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
4817
|
+
var COORDINATOR_PROMPT = `## You are the Orchestrator
|
|
4818
4818
|
|
|
4819
|
-
You are the **
|
|
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
|
|
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
|
-
|
|
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. \`
|
|
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. \`
|
|
4842
|
-
7. \`
|
|
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
|
|
4853
|
+
## How to delegate
|
|
4861
4854
|
|
|
4862
|
-
|
|
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 \`
|
|
4875
|
-
4. After delegation,
|
|
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
|
|
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
|
-
- **
|
|
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: "
|
|
5024
|
-
description: "Plans work, breaks down tasks,
|
|
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:
|
|
5029
|
-
canRunCommands:
|
|
5030
|
-
canCreateArtifacts:
|
|
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
|
|
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");
|
|
@@ -5218,6 +5251,8 @@ var INTERACTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
5218
5251
|
"exitplanmode",
|
|
5219
5252
|
"enterplanmode"
|
|
5220
5253
|
]);
|
|
5254
|
+
var AIDEN_AGENT_WORKOS_USER_ID_PREFIX = "aiden-agent:";
|
|
5255
|
+
var AIDEN_AGENT_WORKOS_USER_ID_LIKE_PATTERN = `${AIDEN_AGENT_WORKOS_USER_ID_PREFIX}%`;
|
|
5221
5256
|
|
|
5222
5257
|
// ../shared/dist/constants/tasks.js
|
|
5223
5258
|
var STATUS_OPTIONS = [
|
|
@@ -5374,6 +5409,7 @@ function normalizeCodexMcpToolResult(output) {
|
|
|
5374
5409
|
}
|
|
5375
5410
|
return raw;
|
|
5376
5411
|
}
|
|
5412
|
+
var MAX_INLINE_GENERATED_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
5377
5413
|
function findCodexSessionLog(runtimeSessionId, codexHome) {
|
|
5378
5414
|
if (!runtimeSessionId || !(0, import_fs.existsSync)(codexHome)) return null;
|
|
5379
5415
|
const root = (0, import_path.join)(codexHome, "sessions");
|
|
@@ -5404,14 +5440,106 @@ function findCodexSessionLog(runtimeSessionId, codexHome) {
|
|
|
5404
5440
|
matches.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
5405
5441
|
return matches[0]?.path ?? null;
|
|
5406
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
|
+
}
|
|
5407
5533
|
async function replayCodexMcpToolEventsFromSessionLog(context, state) {
|
|
5408
5534
|
const runtimeSessionId = state.runtimeSessionId;
|
|
5409
5535
|
if (!runtimeSessionId) return;
|
|
5410
5536
|
const codexHome = context.env.CODEX_HOME || process.env.CODEX_HOME || (0, import_path.join)((0, import_os.homedir)(), ".codex");
|
|
5411
5537
|
const logPath = findCodexSessionLog(runtimeSessionId, codexHome);
|
|
5412
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;
|
|
5413
5542
|
const emittedToolIds = /* @__PURE__ */ new Set();
|
|
5414
|
-
const lines = (0, import_fs.readFileSync)(logPath, "utf8").split(/\r?\n/).filter(Boolean);
|
|
5415
5543
|
for (const line of lines) {
|
|
5416
5544
|
const entry = parseJsonObject(line);
|
|
5417
5545
|
const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
|
|
@@ -5431,20 +5559,27 @@ async function replayCodexMcpToolEventsFromSessionLog(context, state) {
|
|
|
5431
5559
|
if (!callId) continue;
|
|
5432
5560
|
context.presenter.onToolUse("tool_search", payload.arguments ?? {}, callId);
|
|
5433
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);
|
|
5434
5567
|
}
|
|
5435
5568
|
}
|
|
5436
|
-
if (emittedToolIds.size
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
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
|
+
}
|
|
5448
5583
|
}
|
|
5449
5584
|
}
|
|
5450
5585
|
}
|
|
@@ -5454,7 +5589,7 @@ function kimiSessionId(cwd) {
|
|
|
5454
5589
|
resolved = (0, import_fs2.realpathSync)(cwd);
|
|
5455
5590
|
} catch {
|
|
5456
5591
|
}
|
|
5457
|
-
return (0,
|
|
5592
|
+
return (0, import_crypto2.createHash)("md5").update(resolved).digest("hex");
|
|
5458
5593
|
}
|
|
5459
5594
|
function parseKimiStructuredLine(line, context, state) {
|
|
5460
5595
|
const presenter = context.presenter;
|
|
@@ -6136,7 +6271,7 @@ function resolveKimiCliModelArg(model) {
|
|
|
6136
6271
|
if (trimmed.startsWith("claude-")) return void 0;
|
|
6137
6272
|
return trimmed;
|
|
6138
6273
|
}
|
|
6139
|
-
function createKimiCliBackend(command = "kimi", defaultArgs = []) {
|
|
6274
|
+
function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
|
|
6140
6275
|
return {
|
|
6141
6276
|
kind: "kimi_cli",
|
|
6142
6277
|
supportTier: "structured",
|
|
@@ -6962,7 +7097,12 @@ function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
|
|
|
6962
7097
|
const resumeId = ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim();
|
|
6963
7098
|
const modelArgs = ctx.config.selectedModel?.trim() ? ["--model", ctx.config.selectedModel.trim()] : [];
|
|
6964
7099
|
const effortArgs = buildCodexEffortArgs(ctx.config.selectedEffortLevel);
|
|
6965
|
-
const permissionArgs = [
|
|
7100
|
+
const permissionArgs = [
|
|
7101
|
+
"--ask-for-approval",
|
|
7102
|
+
"never",
|
|
7103
|
+
"--sandbox",
|
|
7104
|
+
"danger-full-access"
|
|
7105
|
+
];
|
|
6966
7106
|
const imageArgs = imagePaths.flatMap((p) => ["--image", p]);
|
|
6967
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, "-"];
|
|
6968
7108
|
return [...baseArgs, ...defaultArgs];
|
|
@@ -7146,17 +7286,11 @@ function buildTaskLifecyclePrompt(config) {
|
|
|
7146
7286
|
] : [];
|
|
7147
7287
|
return [
|
|
7148
7288
|
"## Task Lifecycle",
|
|
7149
|
-
`This session is attached to taskId "${taskId}"
|
|
7289
|
+
`This session is attached to taskId "${taskId}".`,
|
|
7290
|
+
`Do not change the task status on your own. The user manages this task's status. Only change it by calling the Aiden MCP update_task tool when the user explicitly asks you to (for example: "move this to review" or "mark it done"). Do not update the status proactively as you move through research, implementation, testing, or review phases.`,
|
|
7150
7291
|
...statusLines,
|
|
7151
7292
|
"",
|
|
7152
|
-
"
|
|
7153
|
-
"Lifecycle mapping:",
|
|
7154
|
-
"- Research / discovery / code reading / planning: use the best matching status such as research, discovery, planning, or the first active status.",
|
|
7155
|
-
"- Implementation / coding / file edits: use the best matching status such as implementing, in_progress, working, or running.",
|
|
7156
|
-
"- Local validation / tests / QA: use the best matching status such as localtesting, local_testing, testing, qa, or validation.",
|
|
7157
|
-
"- Ready for human review: use the best matching review status such as in_review or review.",
|
|
7158
|
-
"- Done: use only when the requested work is fully complete and validated; otherwise leave it in the review/testing phase.",
|
|
7159
|
-
"If no suitable status exists for a phase, leave the current status unchanged rather than forcing an unrelated one."
|
|
7293
|
+
"When the user asks you to change the status, use exact status IDs from the available statuses. Do not invent status IDs. If none of the available statuses clearly matches the request, ask which one they mean instead of guessing."
|
|
7160
7294
|
].join("\n");
|
|
7161
7295
|
}
|
|
7162
7296
|
var BaseMachineAgent = class _BaseMachineAgent {
|
|
@@ -7291,7 +7425,7 @@ Prefer relative paths and keep your work scoped to this project.`
|
|
|
7291
7425
|
const promptText = this.buildPromptText(runtimeConfig);
|
|
7292
7426
|
const runtimeCommand = runtimeConfig.runtimeCommand || this.runtime.runtimeCommand;
|
|
7293
7427
|
const runtimeArgs = runtimeConfig.runtimeArgs || this.runtime.runtimeArgs || [];
|
|
7294
|
-
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);
|
|
7295
7429
|
let lastResult = null;
|
|
7296
7430
|
for (let attempt = 0; attempt <= _BaseMachineAgent.MAX_RETRIES; attempt++) {
|
|
7297
7431
|
if (this.abortController?.signal.aborted) break;
|
|
@@ -7443,7 +7577,7 @@ var PROVIDER_CLI_COMMANDS = {
|
|
|
7443
7577
|
copilot_cli: { provider: "copilot_cli", command: "copilot", envVar: "AIDEN_COPILOT_PATH" },
|
|
7444
7578
|
cursor_agent_cli: { provider: "cursor_agent_cli", command: "cursor-agent", envVar: "AIDEN_CURSOR_AGENT_PATH" },
|
|
7445
7579
|
gemini_cli: { provider: "gemini_cli", command: "gemini", envVar: "AIDEN_GEMINI_PATH" },
|
|
7446
|
-
kimi_cli: { provider: "kimi_cli", command: "kimi", envVar: "AIDEN_KIMI_PATH" },
|
|
7580
|
+
kimi_cli: { provider: "kimi_cli", command: "kimi-cli", envVar: "AIDEN_KIMI_PATH" },
|
|
7447
7581
|
opencode_cli: { provider: "opencode_cli", command: "opencode", envVar: "AIDEN_OPENCODE_PATH" },
|
|
7448
7582
|
droid_cli: { provider: "droid_cli", command: "droid", envVar: "AIDEN_DROID_PATH" },
|
|
7449
7583
|
supatest_cli: { provider: "supatest_cli", command: "supatest", envVar: "AIDEN_SUPATEST_PATH" }
|
|
@@ -7461,11 +7595,14 @@ var BACKEND_CLI_COMMANDS = {
|
|
|
7461
7595
|
cursor_agent_cli: "cursor-agent",
|
|
7462
7596
|
gemini_cli: "gemini",
|
|
7463
7597
|
gemini: "gemini",
|
|
7464
|
-
kimi_cli: "kimi",
|
|
7598
|
+
kimi_cli: "kimi-cli",
|
|
7465
7599
|
opencode_cli: "opencode",
|
|
7466
7600
|
droid_cli: "droid",
|
|
7467
7601
|
supatest_cli: "supatest"
|
|
7468
7602
|
};
|
|
7603
|
+
var CLI_COMMAND_ALIASES = {
|
|
7604
|
+
"kimi-cli": ["kimi"]
|
|
7605
|
+
};
|
|
7469
7606
|
var resolvedCliCache = /* @__PURE__ */ new Map();
|
|
7470
7607
|
var cachedLoginShellEnv = null;
|
|
7471
7608
|
function parseEnvOutput(output) {
|
|
@@ -7593,7 +7730,8 @@ function resolveCliExecutable(command, env = getDaemonCliEnvironment()) {
|
|
|
7593
7730
|
const home = enriched.HOME || enriched.USERPROFILE || (0, import_node_os.homedir)();
|
|
7594
7731
|
const isWin = (0, import_node_os.platform)() === "win32";
|
|
7595
7732
|
const pathExt = enriched.PATHEXT ?? (isWin ? ".EXE;.CMD;.BAT;.COM" : "");
|
|
7596
|
-
const
|
|
7733
|
+
const commandNames = [trimmed, ...CLI_COMMAND_ALIASES[trimmed] ?? []];
|
|
7734
|
+
const names = commandNames.flatMap((name) => isWin ? windowsCommandCandidates(name, pathExt) : [name]);
|
|
7597
7735
|
const candidates = [];
|
|
7598
7736
|
for (const name of names) {
|
|
7599
7737
|
if (name.includes("/") || name.includes("\\")) {
|
|
@@ -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
|
-
|
|
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.
|
|
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,11 +12131,285 @@ async function runSandbox(config) {
|
|
|
11821
12131
|
}
|
|
11822
12132
|
|
|
11823
12133
|
// src/daemon.ts
|
|
11824
|
-
var
|
|
12134
|
+
var import_node_fs4 = require("fs");
|
|
11825
12135
|
var import_node_http = __toESM(require("http"), 1);
|
|
11826
|
-
var
|
|
12136
|
+
var import_node_crypto2 = require("crypto");
|
|
12137
|
+
var import_node_os4 = require("os");
|
|
12138
|
+
var import_node_path4 = require("path");
|
|
12139
|
+
|
|
12140
|
+
// ../shared/dist/node/provider-limits.js
|
|
12141
|
+
var import_node_child_process3 = require("child_process");
|
|
12142
|
+
var import_node_fs3 = require("fs");
|
|
11827
12143
|
var import_node_os3 = require("os");
|
|
11828
|
-
var
|
|
12144
|
+
var import_node_path3 = require("path");
|
|
12145
|
+
var CACHE_TTL_MS = 6e4;
|
|
12146
|
+
var cachedLimits = null;
|
|
12147
|
+
function numericValue(value2) {
|
|
12148
|
+
if (typeof value2 === "number" && Number.isFinite(value2))
|
|
12149
|
+
return value2;
|
|
12150
|
+
if (typeof value2 === "string" && value2.trim() && Number.isFinite(Number(value2))) {
|
|
12151
|
+
return Number(value2);
|
|
12152
|
+
}
|
|
12153
|
+
return null;
|
|
12154
|
+
}
|
|
12155
|
+
function splitPath2(value2) {
|
|
12156
|
+
return (value2 ?? "").split(import_node_path3.delimiter).filter(Boolean);
|
|
12157
|
+
}
|
|
12158
|
+
function isExecutableFile(path) {
|
|
12159
|
+
try {
|
|
12160
|
+
(0, import_node_fs3.accessSync)(path, import_node_fs3.constants.X_OK);
|
|
12161
|
+
return true;
|
|
12162
|
+
} catch {
|
|
12163
|
+
return false;
|
|
12164
|
+
}
|
|
12165
|
+
}
|
|
12166
|
+
function augmentCliPath2(env) {
|
|
12167
|
+
const home = env.HOME || (0, import_node_os3.homedir)();
|
|
12168
|
+
const extraPaths = [
|
|
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"),
|
|
12173
|
+
"/opt/homebrew/bin",
|
|
12174
|
+
"/usr/local/bin"
|
|
12175
|
+
];
|
|
12176
|
+
const existing = new Set(splitPath2(env.PATH));
|
|
12177
|
+
const missing = extraPaths.filter((path) => !existing.has(path));
|
|
12178
|
+
if (missing.length === 0)
|
|
12179
|
+
return env;
|
|
12180
|
+
return {
|
|
12181
|
+
...env,
|
|
12182
|
+
PATH: `${missing.join(import_node_path3.delimiter)}${import_node_path3.delimiter}${env.PATH ?? ""}`
|
|
12183
|
+
};
|
|
12184
|
+
}
|
|
12185
|
+
function resolveExecutable(command, env, overrideEnvVar) {
|
|
12186
|
+
const override = env[overrideEnvVar]?.trim();
|
|
12187
|
+
if (override && isExecutableFile(override))
|
|
12188
|
+
return override;
|
|
12189
|
+
for (const dir of splitPath2(env.PATH)) {
|
|
12190
|
+
const candidate = (0, import_node_path3.join)(dir, command);
|
|
12191
|
+
if (isExecutableFile(candidate))
|
|
12192
|
+
return candidate;
|
|
12193
|
+
}
|
|
12194
|
+
return null;
|
|
12195
|
+
}
|
|
12196
|
+
function limitLabel(windowMinutes, fallback) {
|
|
12197
|
+
if (windowMinutes === 5 * 60)
|
|
12198
|
+
return "5h";
|
|
12199
|
+
if (windowMinutes === 7 * 24 * 60)
|
|
12200
|
+
return "Weekly";
|
|
12201
|
+
return fallback;
|
|
12202
|
+
}
|
|
12203
|
+
function windowFromUsedPercent(params) {
|
|
12204
|
+
const usedPercent = Math.max(0, Math.min(100, params.usedPercent));
|
|
12205
|
+
return {
|
|
12206
|
+
label: limitLabel(params.windowMinutes, params.fallbackLabel),
|
|
12207
|
+
remaining: Math.max(0, 100 - usedPercent),
|
|
12208
|
+
limit: 100,
|
|
12209
|
+
usedPercent,
|
|
12210
|
+
...params.windowMinutes !== null ? { windowMinutes: params.windowMinutes } : {},
|
|
12211
|
+
...params.resetAt ? { resetAt: params.resetAt } : {},
|
|
12212
|
+
source: params.source
|
|
12213
|
+
};
|
|
12214
|
+
}
|
|
12215
|
+
function codexWindow(raw, fallbackLabel) {
|
|
12216
|
+
if (!raw)
|
|
12217
|
+
return null;
|
|
12218
|
+
const usedPercent = numericValue(raw.usedPercent);
|
|
12219
|
+
if (usedPercent === null)
|
|
12220
|
+
return null;
|
|
12221
|
+
const windowMinutes = numericValue(raw.windowDurationMins);
|
|
12222
|
+
const resetSeconds = numericValue(raw.resetsAt);
|
|
12223
|
+
const resetAt = resetSeconds !== null ? new Date(resetSeconds * 1e3).toISOString() : null;
|
|
12224
|
+
return windowFromUsedPercent({
|
|
12225
|
+
usedPercent,
|
|
12226
|
+
windowMinutes,
|
|
12227
|
+
resetAt,
|
|
12228
|
+
fallbackLabel,
|
|
12229
|
+
source: "codex-cli-rpc"
|
|
12230
|
+
});
|
|
12231
|
+
}
|
|
12232
|
+
function claudeWindow(raw, label, windowMinutes) {
|
|
12233
|
+
if (!raw)
|
|
12234
|
+
return null;
|
|
12235
|
+
const usedPercent = numericValue(raw.utilization);
|
|
12236
|
+
if (usedPercent === null)
|
|
12237
|
+
return null;
|
|
12238
|
+
const resetAt = typeof raw.resets_at === "string" && raw.resets_at.trim() ? raw.resets_at.trim() : null;
|
|
12239
|
+
return windowFromUsedPercent({
|
|
12240
|
+
usedPercent,
|
|
12241
|
+
windowMinutes,
|
|
12242
|
+
resetAt,
|
|
12243
|
+
fallbackLabel: label,
|
|
12244
|
+
source: "claude-oauth"
|
|
12245
|
+
});
|
|
12246
|
+
}
|
|
12247
|
+
async function withTimeout(promise, timeoutMs, fallback) {
|
|
12248
|
+
let timer;
|
|
12249
|
+
try {
|
|
12250
|
+
return await Promise.race([
|
|
12251
|
+
promise,
|
|
12252
|
+
new Promise((resolve2) => {
|
|
12253
|
+
timer = setTimeout(() => resolve2(fallback), timeoutMs);
|
|
12254
|
+
})
|
|
12255
|
+
]);
|
|
12256
|
+
} finally {
|
|
12257
|
+
if (timer)
|
|
12258
|
+
clearTimeout(timer);
|
|
12259
|
+
}
|
|
12260
|
+
}
|
|
12261
|
+
async function collectCodexLimits(env) {
|
|
12262
|
+
const runtimeEnv = augmentCliPath2(env);
|
|
12263
|
+
const codexCommand = resolveExecutable("codex", runtimeEnv, "AIDEN_CODEX_PATH");
|
|
12264
|
+
if (!codexCommand)
|
|
12265
|
+
return [];
|
|
12266
|
+
return withTimeout(new Promise((resolve2) => {
|
|
12267
|
+
const child = (0, import_node_child_process3.spawn)(codexCommand, ["-s", "read-only", "-a", "untrusted", "app-server"], {
|
|
12268
|
+
env: runtimeEnv,
|
|
12269
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
12270
|
+
});
|
|
12271
|
+
let nextId = 1;
|
|
12272
|
+
let buffer = "";
|
|
12273
|
+
const pending = /* @__PURE__ */ new Map();
|
|
12274
|
+
const finish = (windows = []) => {
|
|
12275
|
+
pending.clear();
|
|
12276
|
+
if (!child.killed)
|
|
12277
|
+
child.kill();
|
|
12278
|
+
resolve2(windows);
|
|
12279
|
+
};
|
|
12280
|
+
const request = (method, params = {}) => {
|
|
12281
|
+
const id = nextId++;
|
|
12282
|
+
child.stdin.write(`${JSON.stringify({ id, method, params })}
|
|
12283
|
+
`);
|
|
12284
|
+
return new Promise((requestResolve) => {
|
|
12285
|
+
pending.set(id, requestResolve);
|
|
12286
|
+
});
|
|
12287
|
+
};
|
|
12288
|
+
child.on("error", () => finish());
|
|
12289
|
+
child.on("exit", () => finish());
|
|
12290
|
+
child.stdout.on("data", (chunk) => {
|
|
12291
|
+
buffer += chunk.toString("utf8");
|
|
12292
|
+
const lines = buffer.split("\n");
|
|
12293
|
+
buffer = lines.pop() ?? "";
|
|
12294
|
+
for (const line of lines) {
|
|
12295
|
+
const trimmed = line.trim();
|
|
12296
|
+
if (!trimmed)
|
|
12297
|
+
continue;
|
|
12298
|
+
let message;
|
|
12299
|
+
try {
|
|
12300
|
+
message = JSON.parse(trimmed);
|
|
12301
|
+
} catch {
|
|
12302
|
+
continue;
|
|
12303
|
+
}
|
|
12304
|
+
const id = numericValue(message.id);
|
|
12305
|
+
if (id === null)
|
|
12306
|
+
continue;
|
|
12307
|
+
const resolver = pending.get(id);
|
|
12308
|
+
if (!resolver)
|
|
12309
|
+
continue;
|
|
12310
|
+
pending.delete(id);
|
|
12311
|
+
resolver(message.error ? null : message.result);
|
|
12312
|
+
}
|
|
12313
|
+
});
|
|
12314
|
+
void (async () => {
|
|
12315
|
+
try {
|
|
12316
|
+
await request("initialize", {
|
|
12317
|
+
clientInfo: { name: "aiden", version: "runtime" }
|
|
12318
|
+
});
|
|
12319
|
+
child.stdin.write(`${JSON.stringify({ method: "initialized", params: {} })}
|
|
12320
|
+
`);
|
|
12321
|
+
const result = await request("account/rateLimits/read");
|
|
12322
|
+
const windows = [
|
|
12323
|
+
codexWindow(result?.rateLimits?.primary, "Primary"),
|
|
12324
|
+
codexWindow(result?.rateLimits?.secondary, "Weekly")
|
|
12325
|
+
].filter((window2) => Boolean(window2));
|
|
12326
|
+
finish(windows);
|
|
12327
|
+
} catch {
|
|
12328
|
+
finish();
|
|
12329
|
+
}
|
|
12330
|
+
})();
|
|
12331
|
+
}), 4e3, []);
|
|
12332
|
+
}
|
|
12333
|
+
function readClaudeCredentialsPayload() {
|
|
12334
|
+
const path = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", ".credentials.json");
|
|
12335
|
+
if ((0, import_node_fs3.existsSync)(path)) {
|
|
12336
|
+
try {
|
|
12337
|
+
return JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
|
|
12338
|
+
} catch {
|
|
12339
|
+
return null;
|
|
12340
|
+
}
|
|
12341
|
+
}
|
|
12342
|
+
if (process.platform !== "darwin")
|
|
12343
|
+
return null;
|
|
12344
|
+
try {
|
|
12345
|
+
const raw = (0, import_node_child_process3.execFileSync)("security", ["find-generic-password", "-s", "Claude Code-credentials", "-w"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
12346
|
+
if (!raw)
|
|
12347
|
+
return null;
|
|
12348
|
+
return JSON.parse(raw);
|
|
12349
|
+
} catch {
|
|
12350
|
+
return null;
|
|
12351
|
+
}
|
|
12352
|
+
}
|
|
12353
|
+
function readClaudeAccessToken() {
|
|
12354
|
+
const parsed = readClaudeCredentialsPayload();
|
|
12355
|
+
if (!parsed)
|
|
12356
|
+
return null;
|
|
12357
|
+
try {
|
|
12358
|
+
const oauth = parsed.claudeAiOauth;
|
|
12359
|
+
if (!oauth || typeof oauth.accessToken !== "string" || !oauth.accessToken.trim())
|
|
12360
|
+
return null;
|
|
12361
|
+
const expiresAt = numericValue(oauth.expiresAt);
|
|
12362
|
+
if (expiresAt !== null && Date.now() >= expiresAt)
|
|
12363
|
+
return null;
|
|
12364
|
+
return oauth.accessToken.trim();
|
|
12365
|
+
} catch {
|
|
12366
|
+
return null;
|
|
12367
|
+
}
|
|
12368
|
+
}
|
|
12369
|
+
async function collectClaudeLimits() {
|
|
12370
|
+
const token = readClaudeAccessToken();
|
|
12371
|
+
if (!token)
|
|
12372
|
+
return [];
|
|
12373
|
+
return withTimeout((async () => {
|
|
12374
|
+
const response = await fetch("https://api.anthropic.com/api/oauth/usage", {
|
|
12375
|
+
headers: {
|
|
12376
|
+
accept: "application/json",
|
|
12377
|
+
authorization: `Bearer ${token}`,
|
|
12378
|
+
"anthropic-beta": "oauth-2025-04-20",
|
|
12379
|
+
"user-agent": "claude-code/2.1.0"
|
|
12380
|
+
}
|
|
12381
|
+
});
|
|
12382
|
+
if (!response.ok)
|
|
12383
|
+
return [];
|
|
12384
|
+
const body = await response.json();
|
|
12385
|
+
return [
|
|
12386
|
+
claudeWindow(body.five_hour, "5h", 5 * 60),
|
|
12387
|
+
claudeWindow(body.seven_day, "Weekly", 7 * 24 * 60)
|
|
12388
|
+
].filter((window2) => Boolean(window2));
|
|
12389
|
+
})().catch(() => []), 4e3, []);
|
|
12390
|
+
}
|
|
12391
|
+
async function collectLocalAgentProviderLimits(env = process.env) {
|
|
12392
|
+
if (cachedLimits && Object.keys(cachedLimits.value).length > 0 && Date.now() - cachedLimits.collectedAt < CACHE_TTL_MS) {
|
|
12393
|
+
return cachedLimits.value;
|
|
12394
|
+
}
|
|
12395
|
+
const [codex, claude] = await Promise.all([
|
|
12396
|
+
collectCodexLimits(env),
|
|
12397
|
+
collectClaudeLimits()
|
|
12398
|
+
]);
|
|
12399
|
+
const limits = {};
|
|
12400
|
+
if (codex.length > 0)
|
|
12401
|
+
limits.codex_app_server = codex;
|
|
12402
|
+
if (claude.length > 0)
|
|
12403
|
+
limits.claude_cli = claude;
|
|
12404
|
+
if (Object.keys(limits).length > 0) {
|
|
12405
|
+
cachedLimits = { value: limits, collectedAt: Date.now() };
|
|
12406
|
+
} else {
|
|
12407
|
+
cachedLimits = null;
|
|
12408
|
+
}
|
|
12409
|
+
return limits;
|
|
12410
|
+
}
|
|
12411
|
+
|
|
12412
|
+
// src/daemon.ts
|
|
11829
12413
|
var PRODUCTION_API_URL = "https://api.aiden-platform.com";
|
|
11830
12414
|
var PRODUCTION_WS_URL = "wss://ws.aiden-platform.com";
|
|
11831
12415
|
var LOCAL_API_URL = "http://localhost:8400";
|
|
@@ -11851,33 +12435,33 @@ function describeOccupiedLocalDaemon(port) {
|
|
|
11851
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.`;
|
|
11852
12436
|
}
|
|
11853
12437
|
function getConfigPath() {
|
|
11854
|
-
return process.env.AIDEN_AGENT_CONFIG_PATH ?? (0,
|
|
12438
|
+
return process.env.AIDEN_AGENT_CONFIG_PATH ?? (0, import_node_path4.join)((0, import_node_os4.homedir)(), ".aiden", "agent", "config.json");
|
|
11855
12439
|
}
|
|
11856
12440
|
function getEndpointDefaultsPath() {
|
|
11857
|
-
return process.env.AIDEN_AGENT_ENDPOINTS_PATH ?? (0,
|
|
12441
|
+
return process.env.AIDEN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path4.join)((0, import_node_path4.dirname)(getConfigPath()), "endpoints.json");
|
|
11858
12442
|
}
|
|
11859
12443
|
function readConfig() {
|
|
11860
12444
|
const configPath = getConfigPath();
|
|
11861
|
-
if (!(0,
|
|
11862
|
-
return JSON.parse((0,
|
|
12445
|
+
if (!(0, import_node_fs4.existsSync)(configPath)) return {};
|
|
12446
|
+
return JSON.parse((0, import_node_fs4.readFileSync)(configPath, "utf8"));
|
|
11863
12447
|
}
|
|
11864
12448
|
function readEndpointDefaults() {
|
|
11865
12449
|
const endpointsPath = getEndpointDefaultsPath();
|
|
11866
|
-
if (!(0,
|
|
12450
|
+
if (!(0, import_node_fs4.existsSync)(endpointsPath)) return {};
|
|
11867
12451
|
try {
|
|
11868
|
-
return JSON.parse((0,
|
|
12452
|
+
return JSON.parse((0, import_node_fs4.readFileSync)(endpointsPath, "utf8"));
|
|
11869
12453
|
} catch {
|
|
11870
12454
|
return {};
|
|
11871
12455
|
}
|
|
11872
12456
|
}
|
|
11873
12457
|
function writeConfig(config) {
|
|
11874
12458
|
const configPath = getConfigPath();
|
|
11875
|
-
(0,
|
|
11876
|
-
(0,
|
|
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 });
|
|
11877
12461
|
}
|
|
11878
12462
|
function removeConfig() {
|
|
11879
12463
|
const configPath = getConfigPath();
|
|
11880
|
-
if ((0,
|
|
12464
|
+
if ((0, import_node_fs4.existsSync)(configPath)) (0, import_node_fs4.rmSync)(configPath, { force: true });
|
|
11881
12465
|
}
|
|
11882
12466
|
function argValue(args, name) {
|
|
11883
12467
|
const index = args.indexOf(name);
|
|
@@ -11950,33 +12534,46 @@ function abortActiveAgent(entry) {
|
|
|
11950
12534
|
entry.agent.kill();
|
|
11951
12535
|
}
|
|
11952
12536
|
function collectRuntimeMetadata() {
|
|
11953
|
-
const cpuList = (0,
|
|
12537
|
+
const cpuList = (0, import_node_os4.cpus)();
|
|
11954
12538
|
const metadata = {
|
|
11955
|
-
platform: (0,
|
|
11956
|
-
arch: (0,
|
|
11957
|
-
osVersion: (0,
|
|
12539
|
+
platform: (0, import_node_os4.platform)(),
|
|
12540
|
+
arch: (0, import_node_os4.arch)(),
|
|
12541
|
+
osVersion: (0, import_node_os4.release)(),
|
|
11958
12542
|
agentVersion: AGENT_VERSION,
|
|
11959
|
-
memoryBytes: (0,
|
|
11960
|
-
memoryFreeBytes: (0,
|
|
12543
|
+
memoryBytes: (0, import_node_os4.totalmem)(),
|
|
12544
|
+
memoryFreeBytes: (0, import_node_os4.freemem)()
|
|
11961
12545
|
};
|
|
11962
12546
|
if (cpuList.length > 0) {
|
|
11963
12547
|
metadata.cpuModel = cpuList[0]?.model;
|
|
11964
12548
|
metadata.cpuCores = cpuList.length;
|
|
11965
12549
|
}
|
|
11966
12550
|
try {
|
|
11967
|
-
const disk = (0,
|
|
12551
|
+
const disk = (0, import_node_fs4.statfsSync)((0, import_node_os4.homedir)());
|
|
11968
12552
|
metadata.diskFreeBytes = disk.bavail * disk.bsize;
|
|
11969
12553
|
metadata.diskTotalBytes = disk.blocks * disk.bsize;
|
|
11970
12554
|
} catch {
|
|
11971
12555
|
}
|
|
11972
12556
|
return metadata;
|
|
11973
12557
|
}
|
|
12558
|
+
async function collectRuntimeMetadataWithProviderLimits() {
|
|
12559
|
+
const metadata = collectRuntimeMetadata();
|
|
12560
|
+
try {
|
|
12561
|
+
const agentProviderLimits = await collectLocalAgentProviderLimits(getDaemonCliEnvironment());
|
|
12562
|
+
if (Object.keys(agentProviderLimits).length > 0) {
|
|
12563
|
+
metadata.agentProviderLimits = agentProviderLimits;
|
|
12564
|
+
}
|
|
12565
|
+
} catch {
|
|
12566
|
+
}
|
|
12567
|
+
return metadata;
|
|
12568
|
+
}
|
|
11974
12569
|
var RuntimePresenter = class {
|
|
11975
|
-
constructor(socket, conversationId, runId) {
|
|
12570
|
+
constructor(socket, conversationId, runId, cwd) {
|
|
11976
12571
|
this.socket = socket;
|
|
11977
12572
|
this.conversationId = conversationId;
|
|
11978
12573
|
this.runId = runId;
|
|
12574
|
+
this.cwd = cwd;
|
|
11979
12575
|
}
|
|
12576
|
+
emittedGeneratedImageKeys = /* @__PURE__ */ new Set();
|
|
11980
12577
|
emitEvent(event) {
|
|
11981
12578
|
this.socket.emit("agent.event", {
|
|
11982
12579
|
conversationId: this.conversationId,
|
|
@@ -12007,6 +12604,19 @@ var RuntimePresenter = class {
|
|
|
12007
12604
|
ts: Date.now(),
|
|
12008
12605
|
...isError ? { is_error: true } : {}
|
|
12009
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);
|
|
12010
12620
|
}
|
|
12011
12621
|
onTurnComplete(content) {
|
|
12012
12622
|
this.emitEvent({ type: "turn_complete", content, ts: Date.now() });
|
|
@@ -12046,7 +12656,7 @@ async function setupDaemon(args) {
|
|
|
12046
12656
|
const teamId = argValue(args, "--team") ?? process.env.AIDEN_TEAM_ID;
|
|
12047
12657
|
const setupToken = argValue(args, "--setup-token") ?? process.env.AIDEN_RUNTIME_SETUP_TOKEN;
|
|
12048
12658
|
const token = argValue(args, "--token") ?? process.env.AIDEN_SETUP_TOKEN;
|
|
12049
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
12659
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os4.hostname)();
|
|
12050
12660
|
const legacyLocalMachineId = argValue(args, "--legacy-local-machine-id") ?? process.env.AIDEN_LEGACY_LOCAL_MACHINE_ID;
|
|
12051
12661
|
const scope = argValue(args, "--scope") ?? process.env.AIDEN_RUNTIME_SCOPE ?? "team";
|
|
12052
12662
|
if (scope !== "team" && scope !== "user") {
|
|
@@ -12067,7 +12677,7 @@ async function setupDaemon(args) {
|
|
|
12067
12677
|
...teamId ? { teamId } : {},
|
|
12068
12678
|
...setupToken ? { setupToken } : {},
|
|
12069
12679
|
displayName,
|
|
12070
|
-
hostname: (0,
|
|
12680
|
+
hostname: (0, import_node_os4.hostname)(),
|
|
12071
12681
|
...legacyLocalMachineId ? { legacyLocalMachineId } : {},
|
|
12072
12682
|
runtimeKind: "machine",
|
|
12073
12683
|
managementKind: "user_managed",
|
|
@@ -12076,7 +12686,7 @@ async function setupDaemon(args) {
|
|
|
12076
12686
|
ownerType: scope,
|
|
12077
12687
|
visibility: scope,
|
|
12078
12688
|
capabilities: discoverCapabilities(),
|
|
12079
|
-
metadata:
|
|
12689
|
+
metadata: await collectRuntimeMetadataWithProviderLimits()
|
|
12080
12690
|
})
|
|
12081
12691
|
});
|
|
12082
12692
|
if (!response.ok) {
|
|
@@ -12091,23 +12701,23 @@ async function setupDaemon(args) {
|
|
|
12091
12701
|
runtimeId: body.runtime.id,
|
|
12092
12702
|
runtimeToken: body.runtimeToken,
|
|
12093
12703
|
localApiPort: getLocalApiPort(args, {}),
|
|
12094
|
-
localApiToken: (0,
|
|
12704
|
+
localApiToken: (0, import_node_crypto2.randomBytes)(24).toString("hex"),
|
|
12095
12705
|
displayName: body.runtime.displayName ?? displayName
|
|
12096
12706
|
});
|
|
12097
12707
|
console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: getConfigPath() });
|
|
12098
12708
|
}
|
|
12099
12709
|
async function loginWithDeviceCode(args) {
|
|
12100
12710
|
const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
|
|
12101
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
12711
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os4.hostname)();
|
|
12102
12712
|
const maxPolls = Number.parseInt(argValue(args, "--max-polls") ?? "300", 10);
|
|
12103
12713
|
const start = await fetch(`${apiUrl}/public/runtimes/device-authorizations`, {
|
|
12104
12714
|
method: "POST",
|
|
12105
12715
|
headers: { "content-type": "application/json" },
|
|
12106
12716
|
body: JSON.stringify({
|
|
12107
12717
|
displayName,
|
|
12108
|
-
hostname: (0,
|
|
12718
|
+
hostname: (0, import_node_os4.hostname)(),
|
|
12109
12719
|
capabilities: discoverCapabilities(),
|
|
12110
|
-
metadata:
|
|
12720
|
+
metadata: await collectRuntimeMetadataWithProviderLimits()
|
|
12111
12721
|
})
|
|
12112
12722
|
});
|
|
12113
12723
|
if (!start.ok) {
|
|
@@ -12137,7 +12747,7 @@ async function loginWithDeviceCode(args) {
|
|
|
12137
12747
|
runtimeId: body.runtime.id,
|
|
12138
12748
|
runtimeToken: body.runtimeToken,
|
|
12139
12749
|
localApiPort: getLocalApiPort(args, {}),
|
|
12140
|
-
localApiToken: (0,
|
|
12750
|
+
localApiToken: (0, import_node_crypto2.randomBytes)(24).toString("hex"),
|
|
12141
12751
|
displayName: body.runtime.displayName ?? displayName
|
|
12142
12752
|
});
|
|
12143
12753
|
console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: getConfigPath() });
|
|
@@ -12151,13 +12761,13 @@ async function startDaemon(args) {
|
|
|
12151
12761
|
const runtimeToken = argValue(args, "--token") ?? process.env.AIDEN_RUNTIME_TOKEN ?? stored.runtimeToken;
|
|
12152
12762
|
const wsUrl = argValue(args, "--ws-url") ?? process.env.AIDEN_WS_URL ?? stored.wsUrl;
|
|
12153
12763
|
let localApiPort = getLocalApiPort(args, stored);
|
|
12154
|
-
const localApiToken = stored.localApiToken ?? (0,
|
|
12764
|
+
const localApiToken = stored.localApiToken ?? (0, import_node_crypto2.randomBytes)(24).toString("hex");
|
|
12155
12765
|
if (!runtimeId || !runtimeToken || !wsUrl) {
|
|
12156
12766
|
throw new Error("daemon requires runtimeId, runtime token, and wsUrl. Run setup first or pass --runtime-id/--token/--ws-url.");
|
|
12157
12767
|
}
|
|
12158
12768
|
const activeAgents = /* @__PURE__ */ new Map();
|
|
12159
12769
|
const currentCapabilities = () => discoverCapabilities();
|
|
12160
|
-
const currentMetadata = () =>
|
|
12770
|
+
const currentMetadata = () => collectRuntimeMetadataWithProviderLimits();
|
|
12161
12771
|
const recentLogs = [];
|
|
12162
12772
|
const pushLog = (message) => {
|
|
12163
12773
|
recentLogs.push(`${(/* @__PURE__ */ new Date()).toISOString()} ${message}`);
|
|
@@ -12179,12 +12789,17 @@ async function startDaemon(args) {
|
|
|
12179
12789
|
extraHeaders: { "ngrok-skip-browser-warning": "1" }
|
|
12180
12790
|
});
|
|
12181
12791
|
const heartbeat = setInterval(() => {
|
|
12182
|
-
if (socket.connected)
|
|
12792
|
+
if (!socket.connected) return;
|
|
12793
|
+
void currentMetadata().then((metadata) => {
|
|
12794
|
+
socket.emit("runtime.heartbeat", { capabilities: currentCapabilities(), metadata });
|
|
12795
|
+
});
|
|
12183
12796
|
}, 15e3);
|
|
12184
12797
|
socket.on("connect", () => {
|
|
12185
12798
|
pushLog(`connected runtime=${runtimeId}`);
|
|
12186
12799
|
console.info("[aiden-agent] Daemon connected", { runtimeId, wsUrl, version: AGENT_VERSION });
|
|
12187
|
-
|
|
12800
|
+
void currentMetadata().then((metadata) => {
|
|
12801
|
+
socket.emit("runtime.hello", { capabilities: currentCapabilities(), metadata });
|
|
12802
|
+
});
|
|
12188
12803
|
});
|
|
12189
12804
|
let lastConnectErrorLogAt = 0;
|
|
12190
12805
|
socket.on("connect_error", (error) => {
|
|
@@ -12218,13 +12833,13 @@ async function startDaemon(args) {
|
|
|
12218
12833
|
}
|
|
12219
12834
|
socket.emit("agent.accepted", { runId: payload.runId });
|
|
12220
12835
|
pushLog(`accepted run=${payload.runId}`);
|
|
12221
|
-
const
|
|
12836
|
+
const cwd = payload.projectPath ?? process.cwd();
|
|
12837
|
+
const presenter = new RuntimePresenter(socket, payload.conversationId, payload.runId, cwd);
|
|
12222
12838
|
const agent = new CoreAgent(presenter, {
|
|
12223
12839
|
backendKind,
|
|
12224
12840
|
runtimeCommand,
|
|
12225
12841
|
providerApiKey: payload.providerApiKey
|
|
12226
12842
|
});
|
|
12227
|
-
const cwd = payload.projectPath ?? process.cwd();
|
|
12228
12843
|
activeAgents.set(payload.runId, { agent, presenter });
|
|
12229
12844
|
void agent.run({
|
|
12230
12845
|
task: payload.content,
|
|
@@ -12241,6 +12856,7 @@ async function startDaemon(args) {
|
|
|
12241
12856
|
selectedEffortLevel: payload.selectedEffortLevel ?? null,
|
|
12242
12857
|
providerSessionId: payload.providerSessionId,
|
|
12243
12858
|
taskMeta: payload.taskMeta,
|
|
12859
|
+
prMeta: payload.prMeta,
|
|
12244
12860
|
conversationId: payload.conversationId,
|
|
12245
12861
|
taskId: payload.taskMeta?.id,
|
|
12246
12862
|
teamId: payload.teamId,
|
|
@@ -12532,7 +13148,7 @@ async function printDoctor(args = []) {
|
|
|
12532
13148
|
authorization: `Bearer ${config.runtimeToken}`,
|
|
12533
13149
|
"content-type": "application/json"
|
|
12534
13150
|
},
|
|
12535
|
-
body: JSON.stringify({ capabilities, metadata:
|
|
13151
|
+
body: JSON.stringify({ capabilities, metadata: await collectRuntimeMetadataWithProviderLimits() })
|
|
12536
13152
|
});
|
|
12537
13153
|
if (!response.ok) {
|
|
12538
13154
|
syncError = `${response.status} ${await response.text()}`;
|