@alan-ai-hq/agent-manager 0.1.91 → 0.1.92
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 +289 -53
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -3404,7 +3404,7 @@ var require_websocket = __commonJS({
|
|
|
3404
3404
|
var http2 = require("http");
|
|
3405
3405
|
var net = require("net");
|
|
3406
3406
|
var tls = require("tls");
|
|
3407
|
-
var { randomBytes: randomBytes13, createHash:
|
|
3407
|
+
var { randomBytes: randomBytes13, createHash: createHash18 } = require("crypto");
|
|
3408
3408
|
var { Duplex, Readable: Readable2 } = require("stream");
|
|
3409
3409
|
var { URL: URL2 } = 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 = createHash18("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: createHash18 } = 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 = createHash18("sha1").update(key + GUID).digest("base64");
|
|
4729
4729
|
const headers = [
|
|
4730
4730
|
"HTTP/1.1 101 Switching Protocols",
|
|
4731
4731
|
"Upgrade: websocket",
|
|
@@ -15451,7 +15451,7 @@ function describeError(error61) {
|
|
|
15451
15451
|
}
|
|
15452
15452
|
|
|
15453
15453
|
// src/version.ts
|
|
15454
|
-
var AGENT_VERSION = "0.1.
|
|
15454
|
+
var AGENT_VERSION = "0.1.92";
|
|
15455
15455
|
|
|
15456
15456
|
// src/daemon-worktree.ts
|
|
15457
15457
|
var import_node_child_process3 = require("child_process");
|
|
@@ -36003,6 +36003,42 @@ var import_fs = require("fs");
|
|
|
36003
36003
|
var import_os = require("os");
|
|
36004
36004
|
var import_path = require("path");
|
|
36005
36005
|
|
|
36006
|
+
// ../shared/dist/utils/workflow-tools-filter.js
|
|
36007
|
+
var WORKFLOW_ALWAYS_ALLOWED_BUILTIN_TOOLS = [
|
|
36008
|
+
"search_context",
|
|
36009
|
+
"create_test_report",
|
|
36010
|
+
"create_plan",
|
|
36011
|
+
"create_document_artifact",
|
|
36012
|
+
"upsert_prototype_version",
|
|
36013
|
+
"list_artifacts",
|
|
36014
|
+
"get_artifact",
|
|
36015
|
+
"list_prototypes",
|
|
36016
|
+
"get_prototype"
|
|
36017
|
+
];
|
|
36018
|
+
function createWorkflowToolsFilter(workflowTools) {
|
|
36019
|
+
const hasFilter = !!workflowTools && workflowTools.length > 0;
|
|
36020
|
+
if (!hasFilter) {
|
|
36021
|
+
return {
|
|
36022
|
+
hasFilter: false,
|
|
36023
|
+
isMcpServerAllowed: () => true,
|
|
36024
|
+
resolveAllowedBuiltinTools: () => null
|
|
36025
|
+
};
|
|
36026
|
+
}
|
|
36027
|
+
const tools = workflowTools;
|
|
36028
|
+
const mcpServerIds = new Set(tools.filter((t) => t.type === "mcp").map((t) => t.id));
|
|
36029
|
+
const builtinToolIds = tools.filter((t) => t.type === "builtin" || t.type === "integration").map((t) => t.id);
|
|
36030
|
+
return {
|
|
36031
|
+
hasFilter: true,
|
|
36032
|
+
isMcpServerAllowed: (serverName) => mcpServerIds.has(serverName),
|
|
36033
|
+
resolveAllowedBuiltinTools: () => {
|
|
36034
|
+
const merged = new Set(builtinToolIds);
|
|
36035
|
+
for (const id of WORKFLOW_ALWAYS_ALLOWED_BUILTIN_TOOLS)
|
|
36036
|
+
merged.add(id);
|
|
36037
|
+
return [...merged];
|
|
36038
|
+
}
|
|
36039
|
+
};
|
|
36040
|
+
}
|
|
36041
|
+
|
|
36006
36042
|
// ../shared/dist/agent/agent-definitions.js
|
|
36007
36043
|
var COORDINATOR_PROMPT = `## You are the Orchestrator
|
|
36008
36044
|
|
|
@@ -36490,6 +36526,34 @@ function buildAlanMcpServers(registration) {
|
|
|
36490
36526
|
}
|
|
36491
36527
|
};
|
|
36492
36528
|
}
|
|
36529
|
+
var ALAN_RUN_REFERENCE_ENV = "ALAN_RUN_REFERENCE";
|
|
36530
|
+
var MCP_CONFIG_KEY = /^[A-Za-z0-9_-]+$/;
|
|
36531
|
+
function isExternalMcpServerName(name) {
|
|
36532
|
+
return MCP_CONFIG_KEY.test(name) && name !== "alan";
|
|
36533
|
+
}
|
|
36534
|
+
function isMcpConfigKey(name) {
|
|
36535
|
+
return MCP_CONFIG_KEY.test(name);
|
|
36536
|
+
}
|
|
36537
|
+
var CURSOR_RUN_REFERENCE_HEADER_VALUE = `\${env:${ALAN_RUN_REFERENCE_ENV}}`;
|
|
36538
|
+
function toCursorMcpServers(src) {
|
|
36539
|
+
const out = {};
|
|
36540
|
+
for (const [name, raw] of Object.entries(src)) {
|
|
36541
|
+
if (!raw || typeof raw !== "object")
|
|
36542
|
+
continue;
|
|
36543
|
+
const s = raw;
|
|
36544
|
+
const isHttp = typeof s.type === "string" && s.type === "http" || typeof s.url === "string";
|
|
36545
|
+
if (!isHttp) {
|
|
36546
|
+
out[name] = s;
|
|
36547
|
+
continue;
|
|
36548
|
+
}
|
|
36549
|
+
const headers = Object.fromEntries(Object.entries(s.headers ?? {}).filter(([key]) => key.toLowerCase() !== "x-alan-run-reference"));
|
|
36550
|
+
out[name] = {
|
|
36551
|
+
...s,
|
|
36552
|
+
headers: { ...headers, "x-alan-run-reference": CURSOR_RUN_REFERENCE_HEADER_VALUE }
|
|
36553
|
+
};
|
|
36554
|
+
}
|
|
36555
|
+
return out;
|
|
36556
|
+
}
|
|
36493
36557
|
function toFactoryMcpServers(src) {
|
|
36494
36558
|
const out = {};
|
|
36495
36559
|
for (const [name, raw] of Object.entries(src)) {
|
|
@@ -36634,7 +36698,10 @@ function renderAlanMcpConfigFiles(mcpServers, home) {
|
|
|
36634
36698
|
mergeJsonKey: "mcpServers"
|
|
36635
36699
|
},
|
|
36636
36700
|
{ path: `${home}/.codex/config.toml`, content: toCodexMcpToml(mcpServers) },
|
|
36637
|
-
{
|
|
36701
|
+
{
|
|
36702
|
+
path: `${home}/.cursor/mcp.json`,
|
|
36703
|
+
content: JSON.stringify({ mcpServers: toCursorMcpServers(mcpServers) })
|
|
36704
|
+
},
|
|
36638
36705
|
{
|
|
36639
36706
|
path: `${home}/.factory/mcp.json`,
|
|
36640
36707
|
content: JSON.stringify({ mcpServers: toFactoryMcpServers(mcpServers) })
|
|
@@ -38302,6 +38369,7 @@ var import_os4 = require("os");
|
|
|
38302
38369
|
var import_path5 = require("path");
|
|
38303
38370
|
var import_url = require("url");
|
|
38304
38371
|
var import_crypto4 = require("crypto");
|
|
38372
|
+
var import_crypto5 = require("crypto");
|
|
38305
38373
|
var import_fs6 = require("fs");
|
|
38306
38374
|
var import_os5 = require("os");
|
|
38307
38375
|
var import_path6 = require("path");
|
|
@@ -38319,14 +38387,16 @@ var import_path9 = require("path");
|
|
|
38319
38387
|
var import_fs10 = require("fs");
|
|
38320
38388
|
var import_os9 = require("os");
|
|
38321
38389
|
var import_path10 = require("path");
|
|
38322
|
-
var
|
|
38390
|
+
var import_crypto6 = require("crypto");
|
|
38323
38391
|
var import_readline2 = require("readline");
|
|
38324
38392
|
var import_url2 = require("url");
|
|
38325
|
-
var
|
|
38393
|
+
var import_crypto7 = require("crypto");
|
|
38326
38394
|
var import_fs11 = require("fs");
|
|
38327
38395
|
var import_path11 = require("path");
|
|
38328
|
-
var ALAN_RUN_REFERENCE_ENV = "ALAN_RUN_REFERENCE";
|
|
38329
38396
|
var ALAN_MCP_URL_ENV = "ALAN_MCP_URL";
|
|
38397
|
+
function deliversRunReferenceViaEnv(backendKind) {
|
|
38398
|
+
return backendKind === "cursor_agent_cli";
|
|
38399
|
+
}
|
|
38330
38400
|
var ALAN_AGENT_ENTRY_ENV = "ALAN_AGENT_ENTRY";
|
|
38331
38401
|
var ALAN_NODE_EXECUTABLE_ENV = "ALAN_NODE_EXECUTABLE";
|
|
38332
38402
|
function usesProcessLocalManagedMcp(backendKind) {
|
|
@@ -41091,6 +41161,65 @@ function createAntigravityCliBackend(command = "agy", defaultArgs = []) {
|
|
|
41091
41161
|
}
|
|
41092
41162
|
};
|
|
41093
41163
|
}
|
|
41164
|
+
function isWorkflowRun(config2) {
|
|
41165
|
+
return Boolean(config2.workflowId || config2.workflowExecutionId);
|
|
41166
|
+
}
|
|
41167
|
+
function selectExternalMcpServers(config2) {
|
|
41168
|
+
const selected = {};
|
|
41169
|
+
const filter = isWorkflowRun(config2) ? createWorkflowToolsFilter(config2.workflowTools) : null;
|
|
41170
|
+
if (filter && !filter.hasFilter) return selected;
|
|
41171
|
+
for (const [name, server] of Object.entries(config2.externalMcpServers ?? {})) {
|
|
41172
|
+
if (!isExternalMcpServerName(name)) continue;
|
|
41173
|
+
if (filter && !filter.isMcpServerAllowed(name)) continue;
|
|
41174
|
+
selected[name] = server;
|
|
41175
|
+
}
|
|
41176
|
+
return selected;
|
|
41177
|
+
}
|
|
41178
|
+
function headerEnvName(server, header) {
|
|
41179
|
+
const fingerprint = (0, import_crypto5.createHash)("sha256").update(`${server}\0${header}`).digest("hex").slice(0, 12).toUpperCase();
|
|
41180
|
+
return `ALAN_MCP_HEADER_${fingerprint}`;
|
|
41181
|
+
}
|
|
41182
|
+
function planExternalMcpDelivery(config2, processEnv) {
|
|
41183
|
+
const verbatim = selectExternalMcpServers(config2);
|
|
41184
|
+
const servers = {};
|
|
41185
|
+
const env = {};
|
|
41186
|
+
for (const [name, server] of Object.entries(verbatim)) {
|
|
41187
|
+
if (server.url && server.type !== "stdio") {
|
|
41188
|
+
const headerEnv = {};
|
|
41189
|
+
for (const [header, value2] of Object.entries(server.headers ?? {})) {
|
|
41190
|
+
if (!isMcpConfigKey(header)) continue;
|
|
41191
|
+
const variable = headerEnvName(name, header);
|
|
41192
|
+
env[variable] = value2;
|
|
41193
|
+
headerEnv[header] = variable;
|
|
41194
|
+
}
|
|
41195
|
+
servers[name] = {
|
|
41196
|
+
type: server.type === "sse" ? "sse" : "http",
|
|
41197
|
+
url: server.url,
|
|
41198
|
+
...Object.keys(headerEnv).length ? { headerEnv } : {}
|
|
41199
|
+
};
|
|
41200
|
+
} else if (server.command) {
|
|
41201
|
+
const envKeys = [];
|
|
41202
|
+
for (const [key, value2] of Object.entries(server.env ?? {})) {
|
|
41203
|
+
if (!isMcpConfigKey(key)) continue;
|
|
41204
|
+
if (key in processEnv || key in env && env[key] !== value2) {
|
|
41205
|
+
console.warn(
|
|
41206
|
+
`[external-mcp] Not forwarding env ${key} for MCP server ${name}: it is already set for this run`
|
|
41207
|
+
);
|
|
41208
|
+
continue;
|
|
41209
|
+
}
|
|
41210
|
+
env[key] = value2;
|
|
41211
|
+
envKeys.push(key);
|
|
41212
|
+
}
|
|
41213
|
+
servers[name] = {
|
|
41214
|
+
type: "stdio",
|
|
41215
|
+
command: server.command,
|
|
41216
|
+
...server.args?.length ? { args: server.args } : {},
|
|
41217
|
+
...envKeys.length ? { envKeys } : {}
|
|
41218
|
+
};
|
|
41219
|
+
}
|
|
41220
|
+
}
|
|
41221
|
+
return { servers, env, verbatim };
|
|
41222
|
+
}
|
|
41094
41223
|
function resolveClaudeHome(env, variant = "claude") {
|
|
41095
41224
|
if (variant === "supatest") {
|
|
41096
41225
|
return (0, import_path6.join)((0, import_os5.homedir)(), ".supatest", "claude-internal");
|
|
@@ -41525,22 +41654,40 @@ function buildClaudeModelArg(baseModel, selectedContextWindow) {
|
|
|
41525
41654
|
if (selectedContextWindow === "1m") return `${baseModel}[1m]`;
|
|
41526
41655
|
return baseModel;
|
|
41527
41656
|
}
|
|
41528
|
-
function buildClaudeManagedMcpArgs(registration,
|
|
41529
|
-
const
|
|
41530
|
-
const
|
|
41531
|
-
|
|
41657
|
+
function buildClaudeManagedMcpArgs(registration, options = {}) {
|
|
41658
|
+
const mcpServers = {};
|
|
41659
|
+
for (const [name, server] of Object.entries(options.externalServers ?? {})) {
|
|
41660
|
+
if (server.type === "stdio") {
|
|
41661
|
+
mcpServers[name] = {
|
|
41662
|
+
type: "stdio",
|
|
41663
|
+
command: server.command,
|
|
41664
|
+
...server.args?.length ? { args: server.args } : {},
|
|
41665
|
+
...server.envKeys?.length ? { env: Object.fromEntries(server.envKeys.map((key) => [key, `\${${key}}`])) } : {}
|
|
41666
|
+
};
|
|
41667
|
+
} else {
|
|
41668
|
+
mcpServers[name] = {
|
|
41669
|
+
type: server.type,
|
|
41670
|
+
url: server.url,
|
|
41671
|
+
...server.headerEnv ? {
|
|
41672
|
+
headers: Object.fromEntries(
|
|
41673
|
+
Object.entries(server.headerEnv).map(([header, variable]) => [
|
|
41674
|
+
header,
|
|
41675
|
+
`\${${variable}}`
|
|
41676
|
+
])
|
|
41677
|
+
)
|
|
41678
|
+
} : {}
|
|
41679
|
+
};
|
|
41680
|
+
}
|
|
41681
|
+
}
|
|
41682
|
+
mcpServers.alan = {
|
|
41683
|
+
type: "http",
|
|
41684
|
+
url: registration.url,
|
|
41685
|
+
headers: { "x-alan-run-reference": `\${${ALAN_RUN_REFERENCE_ENV}}` }
|
|
41686
|
+
};
|
|
41532
41687
|
return [
|
|
41533
|
-
"--strict-mcp-config",
|
|
41688
|
+
...options.strict ? ["--strict-mcp-config"] : [],
|
|
41534
41689
|
"--mcp-config",
|
|
41535
|
-
JSON.stringify({
|
|
41536
|
-
mcpServers: {
|
|
41537
|
-
[managedMcpServerName(registration)]: {
|
|
41538
|
-
type: "stdio",
|
|
41539
|
-
command: node2,
|
|
41540
|
-
args: [entry, "mcp-proxy"]
|
|
41541
|
-
}
|
|
41542
|
-
}
|
|
41543
|
-
})
|
|
41690
|
+
JSON.stringify({ mcpServers })
|
|
41544
41691
|
];
|
|
41545
41692
|
}
|
|
41546
41693
|
function createClaudeCliBackend(command = "claude", defaultArgs = []) {
|
|
@@ -41549,11 +41696,12 @@ function createClaudeCliBackend(command = "claude", defaultArgs = []) {
|
|
|
41549
41696
|
supportTier: "structured",
|
|
41550
41697
|
async run(context) {
|
|
41551
41698
|
const managedRegistration = context.config.alanMcp;
|
|
41699
|
+
const externalMcp = managedRegistration ? planExternalMcpDelivery(context.config, context.env) : void 0;
|
|
41552
41700
|
const runContext = managedRegistration ? {
|
|
41553
41701
|
...context,
|
|
41554
41702
|
env: {
|
|
41555
41703
|
...context.env,
|
|
41556
|
-
|
|
41704
|
+
...externalMcp?.env,
|
|
41557
41705
|
[ALAN_RUN_REFERENCE_ENV]: requireManagedRunReference(managedRegistration)
|
|
41558
41706
|
}
|
|
41559
41707
|
} : context;
|
|
@@ -41567,7 +41715,12 @@ function createClaudeCliBackend(command = "claude", defaultArgs = []) {
|
|
|
41567
41715
|
getClaudePermissionMode(context.config)
|
|
41568
41716
|
];
|
|
41569
41717
|
if (managedRegistration) {
|
|
41570
|
-
args.push(
|
|
41718
|
+
args.push(
|
|
41719
|
+
...buildClaudeManagedMcpArgs(managedRegistration, {
|
|
41720
|
+
strict: isWorkflowRun(context.config),
|
|
41721
|
+
externalServers: externalMcp?.servers
|
|
41722
|
+
})
|
|
41723
|
+
);
|
|
41571
41724
|
}
|
|
41572
41725
|
const disallowedTools = getClaudeDisallowedTools(context.config);
|
|
41573
41726
|
if (disallowedTools.length > 0) {
|
|
@@ -42796,31 +42949,59 @@ function buildCodexEffortArgs(selectedEffortLevel, options) {
|
|
|
42796
42949
|
}
|
|
42797
42950
|
var CODEX_STARTUP_TIMEOUT_MS = 3e5;
|
|
42798
42951
|
var ALAN_MCP_STARTUP_TIMEOUT_SEC = 30;
|
|
42799
|
-
function buildCodexManagedMcpArgs(registration) {
|
|
42800
|
-
const serverName = managedMcpServerName(registration);
|
|
42952
|
+
function buildCodexManagedMcpArgs(registration, options = {}) {
|
|
42801
42953
|
return [
|
|
42802
|
-
|
|
42954
|
+
// Workflow runs keep the exclusive config: their tool set is a policy,
|
|
42955
|
+
// not the user's own server list.
|
|
42956
|
+
...options.strict ? ["--ignore-user-config"] : [],
|
|
42803
42957
|
"-c",
|
|
42804
|
-
`mcp_servers
|
|
42958
|
+
`mcp_servers.alan.url=${JSON.stringify(registration.url)}`,
|
|
42805
42959
|
"-c",
|
|
42806
|
-
`mcp_servers
|
|
42960
|
+
`mcp_servers.alan.env_http_headers.x-alan-run-reference=${JSON.stringify(ALAN_RUN_REFERENCE_ENV)}`,
|
|
42807
42961
|
"-c",
|
|
42808
|
-
|
|
42962
|
+
"mcp_servers.alan.required=true",
|
|
42809
42963
|
"-c",
|
|
42810
|
-
`mcp_servers
|
|
42964
|
+
`mcp_servers.alan.startup_timeout_sec=${ALAN_MCP_STARTUP_TIMEOUT_SEC}`
|
|
42811
42965
|
];
|
|
42812
42966
|
}
|
|
42967
|
+
function buildCodexExternalMcpArgs(servers) {
|
|
42968
|
+
const args = [];
|
|
42969
|
+
for (const [name, server] of Object.entries(servers ?? {})) {
|
|
42970
|
+
const key = `mcp_servers.${name}`;
|
|
42971
|
+
if (server.type === "stdio") {
|
|
42972
|
+
args.push("-c", `${key}.command=${JSON.stringify(server.command)}`);
|
|
42973
|
+
if (server.args?.length) args.push("-c", `${key}.args=${JSON.stringify(server.args)}`);
|
|
42974
|
+
if (server.envKeys?.length) {
|
|
42975
|
+
args.push("-c", `${key}.env_vars=${JSON.stringify(server.envKeys)}`);
|
|
42976
|
+
}
|
|
42977
|
+
} else {
|
|
42978
|
+
if (server.type === "sse") continue;
|
|
42979
|
+
args.push("-c", `${key}.url=${JSON.stringify(server.url)}`);
|
|
42980
|
+
for (const [header, variable] of Object.entries(server.headerEnv ?? {})) {
|
|
42981
|
+
args.push("-c", `${key}.env_http_headers.${header}=${JSON.stringify(variable)}`);
|
|
42982
|
+
}
|
|
42983
|
+
}
|
|
42984
|
+
}
|
|
42985
|
+
return args;
|
|
42986
|
+
}
|
|
42813
42987
|
function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
|
|
42814
42988
|
return {
|
|
42815
42989
|
kind: "codex_app_server",
|
|
42816
42990
|
supportTier: "structured",
|
|
42817
42991
|
async run(context) {
|
|
42818
42992
|
const managedRegistration = context.config.alanMcp;
|
|
42819
|
-
const
|
|
42993
|
+
const externalMcp = managedRegistration ? planExternalMcpDelivery(context.config, context.env) : void 0;
|
|
42994
|
+
const managedMcpArgs = managedRegistration ? [
|
|
42995
|
+
...buildCodexManagedMcpArgs(managedRegistration, {
|
|
42996
|
+
strict: isWorkflowRun(context.config)
|
|
42997
|
+
}),
|
|
42998
|
+
...buildCodexExternalMcpArgs(externalMcp?.servers)
|
|
42999
|
+
] : [];
|
|
42820
43000
|
const runContext = managedRegistration ? {
|
|
42821
43001
|
...context,
|
|
42822
43002
|
env: {
|
|
42823
43003
|
...context.env,
|
|
43004
|
+
...externalMcp?.env,
|
|
42824
43005
|
[ALAN_RUN_REFERENCE_ENV]: requireManagedRunReference(managedRegistration)
|
|
42825
43006
|
}
|
|
42826
43007
|
} : context;
|
|
@@ -43781,6 +43962,13 @@ function createCursorAgentCliBackend(command = "cursor-agent", defaultArgs = [])
|
|
|
43781
43962
|
context.cwd
|
|
43782
43963
|
);
|
|
43783
43964
|
const approveMcps = context.config.alanMcp ? await cliSupportsFlag(command, "--approve-mcps", context.env) : false;
|
|
43965
|
+
const runContext = context.config.alanMcp ? {
|
|
43966
|
+
...context,
|
|
43967
|
+
env: {
|
|
43968
|
+
...context.env,
|
|
43969
|
+
[ALAN_RUN_REFERENCE_ENV]: requireManagedRunReference(context.config.alanMcp)
|
|
43970
|
+
}
|
|
43971
|
+
} : context;
|
|
43784
43972
|
try {
|
|
43785
43973
|
return await createGenericCliBackend({
|
|
43786
43974
|
kind: "cursor_agent_cli",
|
|
@@ -43858,7 +44046,7 @@ function createCursorAgentCliBackend(command = "cursor-agent", defaultArgs = [])
|
|
|
43858
44046
|
return appendImagePathReferences(prompt, imageFiles);
|
|
43859
44047
|
},
|
|
43860
44048
|
parseStructuredLine: parseCursorStructuredLine
|
|
43861
|
-
}).run(
|
|
44049
|
+
}).run(runContext);
|
|
43862
44050
|
} finally {
|
|
43863
44051
|
cleanup();
|
|
43864
44052
|
}
|
|
@@ -44914,6 +45102,28 @@ function resolveKimiCliModelArg(model) {
|
|
|
44914
45102
|
if (trimmed.startsWith("claude-")) return void 0;
|
|
44915
45103
|
return trimmed;
|
|
44916
45104
|
}
|
|
45105
|
+
function buildKimiMcpConfig(registration, externalServers = {}) {
|
|
45106
|
+
const mcpServers = {};
|
|
45107
|
+
for (const [name, server] of Object.entries(externalServers)) {
|
|
45108
|
+
if (server.url && server.type !== "stdio") {
|
|
45109
|
+
mcpServers[name] = {
|
|
45110
|
+
url: server.url,
|
|
45111
|
+
...server.headers ? { headers: server.headers } : {}
|
|
45112
|
+
};
|
|
45113
|
+
} else if (server.command) {
|
|
45114
|
+
mcpServers[name] = {
|
|
45115
|
+
command: server.command,
|
|
45116
|
+
...server.args?.length ? { args: server.args } : {},
|
|
45117
|
+
...server.env ? { env: server.env } : {}
|
|
45118
|
+
};
|
|
45119
|
+
}
|
|
45120
|
+
}
|
|
45121
|
+
mcpServers[managedMcpServerName(registration)] = {
|
|
45122
|
+
url: registration.url,
|
|
45123
|
+
headers: { "x-alan-run-reference": requireManagedRunReference(registration) }
|
|
45124
|
+
};
|
|
45125
|
+
return { mcpServers };
|
|
45126
|
+
}
|
|
44917
45127
|
function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
|
|
44918
45128
|
return {
|
|
44919
45129
|
kind: "kimi_cli",
|
|
@@ -44925,14 +45135,9 @@ function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
|
|
|
44925
45135
|
if (registration && mcpConfigPath) {
|
|
44926
45136
|
(0, import_fs9.writeFileSync)(
|
|
44927
45137
|
mcpConfigPath,
|
|
44928
|
-
JSON.stringify(
|
|
44929
|
-
|
|
44930
|
-
|
|
44931
|
-
url: registration.url,
|
|
44932
|
-
headers: { "x-alan-run-reference": requireManagedRunReference(registration) }
|
|
44933
|
-
}
|
|
44934
|
-
}
|
|
44935
|
-
}),
|
|
45138
|
+
JSON.stringify(
|
|
45139
|
+
buildKimiMcpConfig(registration, selectExternalMcpServers(context.config))
|
|
45140
|
+
),
|
|
44936
45141
|
{ mode: 384 }
|
|
44937
45142
|
);
|
|
44938
45143
|
}
|
|
@@ -45459,7 +45664,7 @@ function leaseKeyFor(context) {
|
|
|
45459
45664
|
if (!conversationId) return null;
|
|
45460
45665
|
const runReference = context.config.alanMcp?.headers?.["x-alan-run-reference"];
|
|
45461
45666
|
if (!runReference) return `conv:${conversationId}`;
|
|
45462
|
-
const fingerprint = (0,
|
|
45667
|
+
const fingerprint = (0, import_crypto6.createHash)("sha256").update(runReference).digest("hex").slice(0, 16);
|
|
45463
45668
|
return `conv:${conversationId}|mcp:${fingerprint}`;
|
|
45464
45669
|
}
|
|
45465
45670
|
function isLeaseUsable(lease) {
|
|
@@ -46484,8 +46689,10 @@ var BaseMachineAgent = class _BaseMachineAgent {
|
|
|
46484
46689
|
*/
|
|
46485
46690
|
async beginMcpConfigCriticalSection(backend, context) {
|
|
46486
46691
|
const runHeaders = context.config.alanMcp?.headers;
|
|
46487
|
-
if (!runHeaders || usesProcessLocalManagedMcp(backend.kind)
|
|
46488
|
-
|
|
46692
|
+
if (!runHeaders || usesProcessLocalManagedMcp(backend.kind) || deliversRunReferenceViaEnv(backend.kind)) {
|
|
46693
|
+
return () => {
|
|
46694
|
+
};
|
|
46695
|
+
}
|
|
46489
46696
|
const releaseGate = await acquireMcpConfigWriteGate();
|
|
46490
46697
|
try {
|
|
46491
46698
|
const writtenClis = await syncAlanMcpSessionHeaders({
|
|
@@ -46498,7 +46705,11 @@ var BaseMachineAgent = class _BaseMachineAgent {
|
|
|
46498
46705
|
void this.presenter.onLog(`Synced Alan MCP session headers to ${writtenClis.join(", ")}`);
|
|
46499
46706
|
}
|
|
46500
46707
|
} catch (error61) {
|
|
46501
|
-
|
|
46708
|
+
releaseGate();
|
|
46709
|
+
throw new Error(
|
|
46710
|
+
`Alan could not write this run's MCP credential for ${backend.kind}, so the provider was not started: ${error61 instanceof Error ? error61.message : String(error61)}`,
|
|
46711
|
+
{ cause: error61 }
|
|
46712
|
+
);
|
|
46502
46713
|
}
|
|
46503
46714
|
return releaseGate;
|
|
46504
46715
|
}
|
|
@@ -46993,7 +47204,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
|
|
|
46993
47204
|
const { width, height } = readImageDimensions2(buffer, mimeType);
|
|
46994
47205
|
images.push({
|
|
46995
47206
|
type: "generated_image",
|
|
46996
|
-
id: (0,
|
|
47207
|
+
id: (0, import_crypto7.randomUUID)(),
|
|
46997
47208
|
filename: (0, import_path11.basename)(path2),
|
|
46998
47209
|
mimeType,
|
|
46999
47210
|
size: buffer.length,
|
|
@@ -47001,7 +47212,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
|
|
|
47001
47212
|
height,
|
|
47002
47213
|
data: buffer.toString("base64"),
|
|
47003
47214
|
sourcePath: path2,
|
|
47004
|
-
sourceHash: (0,
|
|
47215
|
+
sourceHash: (0, import_crypto7.createHash)("sha256").update(buffer).digest("hex"),
|
|
47005
47216
|
toolId,
|
|
47006
47217
|
ts: Date.now()
|
|
47007
47218
|
});
|
|
@@ -47033,7 +47244,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
|
|
|
47033
47244
|
media.push({
|
|
47034
47245
|
type: "session_media",
|
|
47035
47246
|
kind,
|
|
47036
|
-
id: (0,
|
|
47247
|
+
id: (0, import_crypto7.randomUUID)(),
|
|
47037
47248
|
filename: (0, import_path11.basename)(path2),
|
|
47038
47249
|
mimeType,
|
|
47039
47250
|
size: buffer.length,
|
|
@@ -47041,7 +47252,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
|
|
|
47041
47252
|
height: dimensions?.height,
|
|
47042
47253
|
data: buffer.toString("base64"),
|
|
47043
47254
|
sourcePath: path2,
|
|
47044
|
-
sourceHash: (0,
|
|
47255
|
+
sourceHash: (0, import_crypto7.createHash)("sha256").update(buffer).digest("hex"),
|
|
47045
47256
|
toolId,
|
|
47046
47257
|
ts: Date.now()
|
|
47047
47258
|
});
|
|
@@ -56805,7 +57016,12 @@ async function ensureAlanMcpRegistered(backendKind, registration, home = (0, imp
|
|
|
56805
57016
|
releaseLock();
|
|
56806
57017
|
}
|
|
56807
57018
|
}
|
|
56808
|
-
const fileOk =
|
|
57019
|
+
const fileOk = files.length > 0 && files.every(
|
|
57020
|
+
(file2) => registrationsMatch(
|
|
57021
|
+
readAlanMcpRegistration(file2.path),
|
|
57022
|
+
parseAlanMcpRegistration(file2.path, file2.content) ?? registration
|
|
57023
|
+
)
|
|
57024
|
+
);
|
|
56809
57025
|
if (!fileOk) {
|
|
56810
57026
|
const issue2 = {
|
|
56811
57027
|
code: "mcp_config_repair_required",
|
|
@@ -56979,7 +57195,8 @@ function hasUsableRegistrationCredential(headers) {
|
|
|
56979
57195
|
const normalized = new Map(
|
|
56980
57196
|
Object.entries(headers).map(([name, value2]) => [name.toLowerCase(), value2.trim()])
|
|
56981
57197
|
);
|
|
56982
|
-
|
|
57198
|
+
const reference = normalized.get("x-alan-run-reference") ?? "";
|
|
57199
|
+
return Boolean(reference && !reference.startsWith("${") || normalized.get("authorization"));
|
|
56983
57200
|
}
|
|
56984
57201
|
function readAlanMcpRegistration(path2) {
|
|
56985
57202
|
return parseAlanMcpRegistration(path2, (0, import_node_fs16.readFileSync)(path2, "utf8"));
|
|
@@ -75271,6 +75488,7 @@ async function handleAgentExecute(ctx, payload) {
|
|
|
75271
75488
|
prMeta: payload.prMeta,
|
|
75272
75489
|
conversationId: payload.conversationId,
|
|
75273
75490
|
alanMcp: payload.alanMcp,
|
|
75491
|
+
externalMcpServers: payload.externalMcpServers,
|
|
75274
75492
|
taskId: payload.taskId ?? payload.taskMeta?.id,
|
|
75275
75493
|
teamId: payload.teamId,
|
|
75276
75494
|
currentUser: payload.currentUser,
|
|
@@ -96809,6 +97027,7 @@ var WSClient = class {
|
|
|
96809
97027
|
providerSessionId: data.providerSessionId,
|
|
96810
97028
|
resumeFallbackContext: data.resumeFallbackContext,
|
|
96811
97029
|
backendKind: data.backendKind,
|
|
97030
|
+
providerApiKey: data.providerApiKey,
|
|
96812
97031
|
agentId: data.agentId,
|
|
96813
97032
|
agentPrompt: data.agentPrompt,
|
|
96814
97033
|
selectedModel: data.selectedModel,
|
|
@@ -96826,7 +97045,10 @@ var WSClient = class {
|
|
|
96826
97045
|
cloudEnvironmentId: data.cloudEnvironmentId,
|
|
96827
97046
|
conversationId: data.conversationId,
|
|
96828
97047
|
teamId: data.teamId,
|
|
96829
|
-
currentUser: data.currentUser
|
|
97048
|
+
currentUser: data.currentUser,
|
|
97049
|
+
terminalContextRefs: data.terminalContextRefs,
|
|
97050
|
+
terminalSnapshots: data.terminalSnapshots,
|
|
97051
|
+
externalMcpServers: data.externalMcpServers
|
|
96830
97052
|
};
|
|
96831
97053
|
const acceptDelivery = () => {
|
|
96832
97054
|
if (data.messageId) this.rememberAcceptedMessageId(data.messageId);
|
|
@@ -96850,6 +97072,9 @@ var WSClient = class {
|
|
|
96850
97072
|
this.socket.on("stop", () => {
|
|
96851
97073
|
callbacks.onStop();
|
|
96852
97074
|
});
|
|
97075
|
+
this.socket.on("agent.abort", (data) => {
|
|
97076
|
+
callbacks.onAbort?.({ runId: data?.runId, reason: data?.reason });
|
|
97077
|
+
});
|
|
96853
97078
|
this.socket.on("tool_response", (data) => {
|
|
96854
97079
|
if (data?.toolId && typeof data.response === "string") {
|
|
96855
97080
|
callbacks.onToolResponse?.(data.toolId, data.response);
|
|
@@ -96907,6 +97132,7 @@ async function runSandbox(config2) {
|
|
|
96907
97132
|
let currentTaskMeta;
|
|
96908
97133
|
let currentPrMeta;
|
|
96909
97134
|
let currentWorkflowTools;
|
|
97135
|
+
let currentExternalMcpServers;
|
|
96910
97136
|
let currentMaxIterations = config2.maxIterations ?? 50;
|
|
96911
97137
|
let currentTaskId = config2.taskId;
|
|
96912
97138
|
let currentConversationId = config2.sessionId;
|
|
@@ -97001,6 +97227,14 @@ async function runSandbox(config2) {
|
|
|
97001
97227
|
lifecycle.info("sandbox_agent_stop_received");
|
|
97002
97228
|
stopActiveAgent();
|
|
97003
97229
|
},
|
|
97230
|
+
onAbort: ({ runId, reason }) => {
|
|
97231
|
+
if (runId && currentRunId && runId !== currentRunId) {
|
|
97232
|
+
lifecycle.info("sandbox_agent_abort_ignored_stale_run", { runId, currentRunId });
|
|
97233
|
+
return;
|
|
97234
|
+
}
|
|
97235
|
+
lifecycle.info("sandbox_agent_abort_received", { runId, reason });
|
|
97236
|
+
stopActiveAgent(reason === "watchdog_timeout" ? "watchdog_timeout" : "user");
|
|
97237
|
+
},
|
|
97004
97238
|
onToolResponse: (toolId, response) => {
|
|
97005
97239
|
if (currentAgent) {
|
|
97006
97240
|
const sent = currentAgent.sendToolResponse(toolId, response);
|
|
@@ -97197,6 +97431,7 @@ async function runSandbox(config2) {
|
|
|
97197
97431
|
resumeFallbackContext,
|
|
97198
97432
|
taskMeta: currentTaskMeta,
|
|
97199
97433
|
prMeta: currentPrMeta,
|
|
97434
|
+
externalMcpServers: currentExternalMcpServers,
|
|
97200
97435
|
taskId: currentTaskId,
|
|
97201
97436
|
conversationId: currentConversationId,
|
|
97202
97437
|
alanMcp: currentAlanMcp,
|
|
@@ -97314,6 +97549,7 @@ async function runSandbox(config2) {
|
|
|
97314
97549
|
activeMode = nextPayload.mode;
|
|
97315
97550
|
}
|
|
97316
97551
|
currentAlanMcp = nextPayload.alanMcp;
|
|
97552
|
+
currentExternalMcpServers = nextPayload.externalMcpServers;
|
|
97317
97553
|
if (nextPayload.taskMeta !== void 0) {
|
|
97318
97554
|
currentTaskMeta = nextPayload.taskMeta;
|
|
97319
97555
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alan-ai-hq/agent-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.92",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Alan agent runtime — cloud sandbox and local daemon (alan-agent CLI)",
|
|
6
6
|
"bin": {
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"tsx": "^4.19.0",
|
|
28
28
|
"typescript": "~5.9.3",
|
|
29
29
|
"@alan-ai/agent-core": "0.1.0",
|
|
30
|
-
"@alan-ai/
|
|
31
|
-
"@alan-ai/
|
|
30
|
+
"@alan-ai/shared": "0.1.0",
|
|
31
|
+
"@alan-ai/sandbox-runtime-spec": "0.1.0"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "tsup",
|