@aiden-ade/sandbox-agent 0.1.33 → 0.1.35
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 +322 -208
- package/package.json +9 -5
package/dist/index.cjs
CHANGED
|
@@ -4810,14 +4810,23 @@ var require_websocket_server = __commonJS({
|
|
|
4810
4810
|
}
|
|
4811
4811
|
});
|
|
4812
4812
|
|
|
4813
|
+
// src/legacy-env.ts
|
|
4814
|
+
for (const [key, value2] of Object.entries(process.env)) {
|
|
4815
|
+
if (!key.startsWith("ALAN_") || value2 === void 0) continue;
|
|
4816
|
+
const alanKey = `ALAN_${key.slice("ALAN_".length)}`;
|
|
4817
|
+
if (process.env[alanKey] === void 0 || process.env[alanKey] === "") {
|
|
4818
|
+
process.env[alanKey] = value2;
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
|
|
4813
4822
|
// src/cli-help.ts
|
|
4814
|
-
var HELP_TEXT = `
|
|
4823
|
+
var HELP_TEXT = `Alan agent CLI
|
|
4815
4824
|
|
|
4816
4825
|
Usage:
|
|
4817
|
-
|
|
4826
|
+
alan-agent <command> [options]
|
|
4818
4827
|
|
|
4819
4828
|
Commands:
|
|
4820
|
-
setup Register this computer with a setup token from
|
|
4829
|
+
setup Register this computer with a setup token from Alan
|
|
4821
4830
|
login Register this computer through browser authorization
|
|
4822
4831
|
daemon Start the durable runtime daemon
|
|
4823
4832
|
stop Stop the local daemon (or active runs only via the local API /stop)
|
|
@@ -4826,22 +4835,22 @@ Commands:
|
|
|
4826
4835
|
scan-models Probe installed agent CLIs and print discovered models
|
|
4827
4836
|
logout Remove local runtime configuration
|
|
4828
4837
|
token Rotate or revoke the configured runtime token
|
|
4829
|
-
run-session Internal: run one ephemeral sandbox/session from
|
|
4838
|
+
run-session Internal: run one ephemeral sandbox/session from ALAN_* env vars
|
|
4830
4839
|
|
|
4831
4840
|
Common flows:
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4841
|
+
alan-agent login
|
|
4842
|
+
alan-agent setup --setup-token <token>
|
|
4843
|
+
alan-agent setup --setup-token <token> --scope user
|
|
4844
|
+
alan-agent daemon
|
|
4845
|
+
alan-agent stop
|
|
4837
4846
|
|
|
4838
4847
|
Local development:
|
|
4839
|
-
|
|
4840
|
-
|
|
4848
|
+
alan-agent login --profile local
|
|
4849
|
+
alan-agent setup --profile local --setup-token <token>
|
|
4841
4850
|
`;
|
|
4842
4851
|
function hasRunSessionEnv(env) {
|
|
4843
4852
|
return Boolean(
|
|
4844
|
-
env.
|
|
4853
|
+
env.ALAN_WS_URL && env.ALAN_SESSION_ID && env.ALAN_TASK_ID && env.ALAN_SESSION_TOKEN && env.ALAN_TASK !== void 0
|
|
4845
4854
|
);
|
|
4846
4855
|
}
|
|
4847
4856
|
function resolveCommand(args, env) {
|
|
@@ -4986,7 +4995,7 @@ async function withTimeout(promise, timeoutMs, fallback) {
|
|
|
4986
4995
|
}
|
|
4987
4996
|
async function collectCodexLimits(env) {
|
|
4988
4997
|
const runtimeEnv = augmentCliPath(env);
|
|
4989
|
-
const codexCommand = resolveExecutable("codex", runtimeEnv, "
|
|
4998
|
+
const codexCommand = resolveExecutable("codex", runtimeEnv, "ALAN_CODEX_PATH");
|
|
4990
4999
|
if (!codexCommand)
|
|
4991
5000
|
return [];
|
|
4992
5001
|
return withTimeout(new Promise((resolve3) => {
|
|
@@ -5040,7 +5049,7 @@ async function collectCodexLimits(env) {
|
|
|
5040
5049
|
void (async () => {
|
|
5041
5050
|
try {
|
|
5042
5051
|
await request("initialize", {
|
|
5043
|
-
clientInfo: { name: "
|
|
5052
|
+
clientInfo: { name: "alan", version: "runtime" }
|
|
5044
5053
|
});
|
|
5045
5054
|
child.stdin.write(`${JSON.stringify({ method: "initialized", params: {} })}
|
|
5046
5055
|
`);
|
|
@@ -12870,28 +12879,28 @@ var import_node_fs2 = require("fs");
|
|
|
12870
12879
|
var import_node_os2 = require("os");
|
|
12871
12880
|
var import_node_path2 = require("path");
|
|
12872
12881
|
var PROVIDER_CLI_COMMANDS = {
|
|
12873
|
-
claude_cli: { provider: "claude_cli", command: "claude", envVars: ["
|
|
12882
|
+
claude_cli: { provider: "claude_cli", command: "claude", envVars: ["ALAN_CLAUDE_PATH"] },
|
|
12874
12883
|
codex_app_server: {
|
|
12875
12884
|
provider: "codex_app_server",
|
|
12876
12885
|
command: "codex",
|
|
12877
|
-
envVars: ["
|
|
12886
|
+
envVars: ["ALAN_CODEX_PATH"]
|
|
12878
12887
|
},
|
|
12879
|
-
copilot_cli: { provider: "copilot_cli", command: "copilot", envVars: ["
|
|
12888
|
+
copilot_cli: { provider: "copilot_cli", command: "copilot", envVars: ["ALAN_COPILOT_PATH"] },
|
|
12880
12889
|
cursor_agent_cli: {
|
|
12881
12890
|
provider: "cursor_agent_cli",
|
|
12882
12891
|
command: "cursor-agent",
|
|
12883
|
-
envVars: ["
|
|
12892
|
+
envVars: ["ALAN_CURSOR_AGENT_PATH"]
|
|
12884
12893
|
},
|
|
12885
12894
|
antigravity_cli: {
|
|
12886
12895
|
provider: "antigravity_cli",
|
|
12887
12896
|
command: "agy",
|
|
12888
|
-
envVars: ["
|
|
12897
|
+
envVars: ["ALAN_ANTIGRAVITY_PATH"]
|
|
12889
12898
|
},
|
|
12890
|
-
kimi_cli: { provider: "kimi_cli", command: "kimi-cli", envVars: ["
|
|
12891
|
-
grok_cli: { provider: "grok_cli", command: "grok", envVars: ["
|
|
12892
|
-
opencode_cli: { provider: "opencode_cli", command: "opencode", envVars: ["
|
|
12893
|
-
droid_cli: { provider: "droid_cli", command: "droid", envVars: ["
|
|
12894
|
-
supatest_cli: { provider: "supatest_cli", command: "supatest", envVars: ["
|
|
12899
|
+
kimi_cli: { provider: "kimi_cli", command: "kimi-cli", envVars: ["ALAN_KIMI_PATH"] },
|
|
12900
|
+
grok_cli: { provider: "grok_cli", command: "grok", envVars: ["ALAN_GROK_PATH"] },
|
|
12901
|
+
opencode_cli: { provider: "opencode_cli", command: "opencode", envVars: ["ALAN_OPENCODE_PATH"] },
|
|
12902
|
+
droid_cli: { provider: "droid_cli", command: "droid", envVars: ["ALAN_DROID_PATH"] },
|
|
12903
|
+
supatest_cli: { provider: "supatest_cli", command: "supatest", envVars: ["ALAN_SUPATEST_PATH"] }
|
|
12895
12904
|
};
|
|
12896
12905
|
var DISCOVERABLE_PROVIDER_KINDS = Object.keys(PROVIDER_CLI_COMMANDS);
|
|
12897
12906
|
var PROVIDER_ALIASES = {
|
|
@@ -13177,7 +13186,7 @@ var import_node_fs4 = require("fs");
|
|
|
13177
13186
|
var import_node_fs3 = require("fs");
|
|
13178
13187
|
var import_node_os3 = require("os");
|
|
13179
13188
|
var import_node_path3 = require("path");
|
|
13180
|
-
var DEFAULT_AGENT_DIR = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".
|
|
13189
|
+
var DEFAULT_AGENT_DIR = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".alan", "agent");
|
|
13181
13190
|
function resolveAgentConfigPath(input) {
|
|
13182
13191
|
if (input?.explicitPath?.trim()) return input.explicitPath.trim();
|
|
13183
13192
|
const profile = normalizeAgentEndpointProfile(
|
|
@@ -13191,15 +13200,15 @@ function configExistsAtPath(configPath) {
|
|
|
13191
13200
|
}
|
|
13192
13201
|
function resolveEndpointProfileFromArgs(args) {
|
|
13193
13202
|
const index = args.indexOf("--profile");
|
|
13194
|
-
const raw = index === -1 ? process.env.
|
|
13203
|
+
const raw = index === -1 ? process.env.ALAN_AGENT_PROFILE : args[index + 1];
|
|
13195
13204
|
return normalizeAgentEndpointProfile(raw) ?? "production";
|
|
13196
13205
|
}
|
|
13197
13206
|
function bindAgentConfigPathFromArgs(args) {
|
|
13198
|
-
const explicit = process.env.
|
|
13207
|
+
const explicit = process.env.ALAN_AGENT_CONFIG_PATH?.trim();
|
|
13199
13208
|
if (explicit) return explicit;
|
|
13200
13209
|
const profile = resolveEndpointProfileFromArgs(args);
|
|
13201
13210
|
const configPath = resolveAgentConfigPath({ profile });
|
|
13202
|
-
process.env.
|
|
13211
|
+
process.env.ALAN_AGENT_CONFIG_PATH = configPath;
|
|
13203
13212
|
return configPath;
|
|
13204
13213
|
}
|
|
13205
13214
|
|
|
@@ -13270,7 +13279,7 @@ function buildComputerReadiness(input) {
|
|
|
13270
13279
|
check(
|
|
13271
13280
|
"ws_connected",
|
|
13272
13281
|
input.connected ? "pass" : "fail",
|
|
13273
|
-
input.connected ? "Daemon is connected to
|
|
13282
|
+
input.connected ? "Daemon is connected to Alan backend." : "Daemon is disconnected from Alan backend.",
|
|
13274
13283
|
{
|
|
13275
13284
|
nowMs,
|
|
13276
13285
|
code: input.connected ? void 0 : "ws_disconnected",
|
|
@@ -13329,7 +13338,7 @@ Before create_task:
|
|
|
13329
13338
|
// ../shared/dist/agent/agent-definitions.js
|
|
13330
13339
|
var COORDINATOR_PROMPT = `## You are the Orchestrator
|
|
13331
13340
|
|
|
13332
|
-
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
|
|
13341
|
+
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 Alan" alone; say "I'm the Orchestrator (an Alan agent profile) for this task."
|
|
13333
13342
|
|
|
13334
13343
|
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.
|
|
13335
13344
|
|
|
@@ -13390,7 +13399,7 @@ You are coordination-first, not read-only. Use judgment: act directly for focuse
|
|
|
13390
13399
|
${TASK_CREATE_FIND_BEFORE_CREATE_INSTRUCTIONS}`;
|
|
13391
13400
|
var PM_PROMPT = `## You are the PM Agent
|
|
13392
13401
|
|
|
13393
|
-
You are the **PM Agent** (Product Manager) for this task. When identifying yourself, say "I'm the PM Agent (an
|
|
13402
|
+
You are the **PM Agent** (Product Manager) for this task. When identifying yourself, say "I'm the PM Agent (an Alan agent profile)."
|
|
13394
13403
|
|
|
13395
13404
|
Your job is product thinking, not implementation. You own requirements, scope, and prioritization. You do not write code or edit files.
|
|
13396
13405
|
|
|
@@ -13448,9 +13457,9 @@ Every \`start_task_session\` message must include all four of these:
|
|
|
13448
13457
|
5. Track results and update task status as work completes.`;
|
|
13449
13458
|
var GENERAL_PROMPT = `## You are the General Agent
|
|
13450
13459
|
|
|
13451
|
-
You are a flexible general-purpose agent (an
|
|
13460
|
+
You are a flexible general-purpose agent (an Alan agent profile) for work that does not need a specialist profile. Wear whatever hat the moment demands \u2014 product thinker, planner, programmer, debugger, tester. Read the room and pick the hat.
|
|
13452
13461
|
|
|
13453
|
-
Your name is
|
|
13462
|
+
Your name is Alan, General Agent.
|
|
13454
13463
|
|
|
13455
13464
|
Clarify the goal only when required, inspect the relevant context first, then complete the requested work directly. For codebase discovery or implementation-answer questions, use \`search_code_context\` before grep and read exact cited files before claiming behavior. Keep changes focused, avoid unrelated refactors, and validate the result before reporting back.
|
|
13456
13465
|
|
|
@@ -13468,23 +13477,23 @@ ${TASK_CREATE_FIND_BEFORE_CREATE_INSTRUCTIONS}
|
|
|
13468
13477
|
- Any residual risk or open question`;
|
|
13469
13478
|
var BUDDY_PROMPT = `## You are Buddy
|
|
13470
13479
|
|
|
13471
|
-
You are **Buddy** (an
|
|
13480
|
+
You are **Buddy** (an Alan agent profile) for direct team chat. When identifying yourself, say "I'm Buddy, the direct chat agent in Alan."
|
|
13472
13481
|
|
|
13473
13482
|
Your job is to be the user's always-available teammate: answer questions, inspect context, help shape ambiguous ideas, and take focused implementation or coordination action when the user asks.
|
|
13474
13483
|
|
|
13475
13484
|
## How to work
|
|
13476
13485
|
|
|
13477
13486
|
1. Start from the current team/chat context before asking for details.
|
|
13478
|
-
2. For codebase location, behavior, or implementation-answer questions, call \`search_code_context\` via
|
|
13487
|
+
2. For codebase location, behavior, or implementation-answer questions, call \`search_code_context\` via Alan MCP before grep or filesystem search, then read the exact cited files before claiming behavior.
|
|
13479
13488
|
3. Clarify only when the request has multiple plausible meanings.
|
|
13480
13489
|
4. Keep responses concise, concrete, and tied to the user's next step.
|
|
13481
13490
|
5. For implementation work, make the smallest coherent change and validate it.
|
|
13482
|
-
6. For plans, PRDs, reviews, and test reports, use structured
|
|
13491
|
+
6. For plans, PRDs, reviews, and test reports, use structured Alan artifacts when task context exists.
|
|
13483
13492
|
|
|
13484
13493
|
## Primary tools (code discovery)
|
|
13485
13494
|
|
|
13486
|
-
- \`
|
|
13487
|
-
- \`
|
|
13495
|
+
- \`mcp__alan__search_code_context\` / \`search_code_context\` \u2014 find where code lives or how behavior is implemented (**use this first**)
|
|
13496
|
+
- \`mcp__alan__code_context_status\` \u2014 confirm the team index is ready
|
|
13488
13497
|
- \`Read\`, \`Grep\` \u2014 only after you have paths from the index, or for line-level edits in known files; read exact cited files before answering exact questions
|
|
13489
13498
|
- Do **not** run repo-wide \`grep\` / \`rg\` / Bash find for "where is X" or "how does this work" questions when MCP code-context tools are available
|
|
13490
13499
|
|
|
@@ -13498,7 +13507,7 @@ Your job is to be the user's always-available teammate: answer questions, inspec
|
|
|
13498
13507
|
${TASK_CREATE_FIND_BEFORE_CREATE_INSTRUCTIONS}`;
|
|
13499
13508
|
var REVIEW_PROMPT = `## You are the Review Agent
|
|
13500
13509
|
|
|
13501
|
-
You are the **Review Agent** (an
|
|
13510
|
+
You are the **Review Agent** (an Alan agent profile) for pull request review sessions. When identifying yourself, say "I'm the Review Agent."
|
|
13502
13511
|
|
|
13503
13512
|
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.
|
|
13504
13513
|
|
|
@@ -13519,7 +13528,7 @@ Your job is to inspect the pull request context, reason about correctness and ri
|
|
|
13519
13528
|
- Ask one targeted question only when evidence is missing and blocks a useful review.`;
|
|
13520
13529
|
var IMPLEMENTOR_PROMPT = `## You are the Implementor Agent
|
|
13521
13530
|
|
|
13522
|
-
You are a senior implementation agent responsible for end-to-end code delivery. When identifying yourself, say "I'm the Implementor Agent (an
|
|
13531
|
+
You are a senior implementation agent responsible for end-to-end code delivery. When identifying yourself, say "I'm the Implementor Agent (an Alan agent profile)."
|
|
13523
13532
|
|
|
13524
13533
|
Workflow: Listen \u2192 Understand \u2192 Break down \u2192 Plan \u2192 Build \u2192 Test \u2192 Ship.
|
|
13525
13534
|
|
|
@@ -13532,7 +13541,7 @@ Workflow: Listen \u2192 Understand \u2192 Break down \u2192 Plan \u2192 Build \u
|
|
|
13532
13541
|
|
|
13533
13542
|
## Primary tools
|
|
13534
13543
|
|
|
13535
|
-
- \`
|
|
13544
|
+
- \`mcp__alan__search_code_context\` / \`search_code_context\` \u2014 find where code lives or how behavior is implemented (use BEFORE grep for discovery and implementation-answer questions)
|
|
13536
13545
|
- \`Read\`, \`Glob\`, \`Grep\` \u2014 read exact cited files or narrow search after you have paths from the index
|
|
13537
13546
|
- \`Edit\`, \`Write\` \u2014 make changes; prefer \`Edit\` over \`Write\` for existing files
|
|
13538
13547
|
- \`Bash\` \u2014 run type-checks, tests, and read-only commands; never skip validation
|
|
@@ -13553,7 +13562,7 @@ Workflow: Listen \u2192 Understand \u2192 Break down \u2192 Plan \u2192 Build \u
|
|
|
13553
13562
|
- **Residual risk**: anything that could break or needs follow-up`;
|
|
13554
13563
|
var DESIGNER_PROMPT = `## You are the Designer Agent
|
|
13555
13564
|
|
|
13556
|
-
You are a product UI designer and frontend interaction specialist. When identifying yourself, say "I'm the Designer Agent (an
|
|
13565
|
+
You are a product UI designer and frontend interaction specialist. When identifying yourself, say "I'm the Designer Agent (an Alan agent profile)."
|
|
13557
13566
|
|
|
13558
13567
|
## Taste Skill (premium frontends)
|
|
13559
13568
|
|
|
@@ -13787,9 +13796,9 @@ function isBrowserRecordingToolName(toolName) {
|
|
|
13787
13796
|
}
|
|
13788
13797
|
|
|
13789
13798
|
// ../shared/dist/agent/mcp-config.js
|
|
13790
|
-
function
|
|
13799
|
+
function buildAlanMcpServers(registration) {
|
|
13791
13800
|
return {
|
|
13792
|
-
|
|
13801
|
+
alan: {
|
|
13793
13802
|
type: "http",
|
|
13794
13803
|
url: registration.url,
|
|
13795
13804
|
...Object.keys(registration.headers).length > 0 ? { headers: registration.headers } : {}
|
|
@@ -13904,7 +13913,7 @@ function toCodexMcpToml(src) {
|
|
|
13904
13913
|
return `${lines.join("\n").trim()}
|
|
13905
13914
|
`;
|
|
13906
13915
|
}
|
|
13907
|
-
function
|
|
13916
|
+
function renderAlanMcpConfigFiles(mcpServers, home) {
|
|
13908
13917
|
return [
|
|
13909
13918
|
{
|
|
13910
13919
|
path: `${home}/.claude.json`,
|
|
@@ -13931,8 +13940,8 @@ function renderAidenMcpConfigFiles(mcpServers, home) {
|
|
|
13931
13940
|
}
|
|
13932
13941
|
];
|
|
13933
13942
|
}
|
|
13934
|
-
function
|
|
13935
|
-
const all =
|
|
13943
|
+
function alanMcpConfigFilesForBackend(backendKind, mcpServers, home) {
|
|
13944
|
+
const all = renderAlanMcpConfigFiles(mcpServers, home);
|
|
13936
13945
|
const byPathSuffix = (...suffixes) => all.filter((f) => suffixes.some((s) => f.path.endsWith(s)));
|
|
13937
13946
|
switch (backendKind) {
|
|
13938
13947
|
case "claude_cli":
|
|
@@ -13957,15 +13966,15 @@ function aidenMcpConfigFilesForBackend(backendKind, mcpServers, home) {
|
|
|
13957
13966
|
var SESSION_RESUME_FAILED_MESSAGE = "Session resume failed. The previous session may have expired or is no longer available. Please start a new session.";
|
|
13958
13967
|
|
|
13959
13968
|
// ../shared/dist/agent/system-prompt.js
|
|
13960
|
-
var
|
|
13969
|
+
var ALAN_IDENTITY_PROMPT = `You are Alan, the software factory agent built by Supatest in Bangalore. Alan ships software end to end \u2014 plan, write, review, test, deploy.
|
|
13961
13970
|
|
|
13962
|
-
Do not present yourself as a runtime model, CLI, or backend vendor as your primary identity \u2014 those are runtime details. Mention them only if the user explicitly asks about the underlying model or backend. If the user asks who you are, answer in
|
|
13971
|
+
Do not present yourself as a runtime model, CLI, or backend vendor as your primary identity \u2014 those are runtime details. Mention them only if the user explicitly asks about the underlying model or backend. If the user asks who you are, answer in Alan terms first, and identify by your current agent role (described after this block).
|
|
13963
13972
|
|
|
13964
13973
|
## Voice
|
|
13965
13974
|
|
|
13966
13975
|
Direct. Structured. Concise. No hype, no "Great question!", no tool-brand roleplay. Speak like a teammate, not a data dump. Precise and decisive when working a task; listen, think, then act.
|
|
13967
13976
|
|
|
13968
|
-
## How
|
|
13977
|
+
## How Alan is structured
|
|
13969
13978
|
|
|
13970
13979
|
\`\`\`
|
|
13971
13980
|
Team
|
|
@@ -13983,7 +13992,7 @@ Team
|
|
|
13983
13992
|
|
|
13984
13993
|
## Structure over chat
|
|
13985
13994
|
|
|
13986
|
-
Deliverables persist as
|
|
13995
|
+
Deliverables persist as Alan artifacts and documents \u2014 not as chat. Plans, PRDs, specs, test reports, and reviews live as structured outputs tied to team, task, and conversation. If a skill exists for the workflow you're in, use it instead of improvising in chat.
|
|
13987
13996
|
|
|
13988
13997
|
## Universal teammate principles
|
|
13989
13998
|
|
|
@@ -13999,13 +14008,13 @@ Deliverables persist as Aiden artifacts and documents \u2014 not as chat. Plans,
|
|
|
13999
14008
|
For non-trivial tasks, log high-signal events as they happen: decisions, changed assumptions, validation results, known-good IDs, blockers, risks, and direction changes. Keep one current task-state summary updated with current state, known-good IDs, open risks, and next action. Do not log routine commands or file reads. Before stopping, ensure the timeline and current state are enough for a human to understand progress and for another agent to resume. If a prior decision is stale, write a newer event that supersedes it.
|
|
14000
14009
|
|
|
14001
14010
|
The specific work you do \u2014 implementation, planning, review, coordination, verification \u2014 is determined by your agent role, described next.`;
|
|
14002
|
-
var
|
|
14011
|
+
var ALAN_ASK_USER_PROMPT = `## Asking the user
|
|
14003
14012
|
|
|
14004
|
-
When you need a decision or information only the user can provide, do not guess \u2014 ask with an interactive ask tool so
|
|
14013
|
+
When you need a decision or information only the user can provide, do not guess \u2014 ask with an interactive ask tool so Alan can render clickable question cards.
|
|
14005
14014
|
|
|
14006
14015
|
### Tool preference (required)
|
|
14007
14016
|
1. Prefer the **native** ask tool when it appears in your tool list (\`AskUserQuestion\`, or the backend's equivalent built-in ask tool).
|
|
14008
|
-
2. Only if native ask is missing, call \`
|
|
14017
|
+
2. Only if native ask is missing, call \`mcp__alan__ask_user_question\` (server tool name: \`ask_user_question\`).
|
|
14009
14018
|
|
|
14010
14019
|
Required arguments (both native and MCP forms):
|
|
14011
14020
|
- \`questions\`: non-empty array. Each item needs a clear \`question\` string.
|
|
@@ -14024,22 +14033,22 @@ If neither native ask nor the MCP ask tool is available, ask ONE short plain-tex
|
|
|
14024
14033
|
|
|
14025
14034
|
### After the tool call
|
|
14026
14035
|
The ask tool returns an empty/ack result and does NOT wait. Immediately end your turn. At most one short line like "Please pick an option above." \u2014 no restating the full questions in markdown. The user's answer (or skip) arrives as the next user message; continue from there.`;
|
|
14027
|
-
function
|
|
14036
|
+
function buildAlanTeamScopePrompt(teamId) {
|
|
14028
14037
|
return [
|
|
14029
14038
|
`You are operating within team \`${teamId}\`.`,
|
|
14030
14039
|
"Use this teamId for MCP tools that accept it (search, list_tasks, search_code_context, etc.).",
|
|
14031
|
-
"On code-context tools, teamId auto-resolves from the
|
|
14040
|
+
"On code-context tools, teamId auto-resolves from the Alan session when omitted \u2014 never invent or guess a teamId.",
|
|
14032
14041
|
"Do not call list_teams."
|
|
14033
14042
|
].join(" ");
|
|
14034
14043
|
}
|
|
14035
|
-
var
|
|
14044
|
+
var ALAN_CODE_CONTEXT_PROMPT = `## Codebase index (required for code discovery)
|
|
14036
14045
|
|
|
14037
|
-
This team has an indexed codebase. For questions about where code lives, how something works, how to answer from the codebase, or which files to read, use
|
|
14046
|
+
This team has an indexed codebase. For questions about where code lives, how something works, how to answer from the codebase, or which files to read, use Alan MCP code-context tools BEFORE local grep/find/bash search.
|
|
14038
14047
|
|
|
14039
14048
|
### Required path for codebase questions
|
|
14040
14049
|
Examples: "where is X configured", "which file handles Y", "how does Z work", "find code that \u2026", "why does this behavior happen?"
|
|
14041
|
-
1. Call \`
|
|
14042
|
-
2. Optionally call \`
|
|
14050
|
+
1. Call \`mcp__alan__search_code_context\` (MCP tool: \`search_code_context\`) with hybrid mode and topK 5.
|
|
14051
|
+
2. Optionally call \`mcp__alan__code_context_status\` first when unsure indexing is ready.
|
|
14043
14052
|
3. Use the result citations to choose exact paths, then \`Read\` those files before making claims, proposing edits, or changing code.
|
|
14044
14053
|
4. For exact symbols, constants, routes, schema fields, or line-level behavior, verify in the cited file with \`Read\` or narrow \`Grep\` before answering.
|
|
14045
14054
|
|
|
@@ -14053,20 +14062,20 @@ Examples: "where is X configured", "which file handles Y", "how does Z work", "f
|
|
|
14053
14062
|
- Current breakage: \`code_lsp_diagnostics\` when available.
|
|
14054
14063
|
|
|
14055
14064
|
If search returns no strong matches, say so and try one targeted local search in the most likely package \u2014 not repo-wide grep.`;
|
|
14056
|
-
function
|
|
14057
|
-
return [
|
|
14065
|
+
function buildAlanTeamCodeContextOverlay(teamId) {
|
|
14066
|
+
return [buildAlanTeamScopePrompt(teamId), ALAN_CODE_CONTEXT_PROMPT].join("\n\n");
|
|
14058
14067
|
}
|
|
14059
14068
|
function buildCodeDiscoveryEnforcementTail() {
|
|
14060
14069
|
return [
|
|
14061
14070
|
"## MANDATORY \u2014 team code index (do this before Grep/graphify)",
|
|
14062
|
-
"1. For codebase discovery or implementation-answer questions, call `
|
|
14063
|
-
"2. Optionally `
|
|
14071
|
+
"1. For codebase discovery or implementation-answer questions, call `mcp__alan__search_code_context` (hybrid, topK 5). Omit teamId \u2014 Alan session headers resolve it.",
|
|
14072
|
+
"2. Optionally `mcp__alan__code_context_status` if indexing readiness is unclear.",
|
|
14064
14073
|
"3. Read the exact cited files before answering, claiming behavior, or editing code; use narrow `Grep` only inside known paths.",
|
|
14065
14074
|
"Repo-wide grep, graphify, or Bash find **before** MCP on discovery/implementation-answer questions fails the task."
|
|
14066
14075
|
].join("\n");
|
|
14067
14076
|
}
|
|
14068
14077
|
var PLAN_MODE_PROMPT = [
|
|
14069
|
-
"You are in
|
|
14078
|
+
"You are in Alan plan mode.",
|
|
14070
14079
|
"Analyze the task, inspect the relevant code and context, and produce a concrete implementation plan.",
|
|
14071
14080
|
"Do not make code changes or execute write operations in plan mode.",
|
|
14072
14081
|
"Write the plan in natural markdown. Use whatever structure best communicates the work clearly.",
|
|
@@ -14083,7 +14092,7 @@ var TEST_MODE_PROMPT = [
|
|
|
14083
14092
|
].join("\n");
|
|
14084
14093
|
var ASK_MODE_PROMPT = "You are in ask mode. Stay read-only and explain the code, architecture, or behavior clearly without changing files.";
|
|
14085
14094
|
var REVIEW_MODE_PROMPT = "You are in review mode. Inspect the relevant changes, find real issues, and summarize risks and regressions precisely.";
|
|
14086
|
-
function
|
|
14095
|
+
function getAlanModePrompt(mode) {
|
|
14087
14096
|
switch (mode) {
|
|
14088
14097
|
case "plan":
|
|
14089
14098
|
return PLAN_MODE_PROMPT;
|
|
@@ -14097,7 +14106,7 @@ function getAidenModePrompt(mode) {
|
|
|
14097
14106
|
return void 0;
|
|
14098
14107
|
}
|
|
14099
14108
|
}
|
|
14100
|
-
function
|
|
14109
|
+
function getAlanAgentPrompt(agentId) {
|
|
14101
14110
|
return getAgentSystemPrompt(agentId);
|
|
14102
14111
|
}
|
|
14103
14112
|
|
|
@@ -14689,6 +14698,7 @@ function baseCatalogForProvider(providerKind) {
|
|
|
14689
14698
|
}
|
|
14690
14699
|
return staticCatalog;
|
|
14691
14700
|
}
|
|
14701
|
+
var PROVIDER_MODEL_INFERENCE_IDS = Object.keys(PROVIDER_MODELS).filter((providerId) => providerId !== "antigravity_cli");
|
|
14692
14702
|
function catalogModelsForProvider(providerKind, modelsFromConfig) {
|
|
14693
14703
|
const catalog = baseCatalogForProvider(providerKind);
|
|
14694
14704
|
if (!modelsFromConfig)
|
|
@@ -14721,8 +14731,11 @@ function normalizeToolName2(name) {
|
|
|
14721
14731
|
const mcp = lower.match(/^mcp__[a-z0-9-]+__(.+)$/);
|
|
14722
14732
|
let bare = mcp ? mcp[1] : lower;
|
|
14723
14733
|
bare = bare.replace(/[_\s-]/g, "");
|
|
14724
|
-
|
|
14725
|
-
bare
|
|
14734
|
+
for (const vendor of ["alan", "alan"]) {
|
|
14735
|
+
if (bare.startsWith(vendor) && bare.length > vendor.length) {
|
|
14736
|
+
bare = bare.slice(vendor.length);
|
|
14737
|
+
break;
|
|
14738
|
+
}
|
|
14726
14739
|
}
|
|
14727
14740
|
return bare;
|
|
14728
14741
|
}
|
|
@@ -14761,8 +14774,8 @@ function isInteractiveToolName(name, input) {
|
|
|
14761
14774
|
return true;
|
|
14762
14775
|
return isAskUserQuestionTool(name, input);
|
|
14763
14776
|
}
|
|
14764
|
-
var
|
|
14765
|
-
var
|
|
14777
|
+
var ALAN_AGENT_WORKOS_USER_ID_PREFIX = "alan-agent:";
|
|
14778
|
+
var ALAN_AGENT_WORKOS_USER_ID_LIKE_PATTERN = `${ALAN_AGENT_WORKOS_USER_ID_PREFIX}%`;
|
|
14766
14779
|
|
|
14767
14780
|
// ../shared/dist/constants/colors.js
|
|
14768
14781
|
var CATEGORICAL_COLORS = {
|
|
@@ -15013,11 +15026,11 @@ var import_path6 = require("path");
|
|
|
15013
15026
|
var import_crypto2 = require("crypto");
|
|
15014
15027
|
var import_fs7 = require("fs");
|
|
15015
15028
|
var import_path7 = require("path");
|
|
15016
|
-
var
|
|
15017
|
-
"
|
|
15018
|
-
"
|
|
15019
|
-
"
|
|
15020
|
-
"
|
|
15029
|
+
var MANAGED_ALAN_MCP_SERVER_NAMES = [
|
|
15030
|
+
"alan",
|
|
15031
|
+
"alan-prod",
|
|
15032
|
+
"alan-staging",
|
|
15033
|
+
"alan-local"
|
|
15021
15034
|
];
|
|
15022
15035
|
function parseJsonSafe(content) {
|
|
15023
15036
|
if (!content) return {};
|
|
@@ -15096,8 +15109,8 @@ function parseTomlInlineStringTable(raw) {
|
|
|
15096
15109
|
function buildTomlInlineStringTable(record) {
|
|
15097
15110
|
return `{ ${Object.entries(record).map(([key, value2]) => `${formatTomlKey2(key)} = ${JSON.stringify(value2)}`).join(", ")} }`;
|
|
15098
15111
|
}
|
|
15099
|
-
function
|
|
15100
|
-
for (const name of
|
|
15112
|
+
function findManagedAlanServer(servers) {
|
|
15113
|
+
for (const name of MANAGED_ALAN_MCP_SERVER_NAMES) {
|
|
15101
15114
|
const server = servers[name];
|
|
15102
15115
|
if (server && typeof server === "object") {
|
|
15103
15116
|
return { name, server };
|
|
@@ -15124,7 +15137,7 @@ function patchCodexTomlMcpConfig(content, sessionHeaders) {
|
|
|
15124
15137
|
const lines = content.split(/\r?\n/);
|
|
15125
15138
|
const sectionStart = lines.findIndex((line) => {
|
|
15126
15139
|
const name = getTomlSectionName(line);
|
|
15127
|
-
return Boolean(name &&
|
|
15140
|
+
return Boolean(name && MANAGED_ALAN_MCP_SERVER_NAMES.includes(name));
|
|
15128
15141
|
});
|
|
15129
15142
|
if (sectionStart < 0) return null;
|
|
15130
15143
|
let sectionEnd = lines.findIndex((line, index) => index > sectionStart && /^\s*\[/.test(line));
|
|
@@ -15166,7 +15179,7 @@ function patchJsonMcpTarget(target, sessionHeaders) {
|
|
|
15166
15179
|
const existing = readFileOrNull(target.configPath);
|
|
15167
15180
|
const config = parseJsonSafe(existing);
|
|
15168
15181
|
const servers = target.readServers(config);
|
|
15169
|
-
const match =
|
|
15182
|
+
const match = findManagedAlanServer(servers);
|
|
15170
15183
|
if (!match) return false;
|
|
15171
15184
|
const currentHeaders = target.readHeaders(match.server) ?? {};
|
|
15172
15185
|
target.writeHeaders(match.server, { ...currentHeaders, ...sessionHeaders });
|
|
@@ -15262,7 +15275,7 @@ function buildJsonTargets(home) {
|
|
|
15262
15275
|
}
|
|
15263
15276
|
];
|
|
15264
15277
|
}
|
|
15265
|
-
function
|
|
15278
|
+
function syncAlanMcpSessionHeaders(input) {
|
|
15266
15279
|
const home = input.homeDir ?? (0, import_os2.homedir)();
|
|
15267
15280
|
const sessionHeaders = buildSessionHeaders(input);
|
|
15268
15281
|
const written = [];
|
|
@@ -15308,8 +15321,8 @@ function imageFileExtension(mimeType) {
|
|
|
15308
15321
|
}
|
|
15309
15322
|
function createImageTempDirectory(cwd) {
|
|
15310
15323
|
const candidates = [
|
|
15311
|
-
cwd ? (0, import_path3.join)(cwd, ".
|
|
15312
|
-
(0, import_path3.join)((0, import_os3.tmpdir)(), "
|
|
15324
|
+
cwd ? (0, import_path3.join)(cwd, ".alan-images-") : null,
|
|
15325
|
+
(0, import_path3.join)((0, import_os3.tmpdir)(), "alan-images-")
|
|
15313
15326
|
].filter((value2) => Boolean(value2));
|
|
15314
15327
|
for (const candidate of candidates) {
|
|
15315
15328
|
try {
|
|
@@ -15317,7 +15330,7 @@ function createImageTempDirectory(cwd) {
|
|
|
15317
15330
|
} catch {
|
|
15318
15331
|
}
|
|
15319
15332
|
}
|
|
15320
|
-
return (0, import_fs3.mkdtempSync)((0, import_path3.join)((0, import_os3.tmpdir)(), "
|
|
15333
|
+
return (0, import_fs3.mkdtempSync)((0, import_path3.join)((0, import_os3.tmpdir)(), "alan-images-"));
|
|
15321
15334
|
}
|
|
15322
15335
|
function safeFilename(filename) {
|
|
15323
15336
|
const safe = filename.replace(/[^a-zA-Z0-9._-]/g, "_").replace(/^_+/, "");
|
|
@@ -15331,7 +15344,7 @@ function writeImagesToTempFiles(images, cwd) {
|
|
|
15331
15344
|
const files = [];
|
|
15332
15345
|
for (const img of images) {
|
|
15333
15346
|
const ext = imageFileExtension(img.mimeType);
|
|
15334
|
-
const filePath = (0, import_path3.join)(directory, `
|
|
15347
|
+
const filePath = (0, import_path3.join)(directory, `alan-img-${img.id}.${ext}`);
|
|
15335
15348
|
(0, import_fs3.writeFileSync)(filePath, Buffer.from(img.data, "base64"));
|
|
15336
15349
|
paths.push(filePath);
|
|
15337
15350
|
files.push({
|
|
@@ -16441,7 +16454,7 @@ function maybeFinalizeDeferredResult(kind, context, state) {
|
|
|
16441
16454
|
state.resultDeferredOnBackgroundWork = false;
|
|
16442
16455
|
finalizeStructuredResult(kind, state);
|
|
16443
16456
|
}
|
|
16444
|
-
var DEBUG_ASK = process.env.
|
|
16457
|
+
var DEBUG_ASK = process.env.ALAN_DEBUG_ASK === "1" || process.env.ALAN_DEBUG === "1";
|
|
16445
16458
|
function debugAskLog(message) {
|
|
16446
16459
|
if (DEBUG_ASK) console.info(message);
|
|
16447
16460
|
}
|
|
@@ -18647,7 +18660,7 @@ function buildTaskLifecyclePrompt(config) {
|
|
|
18647
18660
|
return [
|
|
18648
18661
|
"## Task Lifecycle",
|
|
18649
18662
|
`This session is attached to taskId "${taskId}".`,
|
|
18650
|
-
`Do not change the task status on your own. The user manages this task's status. Only change it by calling the
|
|
18663
|
+
`Do not change the task status on your own. The user manages this task's status. Only change it by calling the Alan 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.`,
|
|
18651
18664
|
...statusLines,
|
|
18652
18665
|
"",
|
|
18653
18666
|
"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."
|
|
@@ -18766,12 +18779,12 @@ var BaseMachineAgent = class _BaseMachineAgent {
|
|
|
18766
18779
|
buildRuntimeConfig(config, safeProjectPath) {
|
|
18767
18780
|
const backendKind = this.resolveBackendKind(config);
|
|
18768
18781
|
const supportTier = config.supportTier || this.getDefaultSupportTier(backendKind);
|
|
18769
|
-
const systemPromptParts = [
|
|
18770
|
-
const agentPrompt = config.agentPrompt?.trim() ||
|
|
18782
|
+
const systemPromptParts = [ALAN_IDENTITY_PROMPT];
|
|
18783
|
+
const agentPrompt = config.agentPrompt?.trim() || getAlanAgentPrompt(config.agentId);
|
|
18771
18784
|
if (agentPrompt) systemPromptParts.push(agentPrompt);
|
|
18772
|
-
const modeHint =
|
|
18785
|
+
const modeHint = getAlanModePrompt(config.mode);
|
|
18773
18786
|
if (modeHint) systemPromptParts.push(modeHint);
|
|
18774
|
-
systemPromptParts.push(
|
|
18787
|
+
systemPromptParts.push(ALAN_ASK_USER_PROMPT);
|
|
18775
18788
|
const operatorSystemPrompt = config.systemPrompt?.trim();
|
|
18776
18789
|
if (operatorSystemPrompt) systemPromptParts.push(operatorSystemPrompt);
|
|
18777
18790
|
const workingDir = config.worktreePath || safeProjectPath;
|
|
@@ -18784,7 +18797,7 @@ Prefer relative paths and keep your work scoped to this project.`
|
|
|
18784
18797
|
const lifecyclePrompt = buildTaskLifecyclePrompt(config);
|
|
18785
18798
|
if (lifecyclePrompt) systemPromptParts.push(lifecyclePrompt);
|
|
18786
18799
|
const teamId = config.teamId;
|
|
18787
|
-
const teamCodeOverlay = teamId ?
|
|
18800
|
+
const teamCodeOverlay = teamId ? buildAlanTeamCodeContextOverlay(teamId) : void 0;
|
|
18788
18801
|
if (teamCodeOverlay) {
|
|
18789
18802
|
systemPromptParts.push(teamCodeOverlay);
|
|
18790
18803
|
}
|
|
@@ -18804,7 +18817,7 @@ Prefer relative paths and keep your work scoped to this project.`
|
|
|
18804
18817
|
}
|
|
18805
18818
|
async runCliBackend(config, safeProjectPath) {
|
|
18806
18819
|
const backendKind = this.resolveBackendKind(config);
|
|
18807
|
-
const defaultCwd = (0, import_path.join)((0, import_os.homedir)(), "Documents", "
|
|
18820
|
+
const defaultCwd = (0, import_path.join)((0, import_os.homedir)(), "Documents", "alan");
|
|
18808
18821
|
if (!(0, import_fs.existsSync)(defaultCwd)) {
|
|
18809
18822
|
(0, import_fs.mkdirSync)(defaultCwd, { recursive: true });
|
|
18810
18823
|
}
|
|
@@ -18945,14 +18958,12 @@ Prefer relative paths and keep your work scoped to this project.`
|
|
|
18945
18958
|
}
|
|
18946
18959
|
if (initialConfig.conversationId) {
|
|
18947
18960
|
try {
|
|
18948
|
-
const writtenClis =
|
|
18961
|
+
const writtenClis = syncAlanMcpSessionHeaders({
|
|
18949
18962
|
conversationId: initialConfig.conversationId,
|
|
18950
18963
|
teamId: initialConfig.teamId
|
|
18951
18964
|
});
|
|
18952
18965
|
if (writtenClis.length > 0) {
|
|
18953
|
-
void this.presenter.onLog(
|
|
18954
|
-
`Synced Aiden MCP session headers to ${writtenClis.join(", ")}`
|
|
18955
|
-
);
|
|
18966
|
+
void this.presenter.onLog(`Synced Alan MCP session headers to ${writtenClis.join(", ")}`);
|
|
18956
18967
|
}
|
|
18957
18968
|
} catch (error) {
|
|
18958
18969
|
console.warn("[base-machine-agent] Failed to sync MCP session headers", error);
|
|
@@ -19416,11 +19427,11 @@ ${meta.description}`);
|
|
|
19416
19427
|
}
|
|
19417
19428
|
parts2.push(lines.join("\n"));
|
|
19418
19429
|
}
|
|
19419
|
-
const taskId = config.taskId ?? process.env.
|
|
19420
|
-
const workflowId = config.workflowId ?? process.env.
|
|
19421
|
-
const workflowExecutionId = config.workflowExecutionId ?? process.env.
|
|
19422
|
-
const conversationId = config.conversationId ?? process.env.
|
|
19423
|
-
const teamId = config.teamId ?? process.env.
|
|
19430
|
+
const taskId = config.taskId ?? process.env.ALAN_TASK_ID;
|
|
19431
|
+
const workflowId = config.workflowId ?? process.env.ALAN_WORKFLOW_ID;
|
|
19432
|
+
const workflowExecutionId = config.workflowExecutionId ?? process.env.ALAN_WORKFLOW_EXECUTION_ID;
|
|
19433
|
+
const conversationId = config.conversationId ?? process.env.ALAN_SESSION_ID;
|
|
19434
|
+
const teamId = config.teamId ?? process.env.ALAN_TEAM_ID;
|
|
19424
19435
|
const artifactIds = [];
|
|
19425
19436
|
if (teamId) artifactIds.push(`- teamId: "${teamId}"`);
|
|
19426
19437
|
const isWorkflowSession = !!(workflowId || workflowExecutionId);
|
|
@@ -19444,7 +19455,7 @@ ${meta.description}`);
|
|
|
19444
19455
|
[
|
|
19445
19456
|
"## Prototype Artifacts",
|
|
19446
19457
|
"When the user asks to create, build, modify, or iterate on a prototype, do not create local prototype files such as prototype/index.html.",
|
|
19447
|
-
"Instead, generate a Vite React TypeScript source snapshot and call the
|
|
19458
|
+
"Instead, generate a Vite React TypeScript source snapshot and call the Alan MCP tool upsert_prototype_version with teamId, workflowId, workflowExecutionId, conversationId, title, sourceSnapshot, and packageJson.",
|
|
19448
19459
|
"For follow-up changes to the same prototype, call list_prototypes (with workflowId) or get_prototype if needed, then call upsert_prototype_version again with the existing prototypeId and parentVersionId."
|
|
19449
19460
|
].join("\n")
|
|
19450
19461
|
);
|
|
@@ -19453,7 +19464,7 @@ ${meta.description}`);
|
|
|
19453
19464
|
[
|
|
19454
19465
|
"## Prototype Artifacts",
|
|
19455
19466
|
"When the user asks to create, build, modify, or iterate on a prototype, do not create local prototype files such as prototype/index.html.",
|
|
19456
|
-
"Instead, generate a Vite React TypeScript source snapshot and call the
|
|
19467
|
+
"Instead, generate a Vite React TypeScript source snapshot and call the Alan MCP tool upsert_prototype_version with teamId, taskId, conversationId, title, sourceSnapshot, and packageJson.",
|
|
19457
19468
|
"For follow-up changes to the same prototype, call list_prototypes or get_prototype if needed, then call upsert_prototype_version again with the existing prototypeId and parentVersionId so the task Prototypes panel renders the new version."
|
|
19458
19469
|
].join("\n")
|
|
19459
19470
|
);
|
|
@@ -19466,10 +19477,10 @@ ${meta.description}`);
|
|
|
19466
19477
|
var import_node_fs5 = require("fs");
|
|
19467
19478
|
var import_node_os5 = require("os");
|
|
19468
19479
|
var import_node_path4 = require("path");
|
|
19469
|
-
function
|
|
19480
|
+
function ensureAlanMcpRegistered(backendKind, registration, home = (0, import_node_os5.homedir)()) {
|
|
19470
19481
|
try {
|
|
19471
|
-
const mcpServers =
|
|
19472
|
-
const files =
|
|
19482
|
+
const mcpServers = buildAlanMcpServers(registration);
|
|
19483
|
+
const files = alanMcpConfigFilesForBackend(backendKind, mcpServers, home);
|
|
19473
19484
|
const paths = [];
|
|
19474
19485
|
for (const file of files) {
|
|
19475
19486
|
(0, import_node_fs5.mkdirSync)((0, import_node_path4.dirname)(file.path), { recursive: true });
|
|
@@ -19493,8 +19504,8 @@ function ensureAidenMcpRegistered(backendKind, registration, home = (0, import_n
|
|
|
19493
19504
|
return { ok: false, paths: [], error: err instanceof Error ? err.message : String(err) };
|
|
19494
19505
|
}
|
|
19495
19506
|
}
|
|
19496
|
-
function
|
|
19497
|
-
const files =
|
|
19507
|
+
function verifyAlanMcpRegistered(backendKind, home = (0, import_node_os5.homedir)()) {
|
|
19508
|
+
const files = alanMcpConfigFilesForBackend(backendKind, {}, home);
|
|
19498
19509
|
const missing = files.map((f) => f.path).filter((p) => !(0, import_node_fs5.existsSync)(p));
|
|
19499
19510
|
return { ok: missing.length === 0, missing };
|
|
19500
19511
|
}
|
|
@@ -19852,13 +19863,13 @@ async function discoverProviderModels(provider, executable, env) {
|
|
|
19852
19863
|
}
|
|
19853
19864
|
|
|
19854
19865
|
// src/version.ts
|
|
19855
|
-
var AGENT_VERSION = "0.1.
|
|
19866
|
+
var AGENT_VERSION = "0.1.35";
|
|
19856
19867
|
|
|
19857
19868
|
// src/daemon.ts
|
|
19858
|
-
var STAGING_API_URL = process.env.
|
|
19859
|
-
var STAGING_WS_URL = process.env.
|
|
19860
|
-
var PRODUCTION_API_URL = "https://api.
|
|
19861
|
-
var PRODUCTION_WS_URL = "wss://ws.
|
|
19869
|
+
var STAGING_API_URL = process.env.ALAN_STAGING_API_URL ?? "https://staging-api.tryalan.ai";
|
|
19870
|
+
var STAGING_WS_URL = process.env.ALAN_STAGING_WS_URL ?? "wss://alan-staging-ws.tryalan.ai";
|
|
19871
|
+
var PRODUCTION_API_URL = "https://api.tryalan.ai";
|
|
19872
|
+
var PRODUCTION_WS_URL = "wss://ws.tryalan.ai";
|
|
19862
19873
|
var LOCAL_API_URL = "http://localhost:8400";
|
|
19863
19874
|
var LOCAL_WS_URL = "ws://localhost:8401";
|
|
19864
19875
|
function requiredString(params, key) {
|
|
@@ -19908,10 +19919,10 @@ function gitSafe(cwd, args) {
|
|
|
19908
19919
|
}
|
|
19909
19920
|
function worktreeDir(projectPath) {
|
|
19910
19921
|
const resolved = (0, import_node_path5.resolve)(projectPath);
|
|
19911
|
-
return (0, import_node_path5.join)((0, import_node_path5.dirname)(resolved), `${(0, import_node_path5.basename)(resolved)}-
|
|
19922
|
+
return (0, import_node_path5.join)((0, import_node_path5.dirname)(resolved), `${(0, import_node_path5.basename)(resolved)}-alan-worktrees`);
|
|
19912
19923
|
}
|
|
19913
19924
|
function pathSegment(value2) {
|
|
19914
|
-
return value2.toLowerCase().replace(/^
|
|
19925
|
+
return value2.toLowerCase().replace(/^alan\//, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "task";
|
|
19915
19926
|
}
|
|
19916
19927
|
function repoName(repoUrl, localPath) {
|
|
19917
19928
|
return repoUrl.replace(/\.git$/, "").split("/").pop() || (0, import_node_path5.basename)(localPath) || "repo";
|
|
@@ -20082,7 +20093,7 @@ async function probeLocalDaemonEndpoint(port, token, timeoutMs = 750) {
|
|
|
20082
20093
|
}
|
|
20083
20094
|
}
|
|
20084
20095
|
function describeOccupiedLocalDaemon(port) {
|
|
20085
|
-
return `local daemon API port ${port} is already in use. If
|
|
20096
|
+
return `local daemon API port ${port} is already in use. If Alan desktop is open, it manages the daemon automatically. Quit Alan desktop or stop the existing daemon before starting another.`;
|
|
20086
20097
|
}
|
|
20087
20098
|
var boundAgentConfigPath = null;
|
|
20088
20099
|
function bindConfigPath(args) {
|
|
@@ -20090,10 +20101,10 @@ function bindConfigPath(args) {
|
|
|
20090
20101
|
return boundAgentConfigPath;
|
|
20091
20102
|
}
|
|
20092
20103
|
function getConfigPath() {
|
|
20093
|
-
return process.env.
|
|
20104
|
+
return process.env.ALAN_AGENT_CONFIG_PATH ?? boundAgentConfigPath ?? resolveAgentConfigPath({ profile: "production" });
|
|
20094
20105
|
}
|
|
20095
20106
|
function getEndpointDefaultsPath() {
|
|
20096
|
-
return process.env.
|
|
20107
|
+
return process.env.ALAN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path5.join)((0, import_node_path5.dirname)(getConfigPath()), "endpoints.json");
|
|
20097
20108
|
}
|
|
20098
20109
|
function readConfig() {
|
|
20099
20110
|
const configPath = getConfigPath();
|
|
@@ -20139,8 +20150,8 @@ function resolveEndpoints(args, stored = {}) {
|
|
|
20139
20150
|
const profileApiUrl = requestedProfile === "local" ? LOCAL_API_URL : requestedProfile === "staging" ? STAGING_API_URL : PRODUCTION_API_URL;
|
|
20140
20151
|
const profileWsUrl = requestedProfile === "local" ? LOCAL_WS_URL : requestedProfile === "staging" ? STAGING_WS_URL : PRODUCTION_WS_URL;
|
|
20141
20152
|
const endpointDefaults = readEndpointDefaults();
|
|
20142
|
-
const apiUrl = argValue(args, "--api-url") ?? process.env.
|
|
20143
|
-
const wsUrl = argValue(args, "--ws-url") ?? process.env.
|
|
20153
|
+
const apiUrl = argValue(args, "--api-url") ?? process.env.ALAN_API_URL ?? stored.apiUrl ?? endpointDefaults.apiUrl ?? profileApiUrl;
|
|
20154
|
+
const wsUrl = argValue(args, "--ws-url") ?? process.env.ALAN_WS_URL ?? stored.wsUrl ?? endpointDefaults.wsUrl ?? profileWsUrl;
|
|
20144
20155
|
const endpointProfile = apiUrl === profileApiUrl && wsUrl === profileWsUrl ? requestedProfile : apiUrl === endpointDefaults.apiUrl && wsUrl === endpointDefaults.wsUrl && endpointDefaults.endpointProfile ? endpointDefaults.endpointProfile : "custom";
|
|
20145
20156
|
return { apiUrl, wsUrl, endpointProfile };
|
|
20146
20157
|
}
|
|
@@ -20150,9 +20161,12 @@ function isLocalEndpoint(url2) {
|
|
|
20150
20161
|
function checkStoredEndpointConsistency(stored, endpointDefaults) {
|
|
20151
20162
|
const profile = stored.endpointProfile;
|
|
20152
20163
|
if (profile !== "production" && profile !== "staging") return null;
|
|
20164
|
+
const builtInApiUrl = profile === "production" ? PRODUCTION_API_URL : STAGING_API_URL;
|
|
20165
|
+
const builtInWsUrl = profile === "production" ? PRODUCTION_WS_URL : STAGING_WS_URL;
|
|
20166
|
+
if (stored.apiUrl === builtInApiUrl && stored.wsUrl === builtInWsUrl) return null;
|
|
20153
20167
|
const defaultsMatchProfile = endpointDefaults.endpointProfile === profile;
|
|
20154
|
-
const expectedApiUrl = (defaultsMatchProfile ? endpointDefaults.apiUrl : void 0) ??
|
|
20155
|
-
const expectedWsUrl = (defaultsMatchProfile ? endpointDefaults.wsUrl : void 0) ??
|
|
20168
|
+
const expectedApiUrl = (defaultsMatchProfile ? endpointDefaults.apiUrl : void 0) ?? builtInApiUrl;
|
|
20169
|
+
const expectedWsUrl = (defaultsMatchProfile ? endpointDefaults.wsUrl : void 0) ?? builtInWsUrl;
|
|
20156
20170
|
const issues = [];
|
|
20157
20171
|
if (stored.wsUrl && stored.wsUrl !== expectedWsUrl) {
|
|
20158
20172
|
issues.push(`wsUrl ${stored.wsUrl} (expected ${expectedWsUrl})`);
|
|
@@ -20168,7 +20182,7 @@ function checkStoredEndpointConsistency(stored, endpointDefaults) {
|
|
|
20168
20182
|
};
|
|
20169
20183
|
}
|
|
20170
20184
|
function getLocalApiPort(args, stored) {
|
|
20171
|
-
const raw = argValue(args, "--local-api-port") ?? process.env.
|
|
20185
|
+
const raw = argValue(args, "--local-api-port") ?? process.env.ALAN_AGENT_LOCAL_API_PORT;
|
|
20172
20186
|
if (raw) return Number.parseInt(raw, 10);
|
|
20173
20187
|
const storedPort = stored.localApiPort;
|
|
20174
20188
|
if (storedPort && storedPort > 0) return storedPort;
|
|
@@ -20699,17 +20713,17 @@ var RuntimePresenter = class {
|
|
|
20699
20713
|
async function setupDaemon(args) {
|
|
20700
20714
|
bindConfigPath(args);
|
|
20701
20715
|
const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
|
|
20702
|
-
const teamId = argValue(args, "--team") ?? process.env.
|
|
20703
|
-
const setupToken = argValue(args, "--setup-token") ?? process.env.
|
|
20704
|
-
const token = argValue(args, "--token") ?? process.env.
|
|
20716
|
+
const teamId = argValue(args, "--team") ?? process.env.ALAN_TEAM_ID;
|
|
20717
|
+
const setupToken = argValue(args, "--setup-token") ?? process.env.ALAN_RUNTIME_SETUP_TOKEN;
|
|
20718
|
+
const token = argValue(args, "--token") ?? process.env.ALAN_SETUP_TOKEN;
|
|
20705
20719
|
const displayName = argValue(args, "--name") ?? (0, import_node_os6.hostname)();
|
|
20706
|
-
const scope = argValue(args, "--scope") ?? process.env.
|
|
20720
|
+
const scope = argValue(args, "--scope") ?? process.env.ALAN_RUNTIME_SCOPE ?? "team";
|
|
20707
20721
|
if (scope !== "team" && scope !== "user") {
|
|
20708
20722
|
throw new Error("setup --scope must be either 'team' or 'user'");
|
|
20709
20723
|
}
|
|
20710
20724
|
if (!setupToken && (!teamId || !token)) {
|
|
20711
20725
|
throw new Error(
|
|
20712
|
-
"setup requires --setup-token <token> or --team <team-id> and --token <
|
|
20726
|
+
"setup requires --setup-token <token> or --team <team-id> and --token <alan PAT>.\nFor normal setup, copy the setup token from Alan and run: alan-agent setup --setup-token <token>\nFor browser authorization, run: alan-agent login"
|
|
20713
20727
|
);
|
|
20714
20728
|
}
|
|
20715
20729
|
const response = await fetch(
|
|
@@ -20751,7 +20765,7 @@ async function setupDaemon(args) {
|
|
|
20751
20765
|
localApiToken: (0, import_node_crypto.randomBytes)(24).toString("hex"),
|
|
20752
20766
|
displayName: body.runtime.displayName ?? displayName
|
|
20753
20767
|
});
|
|
20754
|
-
console.info("[
|
|
20768
|
+
console.info("[alan-agent] Runtime registered", {
|
|
20755
20769
|
runtimeId: body.runtime.id,
|
|
20756
20770
|
configPath: getConfigPath()
|
|
20757
20771
|
});
|
|
@@ -20776,8 +20790,8 @@ async function loginWithDeviceCode(args) {
|
|
|
20776
20790
|
}
|
|
20777
20791
|
const authorization = await start.json();
|
|
20778
20792
|
const intervalMs = Math.max(0, (authorization.intervalSeconds ?? 2) * 1e3);
|
|
20779
|
-
console.info(`[
|
|
20780
|
-
console.info(`[
|
|
20793
|
+
console.info(`[alan-agent] Open ${authorization.verificationUri}`);
|
|
20794
|
+
console.info(`[alan-agent] Enter code ${authorization.userCode}`);
|
|
20781
20795
|
for (let attempt = 0; attempt < maxPolls; attempt += 1) {
|
|
20782
20796
|
if (attempt > 0) await sleep(intervalMs);
|
|
20783
20797
|
const token = await fetch(`${apiUrl}/public/runtimes/device-authorizations/token`, {
|
|
@@ -20803,7 +20817,7 @@ async function loginWithDeviceCode(args) {
|
|
|
20803
20817
|
localApiToken: (0, import_node_crypto.randomBytes)(24).toString("hex"),
|
|
20804
20818
|
displayName: body.runtime.displayName ?? displayName
|
|
20805
20819
|
});
|
|
20806
|
-
console.info("[
|
|
20820
|
+
console.info("[alan-agent] Runtime registered", {
|
|
20807
20821
|
runtimeId: body.runtime.id,
|
|
20808
20822
|
configPath: getConfigPath()
|
|
20809
20823
|
});
|
|
@@ -20818,14 +20832,14 @@ async function startDaemon(args) {
|
|
|
20818
20832
|
const endpointProfile = stored.endpointProfile ?? resolveEndpointProfile(args);
|
|
20819
20833
|
const daemonSessionId = (0, import_node_crypto.randomUUID)();
|
|
20820
20834
|
let heartbeatSeq = 0;
|
|
20821
|
-
const runtimeId = argValue(args, "--runtime-id") ?? process.env.
|
|
20822
|
-
const runtimeToken = argValue(args, "--token") ?? process.env.
|
|
20823
|
-
const wsUrlOverride = argValue(args, "--ws-url") ?? process.env.
|
|
20835
|
+
const runtimeId = argValue(args, "--runtime-id") ?? process.env.ALAN_RUNTIME_ID ?? stored.runtimeId;
|
|
20836
|
+
const runtimeToken = argValue(args, "--token") ?? process.env.ALAN_RUNTIME_TOKEN ?? stored.runtimeToken;
|
|
20837
|
+
const wsUrlOverride = argValue(args, "--ws-url") ?? process.env.ALAN_WS_URL;
|
|
20824
20838
|
const endpointMismatch = wsUrlOverride ? null : checkStoredEndpointConsistency(stored, readEndpointDefaults());
|
|
20825
20839
|
let wsUrl = wsUrlOverride ?? stored.wsUrl;
|
|
20826
20840
|
if (endpointMismatch && stored.wsUrl && stored.wsUrl !== endpointMismatch.expectedWsUrl) {
|
|
20827
20841
|
console.warn(
|
|
20828
|
-
"[
|
|
20842
|
+
"[alan-agent] Stored config does not match its endpoint profile \u2014 connecting with the profile endpoints instead. Re-run setup to repair the stored config.",
|
|
20829
20843
|
{ configPath: getConfigPath(), detail: endpointMismatch.detail }
|
|
20830
20844
|
);
|
|
20831
20845
|
wsUrl = endpointMismatch.expectedWsUrl;
|
|
@@ -20840,6 +20854,7 @@ async function startDaemon(args) {
|
|
|
20840
20854
|
const activeAgents = /* @__PURE__ */ new Map();
|
|
20841
20855
|
let disconnectedSinceMs = null;
|
|
20842
20856
|
let lastConnectError = null;
|
|
20857
|
+
let lastConnectErrorCode = null;
|
|
20843
20858
|
const pendingDeliveryLost = [];
|
|
20844
20859
|
const currentCapabilities = () => discoverCapabilities();
|
|
20845
20860
|
const currentMetadata = () => collectRuntimeMetadataWithProviderLimits();
|
|
@@ -20909,9 +20924,10 @@ async function startDaemon(args) {
|
|
|
20909
20924
|
socket.on("connect", () => {
|
|
20910
20925
|
disconnectedSinceMs = null;
|
|
20911
20926
|
lastConnectError = null;
|
|
20927
|
+
lastConnectErrorCode = null;
|
|
20912
20928
|
setConnectedRuntimeSocket(socket);
|
|
20913
20929
|
pushLog(`connected runtime=${runtimeId}`);
|
|
20914
|
-
console.info("[
|
|
20930
|
+
console.info("[alan-agent] Daemon connected", { runtimeId, wsUrl, version: AGENT_VERSION });
|
|
20915
20931
|
flushPendingDeliveryLostEvents({
|
|
20916
20932
|
socket,
|
|
20917
20933
|
activeAgents,
|
|
@@ -20947,18 +20963,22 @@ async function startDaemon(args) {
|
|
|
20947
20963
|
socket.on("connect_error", (error) => {
|
|
20948
20964
|
if (!socket.connected && disconnectedSinceMs === null) disconnectedSinceMs = Date.now();
|
|
20949
20965
|
lastConnectError = error.message;
|
|
20950
|
-
|
|
20966
|
+
const errorCode = error?.data?.code;
|
|
20967
|
+
lastConnectErrorCode = typeof errorCode === "string" ? errorCode : null;
|
|
20968
|
+
pushLog(
|
|
20969
|
+
`connect_error ${error.message}${lastConnectErrorCode ? ` code=${lastConnectErrorCode}` : ""}`
|
|
20970
|
+
);
|
|
20951
20971
|
const now = Date.now();
|
|
20952
20972
|
if (now - lastConnectErrorLogAt < 5e3) return;
|
|
20953
20973
|
lastConnectErrorLogAt = now;
|
|
20954
20974
|
const wsHint = isLocalEndpoint(wsUrl) ? ` Nothing is listening at ${wsUrl}. For local dev run setup with --profile local and start the stack (WS on ws://localhost:8401).` : ` Verify wsUrl in ${getConfigPath()} and that you can reach ${wsUrl}.`;
|
|
20955
|
-
console.warn("[
|
|
20975
|
+
console.warn("[alan-agent] Daemon connection error:", `${error.message}.${wsHint}`);
|
|
20956
20976
|
});
|
|
20957
20977
|
socket.on("disconnect", (reason) => {
|
|
20958
20978
|
setConnectedRuntimeSocket(null);
|
|
20959
20979
|
if (disconnectedSinceMs === null) disconnectedSinceMs = Date.now();
|
|
20960
20980
|
pushLog(`disconnected ${reason}`);
|
|
20961
|
-
console.info("[
|
|
20981
|
+
console.info("[alan-agent] Daemon disconnected:", reason);
|
|
20962
20982
|
for (const [runId, entry] of activeAgents.entries()) {
|
|
20963
20983
|
if (entry.stage === "completed" || entry.stage === "failed" || entry.stage === "aborted" || entry.stage === "delivery_lost") {
|
|
20964
20984
|
continue;
|
|
@@ -21061,7 +21081,7 @@ async function startDaemon(args) {
|
|
|
21061
21081
|
agentVersion: AGENT_VERSION
|
|
21062
21082
|
});
|
|
21063
21083
|
pushLog(`accepted run=${payload.runId}`);
|
|
21064
|
-
console.info("[
|
|
21084
|
+
console.info("[alan-agent] Agent run accepted", correlation);
|
|
21065
21085
|
if (!payload.worktreeInfo?.worktreePath && payload.sharedCheckout?.branchName) {
|
|
21066
21086
|
const repoTargets = resolveSharedCheckoutTargets({
|
|
21067
21087
|
cwd,
|
|
@@ -21091,14 +21111,14 @@ async function startDaemon(args) {
|
|
|
21091
21111
|
};
|
|
21092
21112
|
const releaseActiveRun = () => {
|
|
21093
21113
|
if (!activeAgents.delete(payload.runId)) return;
|
|
21094
|
-
console.info("[
|
|
21114
|
+
console.info("[alan-agent] Agent run finished", correlation);
|
|
21095
21115
|
};
|
|
21096
21116
|
if (backendKind) {
|
|
21097
21117
|
if (payload.aidenMcp) {
|
|
21098
|
-
const registration =
|
|
21118
|
+
const registration = ensureAlanMcpRegistered(backendKind, payload.aidenMcp);
|
|
21099
21119
|
if (registration.ok) {
|
|
21100
21120
|
pushLog(`mcp-registered run=${payload.runId} url=${payload.aidenMcp.url}`);
|
|
21101
|
-
console.info("[
|
|
21121
|
+
console.info("[alan-agent] Alan MCP registered for run", {
|
|
21102
21122
|
...correlation,
|
|
21103
21123
|
mcpUrl: payload.aidenMcp.url,
|
|
21104
21124
|
paths: registration.paths
|
|
@@ -21106,16 +21126,16 @@ async function startDaemon(args) {
|
|
|
21106
21126
|
} else {
|
|
21107
21127
|
pushLog(`mcp-registration-failed run=${payload.runId} ${registration.error}`);
|
|
21108
21128
|
console.warn(
|
|
21109
|
-
"[
|
|
21129
|
+
"[alan-agent] Alan MCP registration failed \u2014 Alan tools may be unavailable this run",
|
|
21110
21130
|
{ ...correlation, error: registration.error }
|
|
21111
21131
|
);
|
|
21112
21132
|
}
|
|
21113
21133
|
} else {
|
|
21114
|
-
const check2 =
|
|
21134
|
+
const check2 = verifyAlanMcpRegistered(backendKind);
|
|
21115
21135
|
if (!check2.ok) {
|
|
21116
21136
|
pushLog(`mcp-config-missing run=${payload.runId}`);
|
|
21117
21137
|
console.warn(
|
|
21118
|
-
"[
|
|
21138
|
+
"[alan-agent] Alan MCP config missing \u2014 Alan tools may be unavailable this run",
|
|
21119
21139
|
{ ...correlation, missing: check2.missing }
|
|
21120
21140
|
);
|
|
21121
21141
|
}
|
|
@@ -21181,7 +21201,7 @@ async function startDaemon(args) {
|
|
|
21181
21201
|
}).catch((error) => {
|
|
21182
21202
|
const message = error instanceof Error ? error.message : String(error);
|
|
21183
21203
|
pushLog(`failed run=${payload.runId} ${message}`);
|
|
21184
|
-
console.error("[
|
|
21204
|
+
console.error("[alan-agent] Agent run failed", {
|
|
21185
21205
|
...correlation,
|
|
21186
21206
|
error: message
|
|
21187
21207
|
});
|
|
@@ -21208,7 +21228,7 @@ async function startDaemon(args) {
|
|
|
21208
21228
|
abortActiveAgent(entry);
|
|
21209
21229
|
activeAgents.delete(payload.runId);
|
|
21210
21230
|
pushLog(`aborted run=${payload.runId}`);
|
|
21211
|
-
console.info("[
|
|
21231
|
+
console.info("[alan-agent] Agent run aborted", {
|
|
21212
21232
|
runId: payload.runId,
|
|
21213
21233
|
agentVersion: AGENT_VERSION
|
|
21214
21234
|
});
|
|
@@ -21315,6 +21335,7 @@ async function startDaemon(args) {
|
|
|
21315
21335
|
lastRunActivityAtMs: runnerSummary.lastRunActivityAtMs,
|
|
21316
21336
|
disconnectedSinceMs: runnerSummary.disconnectedSinceMs,
|
|
21317
21337
|
lastConnectError,
|
|
21338
|
+
lastConnectErrorCode,
|
|
21318
21339
|
daemonSessionId,
|
|
21319
21340
|
heartbeatSeq,
|
|
21320
21341
|
endpointProfile,
|
|
@@ -21341,6 +21362,15 @@ async function startDaemon(args) {
|
|
|
21341
21362
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true }));
|
|
21342
21363
|
return;
|
|
21343
21364
|
}
|
|
21365
|
+
if (req.method === "POST" && req.url === "/reconnect") {
|
|
21366
|
+
pushLog("reconnect requested via local API");
|
|
21367
|
+
lastConnectError = null;
|
|
21368
|
+
lastConnectErrorCode = null;
|
|
21369
|
+
socket.disconnect();
|
|
21370
|
+
socket.connect();
|
|
21371
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true }));
|
|
21372
|
+
return;
|
|
21373
|
+
}
|
|
21344
21374
|
if (req.method === "POST" && req.url?.startsWith("/stop_run")) {
|
|
21345
21375
|
const runId = new URL(req.url, "http://127.0.0.1").searchParams.get("runId");
|
|
21346
21376
|
if (!runId) {
|
|
@@ -21395,7 +21425,7 @@ async function startDaemon(args) {
|
|
|
21395
21425
|
clearInterval(versionRefresh);
|
|
21396
21426
|
socket.disconnect();
|
|
21397
21427
|
throw new Error(
|
|
21398
|
-
`${describeOccupiedLocalDaemon(localApiPort)} The token in ${getConfigPath()} no longer matches the running daemon; quit
|
|
21428
|
+
`${describeOccupiedLocalDaemon(localApiPort)} The token in ${getConfigPath()} no longer matches the running daemon; quit Alan desktop or run setup again.`
|
|
21399
21429
|
);
|
|
21400
21430
|
}
|
|
21401
21431
|
await new Promise((resolve3, reject) => {
|
|
@@ -21425,7 +21455,7 @@ async function startDaemon(args) {
|
|
|
21425
21455
|
const address = localServer.address();
|
|
21426
21456
|
if (address && typeof address === "object") localApiPort = address.port;
|
|
21427
21457
|
pushLog(`local_api listening port=${localApiPort}`);
|
|
21428
|
-
console.info("[
|
|
21458
|
+
console.info("[alan-agent] Local daemon API listening", { port: localApiPort });
|
|
21429
21459
|
resolve3();
|
|
21430
21460
|
});
|
|
21431
21461
|
});
|
|
@@ -21467,11 +21497,11 @@ async function stopDaemon(args) {
|
|
|
21467
21497
|
const probe = await probeLocalDaemonEndpoint(localApiPort, localApiToken);
|
|
21468
21498
|
if (probe.state === "listening_unauthorized") {
|
|
21469
21499
|
throw new Error(
|
|
21470
|
-
`Daemon is listening on port ${localApiPort} but rejected this config token. Quit
|
|
21500
|
+
`Daemon is listening on port ${localApiPort} but rejected this config token. Quit Alan desktop or rerun setup/login to refresh config.`
|
|
21471
21501
|
);
|
|
21472
21502
|
}
|
|
21473
21503
|
if (probe.state === "absent") {
|
|
21474
|
-
console.info("[
|
|
21504
|
+
console.info("[alan-agent] No daemon listening", { port: localApiPort });
|
|
21475
21505
|
return;
|
|
21476
21506
|
}
|
|
21477
21507
|
const response = await fetch(`http://127.0.0.1:${localApiPort}/shutdown`, {
|
|
@@ -21482,7 +21512,7 @@ async function stopDaemon(args) {
|
|
|
21482
21512
|
if (!response.ok) {
|
|
21483
21513
|
throw new Error(`Failed to stop daemon: HTTP ${response.status}`);
|
|
21484
21514
|
}
|
|
21485
|
-
console.info("[
|
|
21515
|
+
console.info("[alan-agent] Daemon stopped", {
|
|
21486
21516
|
port: localApiPort,
|
|
21487
21517
|
runtimeId: probe.status.runtimeId
|
|
21488
21518
|
});
|
|
@@ -21494,18 +21524,18 @@ async function runDaemon(args) {
|
|
|
21494
21524
|
const localApiToken = stored.localApiToken;
|
|
21495
21525
|
const existingProbe = await probeLocalDaemonEndpoint(localApiPort, localApiToken);
|
|
21496
21526
|
if (existingProbe.state === "running") {
|
|
21497
|
-
console.info("[
|
|
21527
|
+
console.info("[alan-agent] Daemon already running", {
|
|
21498
21528
|
port: localApiPort,
|
|
21499
21529
|
runtimeId: existingProbe.status.runtimeId,
|
|
21500
21530
|
connected: existingProbe.status.connected,
|
|
21501
|
-
hint: "If
|
|
21531
|
+
hint: "If Alan desktop is open, it manages the daemon automatically."
|
|
21502
21532
|
});
|
|
21503
21533
|
return;
|
|
21504
21534
|
}
|
|
21505
21535
|
if (existingProbe.state === "listening_unauthorized") {
|
|
21506
|
-
console.info("[
|
|
21536
|
+
console.info("[alan-agent] Daemon already running", {
|
|
21507
21537
|
port: localApiPort,
|
|
21508
|
-
hint: `
|
|
21538
|
+
hint: `Alan desktop is using a different local API token than ${getConfigPath()}. Quit the desktop app or rerun setup if you need a fresh daemon.`
|
|
21509
21539
|
});
|
|
21510
21540
|
return;
|
|
21511
21541
|
}
|
|
@@ -21522,11 +21552,11 @@ async function runDaemon(args) {
|
|
|
21522
21552
|
async function rotateRuntimeToken(args) {
|
|
21523
21553
|
bindConfigPath(args);
|
|
21524
21554
|
const stored = readConfig();
|
|
21525
|
-
const apiUrl = argValue(args, "--api-url") ?? process.env.
|
|
21526
|
-
const runtimeId = argValue(args, "--runtime-id") ?? process.env.
|
|
21527
|
-
const token = argValue(args, "--token") ?? process.env.
|
|
21555
|
+
const apiUrl = argValue(args, "--api-url") ?? process.env.ALAN_API_URL ?? stored.apiUrl;
|
|
21556
|
+
const runtimeId = argValue(args, "--runtime-id") ?? process.env.ALAN_RUNTIME_ID ?? stored.runtimeId;
|
|
21557
|
+
const token = argValue(args, "--token") ?? process.env.ALAN_SETUP_TOKEN;
|
|
21528
21558
|
if (!apiUrl || !runtimeId || !token) {
|
|
21529
|
-
throw new Error("token rotate requires configured api/runtime plus --token <
|
|
21559
|
+
throw new Error("token rotate requires configured api/runtime plus --token <alan PAT>");
|
|
21530
21560
|
}
|
|
21531
21561
|
const response = await fetch(`${apiUrl}/public/runtimes/${runtimeId}/tokens/rotate`, {
|
|
21532
21562
|
method: "POST",
|
|
@@ -21537,16 +21567,16 @@ async function rotateRuntimeToken(args) {
|
|
|
21537
21567
|
}
|
|
21538
21568
|
const body = await response.json();
|
|
21539
21569
|
writeConfig({ ...stored, apiUrl, runtimeId, runtimeToken: body.runtimeToken });
|
|
21540
|
-
console.info("[
|
|
21570
|
+
console.info("[alan-agent] Runtime token rotated", { runtimeId });
|
|
21541
21571
|
}
|
|
21542
21572
|
async function revokeRuntimeToken(args) {
|
|
21543
21573
|
bindConfigPath(args);
|
|
21544
21574
|
const stored = readConfig();
|
|
21545
|
-
const apiUrl = argValue(args, "--api-url") ?? process.env.
|
|
21546
|
-
const runtimeId = argValue(args, "--runtime-id") ?? process.env.
|
|
21547
|
-
const token = argValue(args, "--token") ?? process.env.
|
|
21575
|
+
const apiUrl = argValue(args, "--api-url") ?? process.env.ALAN_API_URL ?? stored.apiUrl;
|
|
21576
|
+
const runtimeId = argValue(args, "--runtime-id") ?? process.env.ALAN_RUNTIME_ID ?? stored.runtimeId;
|
|
21577
|
+
const token = argValue(args, "--token") ?? process.env.ALAN_SETUP_TOKEN;
|
|
21548
21578
|
if (!apiUrl || !runtimeId || !token) {
|
|
21549
|
-
throw new Error("token revoke requires configured api/runtime plus --token <
|
|
21579
|
+
throw new Error("token revoke requires configured api/runtime plus --token <alan PAT>");
|
|
21550
21580
|
}
|
|
21551
21581
|
const response = await fetch(`${apiUrl}/public/runtimes/${runtimeId}/tokens/revoke`, {
|
|
21552
21582
|
method: "POST",
|
|
@@ -21556,12 +21586,12 @@ async function revokeRuntimeToken(args) {
|
|
|
21556
21586
|
throw new Error(`runtime token revoke failed: ${response.status} ${await response.text()}`);
|
|
21557
21587
|
}
|
|
21558
21588
|
removeConfig();
|
|
21559
|
-
console.info("[
|
|
21589
|
+
console.info("[alan-agent] Runtime token revoked", { runtimeId });
|
|
21560
21590
|
}
|
|
21561
21591
|
function logoutDaemon(args = []) {
|
|
21562
21592
|
bindConfigPath(args);
|
|
21563
21593
|
removeConfig();
|
|
21564
|
-
console.info("[
|
|
21594
|
+
console.info("[alan-agent] Runtime config removed", { configPath: getConfigPath() });
|
|
21565
21595
|
}
|
|
21566
21596
|
async function printStatus(args = []) {
|
|
21567
21597
|
bindConfigPath(args);
|
|
@@ -21589,7 +21619,7 @@ async function printStatus(args = []) {
|
|
|
21589
21619
|
localDaemonRunning,
|
|
21590
21620
|
hasLocalApiToken: Boolean(config.localApiToken),
|
|
21591
21621
|
configPath: getConfigPath(),
|
|
21592
|
-
note: configured ? localDaemonRunning ? "Local daemon is running. Stop it with:
|
|
21622
|
+
note: configured ? localDaemonRunning ? "Local daemon is running. Stop it with: alan-agent stop" : "Durable runtime config is present. Start it with: alan-agent daemon" : "No durable runtime configured. Cloud sandbox sessions are launched by Alan with session env vars and do not appear in this local config.",
|
|
21593
21623
|
warnings
|
|
21594
21624
|
},
|
|
21595
21625
|
null,
|
|
@@ -21680,7 +21710,7 @@ var AgentLifecycleLogger = class _AgentLifecycleLogger {
|
|
|
21680
21710
|
const record = omitUndefined({
|
|
21681
21711
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21682
21712
|
level,
|
|
21683
|
-
component: "
|
|
21713
|
+
component: "agent-manager",
|
|
21684
21714
|
event,
|
|
21685
21715
|
...this.context,
|
|
21686
21716
|
...normalizeFields(fields)
|
|
@@ -21690,12 +21720,12 @@ var AgentLifecycleLogger = class _AgentLifecycleLogger {
|
|
|
21690
21720
|
};
|
|
21691
21721
|
function lifecycleContextFromEnv(env) {
|
|
21692
21722
|
return normalizeContext({
|
|
21693
|
-
taskId: env.
|
|
21694
|
-
conversationId: env.
|
|
21695
|
-
runId: env.
|
|
21696
|
-
sandboxId: env.
|
|
21697
|
-
provider: env.
|
|
21698
|
-
backendKind: env.
|
|
21723
|
+
taskId: env.ALAN_TASK_ID,
|
|
21724
|
+
conversationId: env.ALAN_SESSION_ID,
|
|
21725
|
+
runId: env.ALAN_RUN_ID,
|
|
21726
|
+
sandboxId: env.ALAN_SANDBOX_ID,
|
|
21727
|
+
provider: env.ALAN_SANDBOX_PROVIDER,
|
|
21728
|
+
backendKind: env.ALAN_BACKEND_KIND,
|
|
21699
21729
|
agentVersion: AGENT_VERSION
|
|
21700
21730
|
});
|
|
21701
21731
|
}
|
|
@@ -21884,11 +21914,41 @@ var WebPresenter = class {
|
|
|
21884
21914
|
}
|
|
21885
21915
|
};
|
|
21886
21916
|
|
|
21917
|
+
// src/ws-client.ts
|
|
21918
|
+
var import_node_crypto2 = require("crypto");
|
|
21919
|
+
|
|
21920
|
+
// ../shared/dist/agent-liveness.js
|
|
21921
|
+
var AGENT_LIVENESS_PROTOCOL_VERSION = 1;
|
|
21922
|
+
var AGENT_HEARTBEAT_INTERVAL_MS = 15e3;
|
|
21923
|
+
var agentRunStateSchema = external_exports.object({
|
|
21924
|
+
/** True when no run is currently executing in this agent process. */
|
|
21925
|
+
idle: external_exports.boolean(),
|
|
21926
|
+
/** Run ids currently executing (cloud sandbox agent runs one at a time, but keep it a list). */
|
|
21927
|
+
activeRunIds: external_exports.array(external_exports.string()).default([])
|
|
21928
|
+
});
|
|
21929
|
+
var agentHeartbeatSchema = external_exports.object({
|
|
21930
|
+
/** Stable id for this agent OS process; changes only on a fresh agent start. */
|
|
21931
|
+
agentSessionId: external_exports.string().min(1),
|
|
21932
|
+
/** Monotonic per-process sequence number; advances on every heartbeat. */
|
|
21933
|
+
seq: external_exports.number().int().nonnegative(),
|
|
21934
|
+
/** Capability marker — presence is what distinguishes a new agent from a legacy one. */
|
|
21935
|
+
protocolVersion: external_exports.number().int().positive(),
|
|
21936
|
+
runState: agentRunStateSchema,
|
|
21937
|
+
agentVersion: external_exports.string().optional()
|
|
21938
|
+
});
|
|
21939
|
+
var agentProbeAckSchema = external_exports.object({
|
|
21940
|
+
agentSessionId: external_exports.string().min(1),
|
|
21941
|
+
seq: external_exports.number().int().nonnegative().optional(),
|
|
21942
|
+
protocolVersion: external_exports.number().int().positive().optional()
|
|
21943
|
+
});
|
|
21944
|
+
|
|
21887
21945
|
// src/ws-client.ts
|
|
21888
21946
|
var WSClient = class {
|
|
21889
21947
|
constructor(wsUrl, sessionId, taskId, token, callbacks, agentVersion, lifecycle) {
|
|
21890
21948
|
this.lifecycle = lifecycle;
|
|
21891
21949
|
this.lifecycle?.info("sandbox_agent_ws_socket_create", { wsUrl });
|
|
21950
|
+
this.agentVersion = agentVersion ?? "";
|
|
21951
|
+
this.getRunState = callbacks.getRunState;
|
|
21892
21952
|
this.socket = lookup(wsUrl, {
|
|
21893
21953
|
query: { type: "agent", sessionId, taskId, agentVersion: agentVersion ?? "" },
|
|
21894
21954
|
auth: { token },
|
|
@@ -21904,6 +21964,48 @@ var WSClient = class {
|
|
|
21904
21964
|
this.setupListeners(callbacks);
|
|
21905
21965
|
}
|
|
21906
21966
|
socket;
|
|
21967
|
+
/** Stable id for this agent process; fences stale heartbeats server-side. */
|
|
21968
|
+
agentSessionId = (0, import_node_crypto2.randomUUID)();
|
|
21969
|
+
/** Monotonic heartbeat sequence — advances on every hello + heartbeat. */
|
|
21970
|
+
heartbeatSeq = 0;
|
|
21971
|
+
heartbeatTimer = null;
|
|
21972
|
+
agentVersion;
|
|
21973
|
+
getRunState;
|
|
21974
|
+
currentRunState() {
|
|
21975
|
+
try {
|
|
21976
|
+
return this.getRunState?.() ?? { idle: true, activeRunIds: [] };
|
|
21977
|
+
} catch {
|
|
21978
|
+
return { idle: true, activeRunIds: [] };
|
|
21979
|
+
}
|
|
21980
|
+
}
|
|
21981
|
+
buildHeartbeat() {
|
|
21982
|
+
this.heartbeatSeq += 1;
|
|
21983
|
+
return {
|
|
21984
|
+
agentSessionId: this.agentSessionId,
|
|
21985
|
+
seq: this.heartbeatSeq,
|
|
21986
|
+
protocolVersion: AGENT_LIVENESS_PROTOCOL_VERSION,
|
|
21987
|
+
runState: this.currentRunState(),
|
|
21988
|
+
agentVersion: this.agentVersion || void 0
|
|
21989
|
+
};
|
|
21990
|
+
}
|
|
21991
|
+
/** Emit `agent.hello` on (re)connect and (re)start the heartbeat interval. */
|
|
21992
|
+
startHeartbeat() {
|
|
21993
|
+
if (this.socket.connected) {
|
|
21994
|
+
this.socket.emit("agent.hello", this.buildHeartbeat());
|
|
21995
|
+
}
|
|
21996
|
+
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
|
21997
|
+
this.heartbeatTimer = setInterval(() => {
|
|
21998
|
+
if (!this.socket.connected) return;
|
|
21999
|
+
this.socket.emit("agent.heartbeat", this.buildHeartbeat());
|
|
22000
|
+
}, AGENT_HEARTBEAT_INTERVAL_MS);
|
|
22001
|
+
this.heartbeatTimer.unref?.();
|
|
22002
|
+
}
|
|
22003
|
+
stopHeartbeat() {
|
|
22004
|
+
if (this.heartbeatTimer) {
|
|
22005
|
+
clearInterval(this.heartbeatTimer);
|
|
22006
|
+
this.heartbeatTimer = null;
|
|
22007
|
+
}
|
|
22008
|
+
}
|
|
21907
22009
|
emitEvent(event) {
|
|
21908
22010
|
this.socket.emit("agent_event", event);
|
|
21909
22011
|
}
|
|
@@ -21935,17 +22037,27 @@ var WSClient = class {
|
|
|
21935
22037
|
}
|
|
21936
22038
|
close() {
|
|
21937
22039
|
this.lifecycle?.info("sandbox_agent_ws_close_requested");
|
|
22040
|
+
this.stopHeartbeat();
|
|
21938
22041
|
this.socket.disconnect();
|
|
21939
22042
|
}
|
|
21940
22043
|
setupListeners(callbacks) {
|
|
21941
22044
|
this.socket.on("connect", () => {
|
|
21942
22045
|
this.lifecycle?.info("sandbox_agent_ws_socket_connected", { socketId: this.socket.id });
|
|
22046
|
+
this.startHeartbeat();
|
|
21943
22047
|
callbacks.onConnect?.();
|
|
21944
22048
|
});
|
|
21945
22049
|
this.socket.on("disconnect", (reason) => {
|
|
21946
22050
|
this.lifecycle?.info("sandbox_agent_ws_socket_disconnected", { reason });
|
|
22051
|
+
this.stopHeartbeat();
|
|
21947
22052
|
callbacks.onDisconnect?.(reason);
|
|
21948
22053
|
});
|
|
22054
|
+
this.socket.on("agent.probe", (_data, ack) => {
|
|
22055
|
+
ack?.({
|
|
22056
|
+
agentSessionId: this.agentSessionId,
|
|
22057
|
+
seq: this.heartbeatSeq,
|
|
22058
|
+
protocolVersion: AGENT_LIVENESS_PROTOCOL_VERSION
|
|
22059
|
+
});
|
|
22060
|
+
});
|
|
21949
22061
|
this.socket.on("connect_error", (error) => {
|
|
21950
22062
|
this.lifecycle?.warn("sandbox_agent_ws_socket_connect_error", {
|
|
21951
22063
|
error: error instanceof Error ? error : new Error(String(error))
|
|
@@ -22110,7 +22222,9 @@ async function runSandbox(config) {
|
|
|
22110
22222
|
}
|
|
22111
22223
|
},
|
|
22112
22224
|
onConnect: () => lifecycle.info("sandbox_agent_ws_connected"),
|
|
22113
|
-
onDisconnect: (reason) => lifecycle.info("sandbox_agent_ws_disconnected", { reason })
|
|
22225
|
+
onDisconnect: (reason) => lifecycle.info("sandbox_agent_ws_disconnected", { reason }),
|
|
22226
|
+
// Liveness heartbeat run state: a run is active while CoreAgent is executing.
|
|
22227
|
+
getRunState: () => currentAgent ? { idle: false, activeRunIds: currentRunId ? [currentRunId] : [] } : { idle: true, activeRunIds: [] }
|
|
22114
22228
|
},
|
|
22115
22229
|
AGENT_VERSION,
|
|
22116
22230
|
lifecycle
|
|
@@ -22133,7 +22247,7 @@ async function runSandbox(config) {
|
|
|
22133
22247
|
let activeContextWindow = config.contextWindow;
|
|
22134
22248
|
let activeEffortLevel = config.effortLevel;
|
|
22135
22249
|
let activeMode = config.mode || "agent";
|
|
22136
|
-
let
|
|
22250
|
+
let currentAlanMcp;
|
|
22137
22251
|
while (!stopped) {
|
|
22138
22252
|
if (currentTask?.trim()) {
|
|
22139
22253
|
const agent = new CoreAgent(presenter, {
|
|
@@ -22167,8 +22281,8 @@ async function runSandbox(config) {
|
|
|
22167
22281
|
model: activeModel,
|
|
22168
22282
|
maxIterations: currentMaxIterations
|
|
22169
22283
|
});
|
|
22170
|
-
if (
|
|
22171
|
-
const registration =
|
|
22284
|
+
if (currentAlanMcp) {
|
|
22285
|
+
const registration = ensureAlanMcpRegistered(activeBackendKind, currentAlanMcp);
|
|
22172
22286
|
if (registration.ok) {
|
|
22173
22287
|
lifecycle.info("sandbox_agent_mcp_registered", {
|
|
22174
22288
|
backendKind: activeBackendKind,
|
|
@@ -22180,18 +22294,18 @@ async function runSandbox(config) {
|
|
|
22180
22294
|
error: registration.error
|
|
22181
22295
|
});
|
|
22182
22296
|
presenter.onLog(
|
|
22183
|
-
`[sandbox]
|
|
22297
|
+
`[sandbox] Alan MCP registration failed \u2014 Alan tools may be unavailable this run: ${registration.error}`
|
|
22184
22298
|
);
|
|
22185
22299
|
}
|
|
22186
22300
|
} else {
|
|
22187
|
-
const check2 =
|
|
22301
|
+
const check2 = verifyAlanMcpRegistered(activeBackendKind);
|
|
22188
22302
|
if (!check2.ok) {
|
|
22189
22303
|
lifecycle.warn("sandbox_agent_mcp_config_missing", {
|
|
22190
22304
|
backendKind: activeBackendKind,
|
|
22191
22305
|
missing: check2.missing
|
|
22192
22306
|
});
|
|
22193
22307
|
presenter.onLog(
|
|
22194
|
-
`[sandbox]
|
|
22308
|
+
`[sandbox] Alan MCP config missing for ${activeBackendKind} \u2014 Alan tools may be unavailable this run`
|
|
22195
22309
|
);
|
|
22196
22310
|
}
|
|
22197
22311
|
}
|
|
@@ -22303,8 +22417,8 @@ async function runSandbox(config) {
|
|
|
22303
22417
|
if (nextPayload.mode) {
|
|
22304
22418
|
activeMode = nextPayload.mode;
|
|
22305
22419
|
}
|
|
22306
|
-
if (nextPayload.
|
|
22307
|
-
|
|
22420
|
+
if (nextPayload.alanMcp !== void 0) {
|
|
22421
|
+
currentAlanMcp = nextPayload.alanMcp;
|
|
22308
22422
|
}
|
|
22309
22423
|
if (nextPayload.taskMeta !== void 0) {
|
|
22310
22424
|
currentTaskMeta = nextPayload.taskMeta;
|
|
@@ -22353,26 +22467,26 @@ async function runSandbox(config) {
|
|
|
22353
22467
|
|
|
22354
22468
|
// src/index.ts
|
|
22355
22469
|
async function runSessionFromEnv() {
|
|
22356
|
-
const wsUrl = process.env.
|
|
22357
|
-
const sessionId = process.env.
|
|
22358
|
-
const taskId = process.env.
|
|
22359
|
-
const sessionToken = process.env.
|
|
22360
|
-
const task = process.env.
|
|
22361
|
-
const teamId = process.env.
|
|
22362
|
-
const projectPath = process.env.
|
|
22363
|
-
const backendKind = process.env.
|
|
22364
|
-
const agentId = process.env.
|
|
22365
|
-
const agentPrompt = process.env.
|
|
22366
|
-
const mode = process.env.
|
|
22367
|
-
const model = process.env.
|
|
22368
|
-
const contextWindow = process.env.
|
|
22369
|
-
const effortLevel = process.env.
|
|
22370
|
-
const providerSessionId = process.env.
|
|
22371
|
-
const workflowId = process.env.
|
|
22372
|
-
const workflowExecutionId = process.env.
|
|
22373
|
-
const sandboxId = process.env.
|
|
22374
|
-
const provider = process.env.
|
|
22375
|
-
const runId = process.env.
|
|
22470
|
+
const wsUrl = process.env.ALAN_WS_URL;
|
|
22471
|
+
const sessionId = process.env.ALAN_SESSION_ID;
|
|
22472
|
+
const taskId = process.env.ALAN_TASK_ID;
|
|
22473
|
+
const sessionToken = process.env.ALAN_SESSION_TOKEN;
|
|
22474
|
+
const task = process.env.ALAN_TASK;
|
|
22475
|
+
const teamId = process.env.ALAN_TEAM_ID || void 0;
|
|
22476
|
+
const projectPath = process.env.ALAN_PROJECT_PATH || "/home/user/workspace";
|
|
22477
|
+
const backendKind = process.env.ALAN_BACKEND_KIND || "claude_cli";
|
|
22478
|
+
const agentId = process.env.ALAN_AGENT_ID || void 0;
|
|
22479
|
+
const agentPrompt = process.env.ALAN_AGENT_PROMPT || void 0;
|
|
22480
|
+
const mode = process.env.ALAN_MODE || "agent";
|
|
22481
|
+
const model = process.env.ALAN_MODEL;
|
|
22482
|
+
const contextWindow = process.env.ALAN_CONTEXT_WINDOW || void 0;
|
|
22483
|
+
const effortLevel = process.env.ALAN_EFFORT_LEVEL || void 0;
|
|
22484
|
+
const providerSessionId = process.env.ALAN_PROVIDER_SESSION_ID || void 0;
|
|
22485
|
+
const workflowId = process.env.ALAN_WORKFLOW_ID || void 0;
|
|
22486
|
+
const workflowExecutionId = process.env.ALAN_WORKFLOW_EXECUTION_ID || void 0;
|
|
22487
|
+
const sandboxId = process.env.ALAN_SANDBOX_ID || void 0;
|
|
22488
|
+
const provider = process.env.ALAN_SANDBOX_PROVIDER || void 0;
|
|
22489
|
+
const runId = process.env.ALAN_RUN_ID || void 0;
|
|
22376
22490
|
const lifecycle = new AgentLifecycleLogger(lifecycleContextFromEnv(process.env));
|
|
22377
22491
|
if (!wsUrl || !sessionId || !taskId || !sessionToken || task == null) {
|
|
22378
22492
|
lifecycle.error("sandbox_agent_bootstrap_missing_env", {
|
|
@@ -22383,7 +22497,7 @@ async function runSessionFromEnv() {
|
|
|
22383
22497
|
hasTask: task != null
|
|
22384
22498
|
});
|
|
22385
22499
|
throw new Error(
|
|
22386
|
-
"run-session is an internal
|
|
22500
|
+
"run-session is an internal Alan sandbox/session command and must be launched by Alan with session env vars. Missing required env vars: ALAN_WS_URL, ALAN_SESSION_ID, ALAN_TASK_ID, ALAN_SESSION_TOKEN, ALAN_TASK"
|
|
22387
22501
|
);
|
|
22388
22502
|
}
|
|
22389
22503
|
lifecycle.info("sandbox_agent_process_start", {
|