@alan-ai-hq/agent-manager 0.1.90 → 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 +1256 -1010
- 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) {
|
|
@@ -42795,27 +42948,60 @@ function buildCodexEffortArgs(selectedEffortLevel, options) {
|
|
|
42795
42948
|
return ["-c", `model_reasoning_effort=${level}`];
|
|
42796
42949
|
}
|
|
42797
42950
|
var CODEX_STARTUP_TIMEOUT_MS = 3e5;
|
|
42798
|
-
|
|
42799
|
-
|
|
42951
|
+
var ALAN_MCP_STARTUP_TIMEOUT_SEC = 30;
|
|
42952
|
+
function buildCodexManagedMcpArgs(registration, options = {}) {
|
|
42800
42953
|
return [
|
|
42801
|
-
|
|
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"] : [],
|
|
42957
|
+
"-c",
|
|
42958
|
+
`mcp_servers.alan.url=${JSON.stringify(registration.url)}`,
|
|
42802
42959
|
"-c",
|
|
42803
|
-
`mcp_servers
|
|
42960
|
+
`mcp_servers.alan.env_http_headers.x-alan-run-reference=${JSON.stringify(ALAN_RUN_REFERENCE_ENV)}`,
|
|
42804
42961
|
"-c",
|
|
42805
|
-
|
|
42962
|
+
"mcp_servers.alan.required=true",
|
|
42963
|
+
"-c",
|
|
42964
|
+
`mcp_servers.alan.startup_timeout_sec=${ALAN_MCP_STARTUP_TIMEOUT_SEC}`
|
|
42806
42965
|
];
|
|
42807
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
|
+
}
|
|
42808
42987
|
function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
|
|
42809
42988
|
return {
|
|
42810
42989
|
kind: "codex_app_server",
|
|
42811
42990
|
supportTier: "structured",
|
|
42812
42991
|
async run(context) {
|
|
42813
42992
|
const managedRegistration = context.config.alanMcp;
|
|
42814
|
-
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
|
+
] : [];
|
|
42815
43000
|
const runContext = managedRegistration ? {
|
|
42816
43001
|
...context,
|
|
42817
43002
|
env: {
|
|
42818
43003
|
...context.env,
|
|
43004
|
+
...externalMcp?.env,
|
|
42819
43005
|
[ALAN_RUN_REFERENCE_ENV]: requireManagedRunReference(managedRegistration)
|
|
42820
43006
|
}
|
|
42821
43007
|
} : context;
|
|
@@ -43776,6 +43962,13 @@ function createCursorAgentCliBackend(command = "cursor-agent", defaultArgs = [])
|
|
|
43776
43962
|
context.cwd
|
|
43777
43963
|
);
|
|
43778
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;
|
|
43779
43972
|
try {
|
|
43780
43973
|
return await createGenericCliBackend({
|
|
43781
43974
|
kind: "cursor_agent_cli",
|
|
@@ -43853,7 +44046,7 @@ function createCursorAgentCliBackend(command = "cursor-agent", defaultArgs = [])
|
|
|
43853
44046
|
return appendImagePathReferences(prompt, imageFiles);
|
|
43854
44047
|
},
|
|
43855
44048
|
parseStructuredLine: parseCursorStructuredLine
|
|
43856
|
-
}).run(
|
|
44049
|
+
}).run(runContext);
|
|
43857
44050
|
} finally {
|
|
43858
44051
|
cleanup();
|
|
43859
44052
|
}
|
|
@@ -44909,6 +45102,28 @@ function resolveKimiCliModelArg(model) {
|
|
|
44909
45102
|
if (trimmed.startsWith("claude-")) return void 0;
|
|
44910
45103
|
return trimmed;
|
|
44911
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
|
+
}
|
|
44912
45127
|
function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
|
|
44913
45128
|
return {
|
|
44914
45129
|
kind: "kimi_cli",
|
|
@@ -44920,14 +45135,9 @@ function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
|
|
|
44920
45135
|
if (registration && mcpConfigPath) {
|
|
44921
45136
|
(0, import_fs9.writeFileSync)(
|
|
44922
45137
|
mcpConfigPath,
|
|
44923
|
-
JSON.stringify(
|
|
44924
|
-
|
|
44925
|
-
|
|
44926
|
-
url: registration.url,
|
|
44927
|
-
headers: { "x-alan-run-reference": requireManagedRunReference(registration) }
|
|
44928
|
-
}
|
|
44929
|
-
}
|
|
44930
|
-
}),
|
|
45138
|
+
JSON.stringify(
|
|
45139
|
+
buildKimiMcpConfig(registration, selectExternalMcpServers(context.config))
|
|
45140
|
+
),
|
|
44931
45141
|
{ mode: 384 }
|
|
44932
45142
|
);
|
|
44933
45143
|
}
|
|
@@ -45454,7 +45664,7 @@ function leaseKeyFor(context) {
|
|
|
45454
45664
|
if (!conversationId) return null;
|
|
45455
45665
|
const runReference = context.config.alanMcp?.headers?.["x-alan-run-reference"];
|
|
45456
45666
|
if (!runReference) return `conv:${conversationId}`;
|
|
45457
|
-
const fingerprint = (0,
|
|
45667
|
+
const fingerprint = (0, import_crypto6.createHash)("sha256").update(runReference).digest("hex").slice(0, 16);
|
|
45458
45668
|
return `conv:${conversationId}|mcp:${fingerprint}`;
|
|
45459
45669
|
}
|
|
45460
45670
|
function isLeaseUsable(lease) {
|
|
@@ -46479,8 +46689,10 @@ var BaseMachineAgent = class _BaseMachineAgent {
|
|
|
46479
46689
|
*/
|
|
46480
46690
|
async beginMcpConfigCriticalSection(backend, context) {
|
|
46481
46691
|
const runHeaders = context.config.alanMcp?.headers;
|
|
46482
|
-
if (!runHeaders || usesProcessLocalManagedMcp(backend.kind)
|
|
46483
|
-
|
|
46692
|
+
if (!runHeaders || usesProcessLocalManagedMcp(backend.kind) || deliversRunReferenceViaEnv(backend.kind)) {
|
|
46693
|
+
return () => {
|
|
46694
|
+
};
|
|
46695
|
+
}
|
|
46484
46696
|
const releaseGate = await acquireMcpConfigWriteGate();
|
|
46485
46697
|
try {
|
|
46486
46698
|
const writtenClis = await syncAlanMcpSessionHeaders({
|
|
@@ -46493,7 +46705,11 @@ var BaseMachineAgent = class _BaseMachineAgent {
|
|
|
46493
46705
|
void this.presenter.onLog(`Synced Alan MCP session headers to ${writtenClis.join(", ")}`);
|
|
46494
46706
|
}
|
|
46495
46707
|
} catch (error61) {
|
|
46496
|
-
|
|
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
|
+
);
|
|
46497
46713
|
}
|
|
46498
46714
|
return releaseGate;
|
|
46499
46715
|
}
|
|
@@ -46988,7 +47204,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
|
|
|
46988
47204
|
const { width, height } = readImageDimensions2(buffer, mimeType);
|
|
46989
47205
|
images.push({
|
|
46990
47206
|
type: "generated_image",
|
|
46991
|
-
id: (0,
|
|
47207
|
+
id: (0, import_crypto7.randomUUID)(),
|
|
46992
47208
|
filename: (0, import_path11.basename)(path2),
|
|
46993
47209
|
mimeType,
|
|
46994
47210
|
size: buffer.length,
|
|
@@ -46996,7 +47212,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
|
|
|
46996
47212
|
height,
|
|
46997
47213
|
data: buffer.toString("base64"),
|
|
46998
47214
|
sourcePath: path2,
|
|
46999
|
-
sourceHash: (0,
|
|
47215
|
+
sourceHash: (0, import_crypto7.createHash)("sha256").update(buffer).digest("hex"),
|
|
47000
47216
|
toolId,
|
|
47001
47217
|
ts: Date.now()
|
|
47002
47218
|
});
|
|
@@ -47028,7 +47244,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
|
|
|
47028
47244
|
media.push({
|
|
47029
47245
|
type: "session_media",
|
|
47030
47246
|
kind,
|
|
47031
|
-
id: (0,
|
|
47247
|
+
id: (0, import_crypto7.randomUUID)(),
|
|
47032
47248
|
filename: (0, import_path11.basename)(path2),
|
|
47033
47249
|
mimeType,
|
|
47034
47250
|
size: buffer.length,
|
|
@@ -47036,7 +47252,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
|
|
|
47036
47252
|
height: dimensions?.height,
|
|
47037
47253
|
data: buffer.toString("base64"),
|
|
47038
47254
|
sourcePath: path2,
|
|
47039
|
-
sourceHash: (0,
|
|
47255
|
+
sourceHash: (0, import_crypto7.createHash)("sha256").update(buffer).digest("hex"),
|
|
47040
47256
|
toolId,
|
|
47041
47257
|
ts: Date.now()
|
|
47042
47258
|
});
|
|
@@ -56800,7 +57016,12 @@ async function ensureAlanMcpRegistered(backendKind, registration, home = (0, imp
|
|
|
56800
57016
|
releaseLock();
|
|
56801
57017
|
}
|
|
56802
57018
|
}
|
|
56803
|
-
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
|
+
);
|
|
56804
57025
|
if (!fileOk) {
|
|
56805
57026
|
const issue2 = {
|
|
56806
57027
|
code: "mcp_config_repair_required",
|
|
@@ -56974,7 +57195,8 @@ function hasUsableRegistrationCredential(headers) {
|
|
|
56974
57195
|
const normalized = new Map(
|
|
56975
57196
|
Object.entries(headers).map(([name, value2]) => [name.toLowerCase(), value2.trim()])
|
|
56976
57197
|
);
|
|
56977
|
-
|
|
57198
|
+
const reference = normalized.get("x-alan-run-reference") ?? "";
|
|
57199
|
+
return Boolean(reference && !reference.startsWith("${") || normalized.get("authorization"));
|
|
56978
57200
|
}
|
|
56979
57201
|
function readAlanMcpRegistration(path2) {
|
|
56980
57202
|
return parseAlanMcpRegistration(path2, (0, import_node_fs16.readFileSync)(path2, "utf8"));
|
|
@@ -75266,6 +75488,7 @@ async function handleAgentExecute(ctx, payload) {
|
|
|
75266
75488
|
prMeta: payload.prMeta,
|
|
75267
75489
|
conversationId: payload.conversationId,
|
|
75268
75490
|
alanMcp: payload.alanMcp,
|
|
75491
|
+
externalMcpServers: payload.externalMcpServers,
|
|
75269
75492
|
taskId: payload.taskId ?? payload.taskMeta?.id,
|
|
75270
75493
|
teamId: payload.teamId,
|
|
75271
75494
|
currentUser: payload.currentUser,
|
|
@@ -82145,345 +82368,966 @@ function runMcpIntegrationCommand(args, options = {}) {
|
|
|
82145
82368
|
throw new Error(`Unknown integrations action: ${action}`);
|
|
82146
82369
|
}
|
|
82147
82370
|
|
|
82148
|
-
// src/
|
|
82149
|
-
var
|
|
82150
|
-
|
|
82151
|
-
|
|
82152
|
-
|
|
82153
|
-
|
|
82154
|
-
|
|
82155
|
-
|
|
82156
|
-
|
|
82157
|
-
|
|
82158
|
-
return new _AgentLifecycleLogger({ ...this.context, ...context });
|
|
82159
|
-
}
|
|
82160
|
-
debug(event, fields = {}) {
|
|
82161
|
-
this.log("debug", event, fields);
|
|
82162
|
-
}
|
|
82163
|
-
info(event, fields = {}) {
|
|
82164
|
-
this.log("info", event, fields);
|
|
82165
|
-
}
|
|
82166
|
-
warn(event, fields = {}) {
|
|
82167
|
-
this.log("warn", event, fields);
|
|
82168
|
-
}
|
|
82169
|
-
error(event, fields = {}) {
|
|
82170
|
-
this.log("error", event, fields);
|
|
82171
|
-
}
|
|
82172
|
-
log(level, event, fields) {
|
|
82173
|
-
const record2 = omitUndefined({
|
|
82174
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
82175
|
-
level,
|
|
82176
|
-
component: "agent-manager",
|
|
82177
|
-
event,
|
|
82178
|
-
...this.context,
|
|
82179
|
-
...normalizeFields(fields)
|
|
82180
|
-
});
|
|
82181
|
-
console[level](JSON.stringify(record2));
|
|
82182
|
-
}
|
|
82183
|
-
};
|
|
82184
|
-
function lifecycleContextFromEnv(env) {
|
|
82185
|
-
return normalizeContext({
|
|
82186
|
-
taskId: env.ALAN_TASK_ID,
|
|
82187
|
-
conversationId: env.ALAN_SESSION_ID,
|
|
82188
|
-
runId: env.ALAN_RUN_ID,
|
|
82189
|
-
sandboxId: env.ALAN_SANDBOX_ID,
|
|
82190
|
-
provider: env.ALAN_SANDBOX_PROVIDER,
|
|
82191
|
-
backendKind: env.ALAN_BACKEND_KIND,
|
|
82192
|
-
agentVersion: AGENT_VERSION
|
|
82193
|
-
});
|
|
82194
|
-
}
|
|
82195
|
-
function normalizeContext(context) {
|
|
82196
|
-
return omitUndefined({
|
|
82197
|
-
...context,
|
|
82198
|
-
agentVersion: context.agentVersion ?? AGENT_VERSION
|
|
82199
|
-
});
|
|
82371
|
+
// src/service-manager.ts
|
|
82372
|
+
var import_node_child_process9 = require("child_process");
|
|
82373
|
+
var import_node_fs25 = require("fs");
|
|
82374
|
+
var import_node_os16 = require("os");
|
|
82375
|
+
var import_node_path27 = require("path");
|
|
82376
|
+
var SERVICE_LABEL = "ai.tryalan.agent";
|
|
82377
|
+
var SYSTEMD_UNIT = "alan-agent.service";
|
|
82378
|
+
var WINDOWS_TASK = "Alan Agent";
|
|
82379
|
+
function xml(value2) {
|
|
82380
|
+
return value2.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
82200
82381
|
}
|
|
82201
|
-
function
|
|
82202
|
-
|
|
82203
|
-
for (const [key, value2] of Object.entries(fields)) {
|
|
82204
|
-
if (value2 instanceof Error) {
|
|
82205
|
-
normalized[key] = {
|
|
82206
|
-
name: value2.name,
|
|
82207
|
-
message: value2.message,
|
|
82208
|
-
stack: value2.stack
|
|
82209
|
-
};
|
|
82210
|
-
} else {
|
|
82211
|
-
normalized[key] = value2;
|
|
82212
|
-
}
|
|
82213
|
-
}
|
|
82214
|
-
return normalized;
|
|
82382
|
+
function systemdArg(value2) {
|
|
82383
|
+
return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
82215
82384
|
}
|
|
82216
|
-
function
|
|
82217
|
-
return
|
|
82385
|
+
function powershellLiteral(value2) {
|
|
82386
|
+
return `'${value2.replaceAll("'", "''")}'`;
|
|
82218
82387
|
}
|
|
82219
|
-
|
|
82220
|
-
|
|
82221
|
-
|
|
82222
|
-
var __defProp3 = Object.defineProperty;
|
|
82223
|
-
var __getOwnPropDesc3 = Object.getOwnPropertyDescriptor;
|
|
82224
|
-
var __getOwnPropNames3 = Object.getOwnPropertyNames;
|
|
82225
|
-
var __getProtoOf3 = Object.getPrototypeOf;
|
|
82226
|
-
var __hasOwnProp3 = Object.prototype.hasOwnProperty;
|
|
82227
|
-
var __commonJSMin2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
82228
|
-
var __exportAll2 = (all, symbols) => {
|
|
82229
|
-
let target = {};
|
|
82230
|
-
for (var name in all) {
|
|
82231
|
-
__defProp3(target, name, {
|
|
82232
|
-
get: all[name],
|
|
82233
|
-
enumerable: true
|
|
82234
|
-
});
|
|
82235
|
-
}
|
|
82236
|
-
if (symbols) {
|
|
82237
|
-
__defProp3(target, Symbol.toStringTag, { value: "Module" });
|
|
82388
|
+
function serviceNames(profile) {
|
|
82389
|
+
if (profile === "production") {
|
|
82390
|
+
return { launchd: SERVICE_LABEL, systemd: SYSTEMD_UNIT, windows: WINDOWS_TASK };
|
|
82238
82391
|
}
|
|
82239
|
-
|
|
82240
|
-
}
|
|
82241
|
-
|
|
82242
|
-
|
|
82243
|
-
|
|
82244
|
-
|
|
82245
|
-
|
|
82246
|
-
|
|
82247
|
-
|
|
82248
|
-
|
|
82249
|
-
|
|
82250
|
-
|
|
82251
|
-
|
|
82392
|
+
const suffix = profile === "custom" ? "prod" : profile;
|
|
82393
|
+
const title = `${suffix[0]?.toUpperCase()}${suffix.slice(1)}`;
|
|
82394
|
+
return {
|
|
82395
|
+
launchd: `${SERVICE_LABEL}.${suffix}`,
|
|
82396
|
+
systemd: `alan-agent-${suffix}.service`,
|
|
82397
|
+
windows: `${WINDOWS_TASK} ${title}`
|
|
82398
|
+
};
|
|
82399
|
+
}
|
|
82400
|
+
function buildDaemonServicePlan(input2) {
|
|
82401
|
+
const daemonArgs = [input2.nodeExecutable, input2.cliEntry, "daemon", "--profile", input2.profile];
|
|
82402
|
+
const names = serviceNames(input2.profile);
|
|
82403
|
+
if (input2.platform === "darwin") {
|
|
82404
|
+
const userId = input2.userId ?? process.getuid?.();
|
|
82405
|
+
if (userId === void 0) throw new Error("Cannot determine the current macOS user ID");
|
|
82406
|
+
const domain2 = `gui/${userId}`;
|
|
82407
|
+
const serviceTarget = `${domain2}/${names.launchd}`;
|
|
82408
|
+
const manifestPath = (0, import_node_path27.join)(input2.homeDir, "Library", "LaunchAgents", `${names.launchd}.plist`);
|
|
82409
|
+
const logDir = (0, import_node_path27.join)(resolveAgentConfigDirectory(input2.profile, input2.homeDir), "logs");
|
|
82410
|
+
const programArguments = daemonArgs.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
|
|
82411
|
+
const environmentEntries = Object.entries(input2.environment ?? {}).map(([key, value2]) => ` <key>${xml(key)}</key>
|
|
82412
|
+
<string>${xml(value2)}</string>`).join("\n");
|
|
82413
|
+
const environmentBlock = environmentEntries ? ` <key>EnvironmentVariables</key>
|
|
82414
|
+
<dict>
|
|
82415
|
+
${environmentEntries}
|
|
82416
|
+
</dict>
|
|
82417
|
+
` : "";
|
|
82418
|
+
const manifest = `<?xml version="1.0" encoding="UTF-8"?>
|
|
82419
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
82420
|
+
<plist version="1.0">
|
|
82421
|
+
<dict>
|
|
82422
|
+
<key>Label</key>
|
|
82423
|
+
<string>${names.launchd}</string>
|
|
82424
|
+
<key>ProgramArguments</key>
|
|
82425
|
+
<array>
|
|
82426
|
+
${programArguments}
|
|
82427
|
+
</array>
|
|
82428
|
+
${environmentBlock} <key>RunAtLoad</key>
|
|
82429
|
+
<true/>
|
|
82430
|
+
<key>KeepAlive</key>
|
|
82431
|
+
<dict>
|
|
82432
|
+
<key>SuccessfulExit</key>
|
|
82433
|
+
<false/>
|
|
82434
|
+
</dict>
|
|
82435
|
+
<key>ThrottleInterval</key>
|
|
82436
|
+
<integer>5</integer>
|
|
82437
|
+
<key>StandardOutPath</key>
|
|
82438
|
+
<string>${xml((0, import_node_path27.join)(logDir, "daemon.log"))}</string>
|
|
82439
|
+
<key>StandardErrorPath</key>
|
|
82440
|
+
<string>${xml((0, import_node_path27.join)(logDir, "daemon-error.log"))}</string>
|
|
82441
|
+
</dict>
|
|
82442
|
+
</plist>
|
|
82443
|
+
`;
|
|
82444
|
+
return {
|
|
82445
|
+
platform: "darwin",
|
|
82446
|
+
manifestPath,
|
|
82447
|
+
manifest,
|
|
82448
|
+
logDirectory: logDir,
|
|
82449
|
+
loadDefinitionCommands: [
|
|
82450
|
+
{
|
|
82451
|
+
command: "launchctl",
|
|
82452
|
+
args: ["bootstrap", domain2, manifestPath],
|
|
82453
|
+
tolerateFailure: true
|
|
82454
|
+
}
|
|
82455
|
+
],
|
|
82456
|
+
reloadDefinitionCommands: [
|
|
82457
|
+
{
|
|
82458
|
+
command: "launchctl",
|
|
82459
|
+
args: ["bootout", domain2, manifestPath],
|
|
82460
|
+
tolerateFailure: true
|
|
82461
|
+
},
|
|
82462
|
+
{
|
|
82463
|
+
command: "launchctl",
|
|
82464
|
+
args: ["bootstrap", domain2, manifestPath],
|
|
82465
|
+
tolerateFailure: false
|
|
82466
|
+
}
|
|
82467
|
+
],
|
|
82468
|
+
enableCommands: [
|
|
82469
|
+
{
|
|
82470
|
+
command: "launchctl",
|
|
82471
|
+
args: ["enable", serviceTarget],
|
|
82472
|
+
tolerateFailure: true
|
|
82473
|
+
}
|
|
82474
|
+
],
|
|
82475
|
+
startCommands: [
|
|
82476
|
+
{
|
|
82477
|
+
command: "launchctl",
|
|
82478
|
+
args: ["kickstart", serviceTarget],
|
|
82479
|
+
tolerateFailure: false
|
|
82480
|
+
}
|
|
82481
|
+
],
|
|
82482
|
+
stopCommands: [
|
|
82483
|
+
{
|
|
82484
|
+
command: "launchctl",
|
|
82485
|
+
args: ["kill", "SIGTERM", serviceTarget],
|
|
82486
|
+
tolerateFailure: true
|
|
82487
|
+
}
|
|
82488
|
+
],
|
|
82489
|
+
replaceCommands: [
|
|
82490
|
+
{
|
|
82491
|
+
command: "launchctl",
|
|
82492
|
+
args: ["bootout", domain2, manifestPath],
|
|
82493
|
+
tolerateFailure: true
|
|
82494
|
+
},
|
|
82495
|
+
{
|
|
82496
|
+
command: "launchctl",
|
|
82497
|
+
args: ["bootstrap", domain2, manifestPath],
|
|
82498
|
+
tolerateFailure: false
|
|
82499
|
+
},
|
|
82500
|
+
{
|
|
82501
|
+
command: "launchctl",
|
|
82502
|
+
args: ["kickstart", "-k", serviceTarget],
|
|
82503
|
+
tolerateFailure: false
|
|
82504
|
+
}
|
|
82505
|
+
],
|
|
82506
|
+
uninstallCommands: [
|
|
82507
|
+
{
|
|
82508
|
+
command: "launchctl",
|
|
82509
|
+
args: ["bootout", domain2, manifestPath],
|
|
82510
|
+
tolerateFailure: true
|
|
82511
|
+
}
|
|
82512
|
+
],
|
|
82513
|
+
statusCommand: {
|
|
82514
|
+
command: "launchctl",
|
|
82515
|
+
args: ["print", serviceTarget],
|
|
82516
|
+
tolerateFailure: true
|
|
82517
|
+
},
|
|
82518
|
+
isActiveCommand: {
|
|
82519
|
+
command: "launchctl",
|
|
82520
|
+
args: ["print", serviceTarget],
|
|
82521
|
+
tolerateFailure: true
|
|
82522
|
+
},
|
|
82523
|
+
lingerStatusCommand: null
|
|
82524
|
+
};
|
|
82252
82525
|
}
|
|
82253
|
-
|
|
82254
|
-
|
|
82255
|
-
|
|
82256
|
-
|
|
82257
|
-
|
|
82258
|
-
|
|
82526
|
+
if (input2.platform === "linux") {
|
|
82527
|
+
const manifestPath = (0, import_node_path27.join)(input2.homeDir, ".config", "systemd", "user", names.systemd);
|
|
82528
|
+
const environmentLines = Object.entries(input2.environment ?? {}).map(([key, value2]) => `Environment=${systemdArg(`${key}=${value2}`)}`).join("\n");
|
|
82529
|
+
const manifest = `[Unit]
|
|
82530
|
+
Description=Alan local agent daemon
|
|
82531
|
+
After=network-online.target
|
|
82532
|
+
Wants=network-online.target
|
|
82533
|
+
StartLimitIntervalSec=300
|
|
82534
|
+
StartLimitBurst=3
|
|
82259
82535
|
|
|
82260
|
-
|
|
82261
|
-
|
|
82262
|
-
|
|
82263
|
-
|
|
82264
|
-
|
|
82265
|
-
|
|
82266
|
-
return typeof $schema === "string" && DRAFT_2019_09_URIS2.has($schema.replace(/#$/, ""));
|
|
82267
|
-
}
|
|
82268
|
-
function declaredDialect2(schema, remedy) {
|
|
82269
|
-
if (!("$schema" in schema) || typeof schema.$schema !== "string") return "2020-12";
|
|
82270
|
-
const declared = schema.$schema.replace(/#$/, "");
|
|
82271
|
-
if (DRAFT_2020_12_URIS2.has(declared)) return "2020-12";
|
|
82272
|
-
if (DRAFT_2019_09_URIS2.has(declared)) return "2019-09";
|
|
82273
|
-
if (DRAFT_07_URIS2.has(declared) || DRAFT_06_URIS2.has(declared)) return "draft-7";
|
|
82274
|
-
throw new Error(`JSON Schema declares an unsupported dialect ("$schema": "${schema.$schema.slice(0, 200)}"). The default validator supports JSON Schema 2020-12, 2019-09, draft-07, and draft-06; ${remedy}`);
|
|
82275
|
-
}
|
|
82536
|
+
[Service]
|
|
82537
|
+
Type=simple
|
|
82538
|
+
${environmentLines ? `${environmentLines}
|
|
82539
|
+
` : ""}ExecStart=${daemonArgs.map(systemdArg).join(" ")}
|
|
82540
|
+
Restart=on-failure
|
|
82541
|
+
RestartSec=5
|
|
82276
82542
|
|
|
82277
|
-
|
|
82278
|
-
|
|
82279
|
-
|
|
82280
|
-
|
|
82281
|
-
|
|
82282
|
-
|
|
82283
|
-
|
|
82284
|
-
|
|
82285
|
-
|
|
82286
|
-
|
|
82287
|
-
|
|
82288
|
-
|
|
82289
|
-
|
|
82290
|
-
|
|
82291
|
-
|
|
82292
|
-
|
|
82293
|
-
|
|
82294
|
-
|
|
82295
|
-
|
|
82296
|
-
|
|
82297
|
-
|
|
82298
|
-
|
|
82299
|
-
|
|
82300
|
-
|
|
82301
|
-
|
|
82302
|
-
|
|
82303
|
-
|
|
82304
|
-
|
|
82305
|
-
|
|
82306
|
-
|
|
82307
|
-
|
|
82308
|
-
|
|
82309
|
-
|
|
82310
|
-
|
|
82311
|
-
|
|
82312
|
-
|
|
82313
|
-
|
|
82314
|
-
|
|
82315
|
-
|
|
82316
|
-
|
|
82317
|
-
|
|
82318
|
-
|
|
82319
|
-
|
|
82320
|
-
|
|
82321
|
-
|
|
82322
|
-
|
|
82543
|
+
[Install]
|
|
82544
|
+
WantedBy=default.target
|
|
82545
|
+
`;
|
|
82546
|
+
return {
|
|
82547
|
+
platform: "linux",
|
|
82548
|
+
manifestPath,
|
|
82549
|
+
manifest,
|
|
82550
|
+
logDirectory: null,
|
|
82551
|
+
loadDefinitionCommands: [
|
|
82552
|
+
{
|
|
82553
|
+
command: "systemctl",
|
|
82554
|
+
args: ["--user", "daemon-reload"],
|
|
82555
|
+
tolerateFailure: false
|
|
82556
|
+
}
|
|
82557
|
+
],
|
|
82558
|
+
reloadDefinitionCommands: [
|
|
82559
|
+
{
|
|
82560
|
+
command: "systemctl",
|
|
82561
|
+
args: ["--user", "daemon-reload"],
|
|
82562
|
+
tolerateFailure: false
|
|
82563
|
+
}
|
|
82564
|
+
],
|
|
82565
|
+
enableCommands: [
|
|
82566
|
+
{
|
|
82567
|
+
command: "systemctl",
|
|
82568
|
+
args: ["--user", "enable", names.systemd],
|
|
82569
|
+
tolerateFailure: false
|
|
82570
|
+
}
|
|
82571
|
+
],
|
|
82572
|
+
startCommands: [
|
|
82573
|
+
{
|
|
82574
|
+
command: "systemctl",
|
|
82575
|
+
args: ["--user", "start", names.systemd],
|
|
82576
|
+
tolerateFailure: false
|
|
82577
|
+
}
|
|
82578
|
+
],
|
|
82579
|
+
stopCommands: [
|
|
82580
|
+
{
|
|
82581
|
+
command: "systemctl",
|
|
82582
|
+
args: ["--user", "stop", names.systemd],
|
|
82583
|
+
tolerateFailure: true
|
|
82584
|
+
}
|
|
82585
|
+
],
|
|
82586
|
+
replaceCommands: [
|
|
82587
|
+
{
|
|
82588
|
+
command: "systemctl",
|
|
82589
|
+
args: ["--user", "daemon-reload"],
|
|
82590
|
+
tolerateFailure: false
|
|
82591
|
+
},
|
|
82592
|
+
{
|
|
82593
|
+
command: "systemctl",
|
|
82594
|
+
args: ["--user", "restart", names.systemd],
|
|
82595
|
+
tolerateFailure: false
|
|
82596
|
+
}
|
|
82597
|
+
],
|
|
82598
|
+
uninstallCommands: [
|
|
82599
|
+
{
|
|
82600
|
+
command: "systemctl",
|
|
82601
|
+
args: ["--user", "disable", "--now", names.systemd],
|
|
82602
|
+
tolerateFailure: true
|
|
82603
|
+
},
|
|
82604
|
+
{
|
|
82605
|
+
command: "systemctl",
|
|
82606
|
+
args: ["--user", "daemon-reload"],
|
|
82607
|
+
tolerateFailure: false
|
|
82608
|
+
}
|
|
82609
|
+
],
|
|
82610
|
+
statusCommand: {
|
|
82611
|
+
command: "systemctl",
|
|
82612
|
+
args: ["--user", "status", names.systemd, "--no-pager"],
|
|
82613
|
+
tolerateFailure: true
|
|
82614
|
+
},
|
|
82615
|
+
isActiveCommand: {
|
|
82616
|
+
command: "systemctl",
|
|
82617
|
+
args: ["--user", "is-active", names.systemd],
|
|
82618
|
+
tolerateFailure: true
|
|
82619
|
+
},
|
|
82620
|
+
lingerStatusCommand: {
|
|
82621
|
+
command: "loginctl",
|
|
82622
|
+
args: ["show-user", "$(id -un)", "-p", "Linger"],
|
|
82623
|
+
tolerateFailure: true
|
|
82624
|
+
}
|
|
82625
|
+
};
|
|
82323
82626
|
}
|
|
82324
|
-
|
|
82325
|
-
|
|
82326
|
-
|
|
82327
|
-
|
|
82328
|
-
|
|
82329
|
-
|
|
82627
|
+
const environmentPrefix = Object.entries(input2.environment ?? {}).map(([key, value2]) => `$env:${key} = ${powershellLiteral(value2)}`).join("; ");
|
|
82628
|
+
const directArgument = [input2.cliEntry, "daemon", "--profile", input2.profile].map((part) => part.includes(" ") ? `"${part}"` : part).join(" ");
|
|
82629
|
+
const executable = powershellLiteral(environmentPrefix ? "powershell.exe" : input2.nodeExecutable);
|
|
82630
|
+
const argument = powershellLiteral(
|
|
82631
|
+
environmentPrefix ? `-NoProfile -NonInteractive -WindowStyle Hidden -Command "${environmentPrefix}; & ${powershellLiteral(input2.nodeExecutable)} ${powershellLiteral(input2.cliEntry)} daemon --profile ${input2.profile}"` : directArgument
|
|
82632
|
+
);
|
|
82633
|
+
const registerScript = [
|
|
82634
|
+
"$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name",
|
|
82635
|
+
`$action = New-ScheduledTaskAction -Execute ${executable} -Argument ${argument}`,
|
|
82636
|
+
"$trigger = New-ScheduledTaskTrigger -AtLogOn -User $currentUser",
|
|
82637
|
+
"$principal = New-ScheduledTaskPrincipal -UserId $currentUser -LogonType Interactive -RunLevel Limited",
|
|
82638
|
+
"$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero)",
|
|
82639
|
+
`Register-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null`
|
|
82640
|
+
].join("; ");
|
|
82641
|
+
return {
|
|
82642
|
+
platform: "win32",
|
|
82643
|
+
manifestPath: null,
|
|
82644
|
+
manifest: null,
|
|
82645
|
+
logDirectory: null,
|
|
82646
|
+
loadDefinitionCommands: [
|
|
82647
|
+
{
|
|
82648
|
+
command: "powershell.exe",
|
|
82649
|
+
args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
|
|
82650
|
+
tolerateFailure: false
|
|
82651
|
+
}
|
|
82652
|
+
],
|
|
82653
|
+
reloadDefinitionCommands: [
|
|
82654
|
+
{
|
|
82655
|
+
command: "powershell.exe",
|
|
82656
|
+
args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
|
|
82657
|
+
tolerateFailure: false
|
|
82658
|
+
}
|
|
82659
|
+
],
|
|
82660
|
+
enableCommands: [],
|
|
82661
|
+
startCommands: [
|
|
82662
|
+
{
|
|
82663
|
+
command: "powershell.exe",
|
|
82664
|
+
args: [
|
|
82665
|
+
"-NoProfile",
|
|
82666
|
+
"-NonInteractive",
|
|
82667
|
+
"-Command",
|
|
82668
|
+
`Start-ScheduledTask -TaskName ${powershellLiteral(names.windows)}`
|
|
82669
|
+
],
|
|
82670
|
+
tolerateFailure: false
|
|
82671
|
+
}
|
|
82672
|
+
],
|
|
82673
|
+
stopCommands: [
|
|
82674
|
+
{
|
|
82675
|
+
command: "powershell.exe",
|
|
82676
|
+
args: [
|
|
82677
|
+
"-NoProfile",
|
|
82678
|
+
"-NonInteractive",
|
|
82679
|
+
"-Command",
|
|
82680
|
+
`Stop-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -ErrorAction SilentlyContinue`
|
|
82681
|
+
],
|
|
82682
|
+
tolerateFailure: true
|
|
82683
|
+
}
|
|
82684
|
+
],
|
|
82685
|
+
replaceCommands: [
|
|
82686
|
+
{
|
|
82687
|
+
command: "powershell.exe",
|
|
82688
|
+
args: [
|
|
82689
|
+
"-NoProfile",
|
|
82690
|
+
"-NonInteractive",
|
|
82691
|
+
"-Command",
|
|
82692
|
+
`${registerScript}; Start-ScheduledTask -TaskName ${powershellLiteral(names.windows)}`
|
|
82693
|
+
],
|
|
82694
|
+
tolerateFailure: false
|
|
82695
|
+
}
|
|
82696
|
+
],
|
|
82697
|
+
uninstallCommands: [
|
|
82698
|
+
{
|
|
82699
|
+
command: "powershell.exe",
|
|
82700
|
+
args: [
|
|
82701
|
+
"-NoProfile",
|
|
82702
|
+
"-NonInteractive",
|
|
82703
|
+
"-Command",
|
|
82704
|
+
`Unregister-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -Confirm:$false -ErrorAction SilentlyContinue`
|
|
82705
|
+
],
|
|
82706
|
+
tolerateFailure: true
|
|
82707
|
+
}
|
|
82708
|
+
],
|
|
82709
|
+
statusCommand: {
|
|
82710
|
+
command: "powershell.exe",
|
|
82711
|
+
args: [
|
|
82712
|
+
"-NoProfile",
|
|
82713
|
+
"-NonInteractive",
|
|
82714
|
+
"-Command",
|
|
82715
|
+
`Get-ScheduledTask -TaskName ${powershellLiteral(names.windows)} | Format-List TaskName,State`
|
|
82716
|
+
],
|
|
82717
|
+
tolerateFailure: true
|
|
82718
|
+
},
|
|
82719
|
+
isActiveCommand: {
|
|
82720
|
+
command: "powershell.exe",
|
|
82721
|
+
args: [
|
|
82722
|
+
"-NoProfile",
|
|
82723
|
+
"-NonInteractive",
|
|
82724
|
+
"-Command",
|
|
82725
|
+
`(Get-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -ErrorAction SilentlyContinue).State`
|
|
82726
|
+
],
|
|
82727
|
+
tolerateFailure: true
|
|
82728
|
+
},
|
|
82729
|
+
lingerStatusCommand: null
|
|
82730
|
+
};
|
|
82731
|
+
}
|
|
82732
|
+
function resolveCurrentPlatform() {
|
|
82733
|
+
const currentPlatform = (0, import_node_os16.platform)();
|
|
82734
|
+
if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
|
|
82735
|
+
throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
|
|
82330
82736
|
}
|
|
82331
|
-
|
|
82332
|
-
|
|
82333
|
-
|
|
82334
|
-
|
|
82335
|
-
|
|
82336
|
-
|
|
82337
|
-
|
|
82338
|
-
|
|
82339
|
-
|
|
82340
|
-
|
|
82737
|
+
return currentPlatform;
|
|
82738
|
+
}
|
|
82739
|
+
function currentServicePlan(args, runtime) {
|
|
82740
|
+
const currentPlatform = resolveCurrentPlatform();
|
|
82741
|
+
const profile = resolveEndpointProfileFromArgs(args);
|
|
82742
|
+
const cliEntry = runtime?.cliEntry ?? process.argv[1];
|
|
82743
|
+
if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
|
|
82744
|
+
return buildDaemonServicePlan({
|
|
82745
|
+
platform: currentPlatform,
|
|
82746
|
+
homeDir: (0, import_node_os16.homedir)(),
|
|
82747
|
+
nodeExecutable: runtime?.executable ?? process.execPath,
|
|
82748
|
+
cliEntry: (0, import_node_path27.resolve)(cliEntry),
|
|
82749
|
+
profile,
|
|
82750
|
+
environment: runtime?.environment
|
|
82751
|
+
});
|
|
82752
|
+
}
|
|
82753
|
+
function writeManifestAtomic(path2, contents) {
|
|
82754
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path27.dirname)(path2), { recursive: true, mode: 448 });
|
|
82755
|
+
const pendingPath = `${path2}.pending-${process.pid}`;
|
|
82756
|
+
try {
|
|
82757
|
+
(0, import_node_fs25.writeFileSync)(pendingPath, contents, { mode: 384 });
|
|
82758
|
+
(0, import_node_fs25.chmodSync)(pendingPath, 384);
|
|
82759
|
+
(0, import_node_fs25.renameSync)(pendingPath, path2);
|
|
82760
|
+
} finally {
|
|
82761
|
+
(0, import_node_fs25.rmSync)(pendingPath, { force: true });
|
|
82341
82762
|
}
|
|
82342
|
-
|
|
82343
|
-
|
|
82344
|
-
|
|
82345
|
-
|
|
82346
|
-
|
|
82763
|
+
}
|
|
82764
|
+
function defaultReadManifest(path2) {
|
|
82765
|
+
if (!(0, import_node_fs25.existsSync)(path2)) return null;
|
|
82766
|
+
return (0, import_node_fs25.readFileSync)(path2, "utf8");
|
|
82767
|
+
}
|
|
82768
|
+
function runServiceCommand(command) {
|
|
82769
|
+
const result = (0, import_node_child_process9.spawnSync)(command.command, command.args, { encoding: "utf8", shell: false });
|
|
82770
|
+
const status = result.status ?? 1;
|
|
82771
|
+
const output2 = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
82772
|
+
if (status !== 0 && !command.tolerateFailure) {
|
|
82773
|
+
throw new Error(
|
|
82774
|
+
`Service command failed (${command.command} ${command.args.join(" ")}): ${output2 || `exit ${status}`}`
|
|
82775
|
+
);
|
|
82347
82776
|
}
|
|
82348
|
-
};
|
|
82349
|
-
|
|
82350
|
-
|
|
82351
|
-
|
|
82352
|
-
|
|
82353
|
-
|
|
82354
|
-
|
|
82355
|
-
|
|
82356
|
-
|
|
82357
|
-
|
|
82358
|
-
|
|
82359
|
-
|
|
82360
|
-
|
|
82361
|
-
|
|
82362
|
-
SdkErrorCode$1["EraNegotiationFailed"] = "ERA_NEGOTIATION_FAILED";
|
|
82363
|
-
SdkErrorCode$1["ClientHttpNotImplemented"] = "CLIENT_HTTP_NOT_IMPLEMENTED";
|
|
82364
|
-
SdkErrorCode$1["ClientHttpAuthentication"] = "CLIENT_HTTP_AUTHENTICATION";
|
|
82365
|
-
SdkErrorCode$1["ClientHttpForbidden"] = "CLIENT_HTTP_FORBIDDEN";
|
|
82366
|
-
SdkErrorCode$1["ClientHttpUnexpectedContent"] = "CLIENT_HTTP_UNEXPECTED_CONTENT";
|
|
82367
|
-
SdkErrorCode$1["ClientHttpFailedToOpenStream"] = "CLIENT_HTTP_FAILED_TO_OPEN_STREAM";
|
|
82368
|
-
SdkErrorCode$1["ClientHttpFailedToTerminateSession"] = "CLIENT_HTTP_FAILED_TO_TERMINATE_SESSION";
|
|
82369
|
-
return SdkErrorCode$1;
|
|
82370
|
-
})({});
|
|
82371
|
-
var SdkError2 = class extends Error {
|
|
82372
|
-
static {
|
|
82373
|
-
Object.defineProperty(this, "mcpBrand", { value: "mcp.SdkError" });
|
|
82777
|
+
return { status, output: output2 };
|
|
82778
|
+
}
|
|
82779
|
+
function defaultSleep(ms) {
|
|
82780
|
+
return new Promise((resolveSleep) => {
|
|
82781
|
+
setTimeout(resolveSleep, ms);
|
|
82782
|
+
});
|
|
82783
|
+
}
|
|
82784
|
+
function parseServiceHostState(servicePlatform, result) {
|
|
82785
|
+
const output2 = result.output;
|
|
82786
|
+
if (servicePlatform === "linux") {
|
|
82787
|
+
const trimmed = output2.trim().toLowerCase();
|
|
82788
|
+
if (trimmed === "inactive" || trimmed === "failed" || trimmed === "dead" || /\binactive\b/i.test(output2) || /\bfailed\b/i.test(output2)) {
|
|
82789
|
+
return "stopped";
|
|
82790
|
+
}
|
|
82374
82791
|
}
|
|
82375
|
-
|
|
82376
|
-
|
|
82792
|
+
if (result.status !== 0) return "unknown";
|
|
82793
|
+
if (servicePlatform === "darwin") {
|
|
82794
|
+
if (/\bstate\s*=\s*running\b/i.test(output2)) return "running";
|
|
82795
|
+
if (/\bstate\s*=\s*(not running|waiting|stopped)\b/i.test(output2)) return "stopped";
|
|
82796
|
+
if (/\bpid\s*=\s*[1-9]\d*\b/i.test(output2)) return "running";
|
|
82797
|
+
if (/could not find service/i.test(output2)) return "stopped";
|
|
82798
|
+
return "unknown";
|
|
82377
82799
|
}
|
|
82378
|
-
|
|
82379
|
-
|
|
82380
|
-
|
|
82381
|
-
|
|
82382
|
-
|
|
82383
|
-
* in callback position write `v => SdkError.isInstance(v)`, not
|
|
82384
|
-
* `.filter(SdkError.isInstance)` (detached calls throw rather than
|
|
82385
|
-
* silently matching nothing).
|
|
82386
|
-
*/
|
|
82387
|
-
static isInstance(value2) {
|
|
82388
|
-
if (typeof this !== "function") throw new TypeError("isInstance must be called on the class (e.g. `SdkError.isInstance(value)`); for callbacks use `v => SdkError.isInstance(v)`");
|
|
82389
|
-
return brandedHasInstance2(this, value2);
|
|
82800
|
+
if (servicePlatform === "linux") {
|
|
82801
|
+
const trimmed = output2.trim().toLowerCase();
|
|
82802
|
+
if (trimmed === "active" || /\bactive\s*\(running\)/i.test(output2)) return "running";
|
|
82803
|
+
if (trimmed === "activating" || trimmed === "reloading") return "starting";
|
|
82804
|
+
return "unknown";
|
|
82390
82805
|
}
|
|
82391
|
-
|
|
82392
|
-
|
|
82393
|
-
|
|
82394
|
-
|
|
82395
|
-
|
|
82396
|
-
|
|
82806
|
+
const stateMatch = output2.match(/\b(?:State|state)\s*[:=]\s*(\w+)/);
|
|
82807
|
+
const state = (stateMatch?.[1] ?? output2.trim()).toLowerCase();
|
|
82808
|
+
if (state === "running") return "running";
|
|
82809
|
+
if (state === "ready" || state === "disabled" || state === "queued") return "stopped";
|
|
82810
|
+
return "unknown";
|
|
82811
|
+
}
|
|
82812
|
+
function resolveEnsureDefinitionOutcome(input2) {
|
|
82813
|
+
if (!input2.definitionChanged) {
|
|
82814
|
+
return { changed: false, updatePending: false };
|
|
82397
82815
|
}
|
|
82398
|
-
|
|
82399
|
-
|
|
82400
|
-
static {
|
|
82401
|
-
Object.defineProperty(this, "mcpBrand", { value: "mcp.SdkHttpError" });
|
|
82816
|
+
if (input2.hostState === "running" || input2.hostState === "starting") {
|
|
82817
|
+
return { changed: true, updatePending: true };
|
|
82402
82818
|
}
|
|
82403
|
-
|
|
82404
|
-
|
|
82405
|
-
|
|
82819
|
+
return { changed: true, updatePending: false };
|
|
82820
|
+
}
|
|
82821
|
+
function shouldStartOnInstall(hostState) {
|
|
82822
|
+
return hostState === "stopped";
|
|
82823
|
+
}
|
|
82824
|
+
function resolveUsername(options) {
|
|
82825
|
+
if (options?.username) return options.username;
|
|
82826
|
+
try {
|
|
82827
|
+
return (0, import_node_os16.userInfo)().username;
|
|
82828
|
+
} catch {
|
|
82829
|
+
return process.env.USER || process.env.USERNAME || "unknown";
|
|
82406
82830
|
}
|
|
82407
|
-
|
|
82408
|
-
|
|
82831
|
+
}
|
|
82832
|
+
function buildLingerStatusCommand(username) {
|
|
82833
|
+
return {
|
|
82834
|
+
command: "loginctl",
|
|
82835
|
+
args: ["show-user", username, "-p", "Linger"],
|
|
82836
|
+
tolerateFailure: true
|
|
82837
|
+
};
|
|
82838
|
+
}
|
|
82839
|
+
function assertSystemdUserLingerEnabled(options = {}) {
|
|
82840
|
+
const username = resolveUsername(options);
|
|
82841
|
+
const run = options.runCommand ?? runServiceCommand;
|
|
82842
|
+
const result = run(buildLingerStatusCommand(username));
|
|
82843
|
+
if (result.status !== 0) {
|
|
82844
|
+
throw new Error(
|
|
82845
|
+
`Cannot verify systemd user linger for ${username} (loginctl failed). For durable headless VM boot run: sudo loginctl enable-linger ${username}`
|
|
82846
|
+
);
|
|
82409
82847
|
}
|
|
82410
|
-
|
|
82411
|
-
|
|
82848
|
+
if (!/Linger=yes/i.test(result.output)) {
|
|
82849
|
+
throw new Error(
|
|
82850
|
+
`systemd user linger is disabled for ${username}. For durable headless VM boot run: sudo loginctl enable-linger ${username}`
|
|
82851
|
+
);
|
|
82412
82852
|
}
|
|
82413
|
-
};
|
|
82414
|
-
function isPlainObject$7(value2) {
|
|
82415
|
-
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
82416
82853
|
}
|
|
82417
|
-
function
|
|
82418
|
-
|
|
82854
|
+
function createHostContext(options = {}) {
|
|
82855
|
+
const args = options.args ?? [];
|
|
82856
|
+
const plan = currentServicePlan(args, options.runtime);
|
|
82857
|
+
const run = options.runCommand ?? runServiceCommand;
|
|
82858
|
+
const sleep4 = options.sleep ?? defaultSleep;
|
|
82859
|
+
const nowMs = options.nowMs ?? Date.now;
|
|
82860
|
+
const readManifest = options.readManifest ?? defaultReadManifest;
|
|
82861
|
+
const writeManifest = options.writeManifest ?? writeManifestAtomic;
|
|
82862
|
+
const removeManifest = options.removeManifest ?? ((path2) => (0, import_node_fs25.rmSync)(path2, { force: true }));
|
|
82863
|
+
const ensureLogDir = options.ensureLogDir ?? (() => {
|
|
82864
|
+
if (plan.logDirectory) (0, import_node_fs25.mkdirSync)(plan.logDirectory, { recursive: true, mode: 448 });
|
|
82865
|
+
});
|
|
82866
|
+
return {
|
|
82867
|
+
args,
|
|
82868
|
+
plan,
|
|
82869
|
+
run,
|
|
82870
|
+
sleep: sleep4,
|
|
82871
|
+
nowMs,
|
|
82872
|
+
readManifest,
|
|
82873
|
+
writeManifest,
|
|
82874
|
+
removeManifest,
|
|
82875
|
+
ensureLogDir,
|
|
82876
|
+
profile: resolveEndpointProfileFromArgs(args)
|
|
82877
|
+
};
|
|
82419
82878
|
}
|
|
82420
|
-
function
|
|
82421
|
-
|
|
82422
|
-
|
|
82423
|
-
|
|
82424
|
-
|
|
82425
|
-
|
|
82426
|
-
|
|
82427
|
-
|
|
82428
|
-
|
|
82879
|
+
function inspectDaemonService(options = {}) {
|
|
82880
|
+
const { plan, run, nowMs } = createHostContext(options);
|
|
82881
|
+
const result = run(plan.isActiveCommand);
|
|
82882
|
+
const state = parseServiceHostState(plan.platform, result);
|
|
82883
|
+
return {
|
|
82884
|
+
state,
|
|
82885
|
+
platform: plan.platform,
|
|
82886
|
+
detail: result.output || void 0,
|
|
82887
|
+
observedAtMs: nowMs()
|
|
82888
|
+
};
|
|
82889
|
+
}
|
|
82890
|
+
function ensureDaemonServiceDefinition(options = {}) {
|
|
82891
|
+
const ctx = createHostContext(options);
|
|
82892
|
+
const { plan, run, readManifest, writeManifest, ensureLogDir } = ctx;
|
|
82893
|
+
let definitionChanged = false;
|
|
82894
|
+
if (plan.manifestPath && plan.manifest) {
|
|
82895
|
+
ensureLogDir();
|
|
82896
|
+
const existing = readManifest(plan.manifestPath);
|
|
82897
|
+
definitionChanged = existing !== plan.manifest;
|
|
82898
|
+
if (definitionChanged) {
|
|
82899
|
+
writeManifest(plan.manifestPath, plan.manifest);
|
|
82429
82900
|
}
|
|
82430
|
-
|
|
82431
|
-
|
|
82432
|
-
|
|
82433
|
-
|
|
82901
|
+
} else if (plan.platform === "win32") {
|
|
82902
|
+
definitionChanged = true;
|
|
82903
|
+
}
|
|
82904
|
+
const inspection = inspectDaemonService(options);
|
|
82905
|
+
const outcome = resolveEnsureDefinitionOutcome({
|
|
82906
|
+
definitionChanged,
|
|
82907
|
+
hostState: inspection.state
|
|
82908
|
+
});
|
|
82909
|
+
if (outcome.updatePending) {
|
|
82910
|
+
return outcome;
|
|
82911
|
+
}
|
|
82912
|
+
if (inspection.state === "running" || inspection.state === "starting") {
|
|
82913
|
+
return outcome;
|
|
82434
82914
|
}
|
|
82915
|
+
const definitionCommands = inspection.state === "stopped" ? plan.reloadDefinitionCommands : plan.loadDefinitionCommands;
|
|
82916
|
+
for (const command of definitionCommands) run(command);
|
|
82917
|
+
return outcome;
|
|
82435
82918
|
}
|
|
82436
|
-
function
|
|
82437
|
-
const
|
|
82438
|
-
for (const
|
|
82439
|
-
|
|
82440
|
-
|
|
82441
|
-
|
|
82442
|
-
|
|
82443
|
-
|
|
82444
|
-
|
|
82445
|
-
|
|
82446
|
-
|
|
82447
|
-
|
|
82448
|
-
|
|
82919
|
+
function enableDaemonService(options = {}) {
|
|
82920
|
+
const { plan, run } = createHostContext(options);
|
|
82921
|
+
for (const command of plan.enableCommands) run(command);
|
|
82922
|
+
}
|
|
82923
|
+
function startDaemonService(options = {}) {
|
|
82924
|
+
const { plan, run } = createHostContext(options);
|
|
82925
|
+
for (const command of plan.startCommands) run(command);
|
|
82926
|
+
}
|
|
82927
|
+
function uninstallDaemonService(args = [], options = {}) {
|
|
82928
|
+
const ctx = createHostContext({ ...options, args: options.args ?? args });
|
|
82929
|
+
for (const command of ctx.plan.uninstallCommands) ctx.run(command);
|
|
82930
|
+
if (ctx.plan.manifestPath) ctx.removeManifest(ctx.plan.manifestPath);
|
|
82931
|
+
console.info("[alan-agent] Per-user daemon service removed");
|
|
82932
|
+
}
|
|
82933
|
+
function installDaemonService(args = [], runtime, options = {}) {
|
|
82934
|
+
const profile = resolveEndpointProfileFromArgs(args);
|
|
82935
|
+
const configPath = resolveAgentConfigPath({ profile });
|
|
82936
|
+
if (!configExistsAtPath(configPath)) {
|
|
82937
|
+
throw new Error(`No ${profile} runtime is configured. Run alan-agent setup or login first.`);
|
|
82938
|
+
}
|
|
82939
|
+
const headless = options.headless ?? args.includes("--headless");
|
|
82940
|
+
const merged = { ...options, args, runtime, headless };
|
|
82941
|
+
const ctx = createHostContext(merged);
|
|
82942
|
+
if (headless) {
|
|
82943
|
+
if (ctx.plan.platform !== "linux") {
|
|
82944
|
+
throw new Error("--headless is only supported on Linux systemd user services");
|
|
82449
82945
|
}
|
|
82946
|
+
assertSystemdUserLingerEnabled(merged);
|
|
82450
82947
|
}
|
|
82451
|
-
|
|
82452
|
-
|
|
82453
|
-
|
|
82454
|
-
|
|
82455
|
-
|
|
82948
|
+
const ensured = ensureDaemonServiceDefinition(merged);
|
|
82949
|
+
enableDaemonService(merged);
|
|
82950
|
+
const inspection = inspectDaemonService(merged);
|
|
82951
|
+
if (ensured.updatePending) {
|
|
82952
|
+
console.info("[alan-agent] Daemon service definition update pending; leaving running service", {
|
|
82953
|
+
profile,
|
|
82954
|
+
state: inspection.state
|
|
82955
|
+
});
|
|
82956
|
+
return;
|
|
82957
|
+
}
|
|
82958
|
+
if (!shouldStartOnInstall(inspection.state)) {
|
|
82959
|
+
console.info("[alan-agent] Per-user daemon service already present", {
|
|
82960
|
+
profile,
|
|
82961
|
+
state: inspection.state
|
|
82962
|
+
});
|
|
82963
|
+
return;
|
|
82964
|
+
}
|
|
82965
|
+
startDaemonService(merged);
|
|
82966
|
+
console.info("[alan-agent] Per-user daemon service installed", { profile });
|
|
82456
82967
|
}
|
|
82457
|
-
function
|
|
82458
|
-
|
|
82968
|
+
function printDaemonServiceStatus(args = []) {
|
|
82969
|
+
const plan = currentServicePlan(args);
|
|
82970
|
+
const result = runServiceCommand({ ...plan.statusCommand, tolerateFailure: true });
|
|
82971
|
+
if (result.status !== 0) {
|
|
82972
|
+
process.stdout.write(`unknown
|
|
82973
|
+
${result.output}
|
|
82974
|
+
`);
|
|
82975
|
+
return;
|
|
82976
|
+
}
|
|
82977
|
+
process.stdout.write(`${result.output}
|
|
82978
|
+
`);
|
|
82459
82979
|
}
|
|
82460
|
-
|
|
82461
|
-
|
|
82980
|
+
|
|
82981
|
+
// src/install-command.ts
|
|
82982
|
+
async function runInstallCommand(commandArgs) {
|
|
82983
|
+
bindConfigPath(commandArgs);
|
|
82984
|
+
const configured = readConfig();
|
|
82985
|
+
const configurationMode = resolveInstallConfigurationMode(commandArgs, configured);
|
|
82986
|
+
if (configurationMode === "setup") await setupDaemon(commandArgs);
|
|
82987
|
+
if (configurationMode === "login") await loginWithDeviceCode(commandArgs);
|
|
82988
|
+
installDaemonService(commandArgs);
|
|
82989
|
+
runMcpIntegrationCommand(["reconcile", ...commandArgs]);
|
|
82462
82990
|
}
|
|
82463
|
-
|
|
82464
|
-
|
|
82465
|
-
|
|
82466
|
-
|
|
82467
|
-
|
|
82468
|
-
|
|
82469
|
-
|
|
82470
|
-
|
|
82471
|
-
|
|
82472
|
-
|
|
82473
|
-
|
|
82474
|
-
|
|
82991
|
+
|
|
82992
|
+
// src/lifecycle-logger.ts
|
|
82993
|
+
var AgentLifecycleLogger = class _AgentLifecycleLogger {
|
|
82994
|
+
context;
|
|
82995
|
+
constructor(context = {}) {
|
|
82996
|
+
this.context = normalizeContext(context);
|
|
82997
|
+
}
|
|
82998
|
+
setContext(context) {
|
|
82999
|
+
this.context = normalizeContext({ ...this.context, ...context });
|
|
83000
|
+
}
|
|
83001
|
+
child(context) {
|
|
83002
|
+
return new _AgentLifecycleLogger({ ...this.context, ...context });
|
|
83003
|
+
}
|
|
83004
|
+
debug(event, fields = {}) {
|
|
83005
|
+
this.log("debug", event, fields);
|
|
83006
|
+
}
|
|
83007
|
+
info(event, fields = {}) {
|
|
83008
|
+
this.log("info", event, fields);
|
|
83009
|
+
}
|
|
83010
|
+
warn(event, fields = {}) {
|
|
83011
|
+
this.log("warn", event, fields);
|
|
83012
|
+
}
|
|
83013
|
+
error(event, fields = {}) {
|
|
83014
|
+
this.log("error", event, fields);
|
|
83015
|
+
}
|
|
83016
|
+
log(level, event, fields) {
|
|
83017
|
+
const record2 = omitUndefined({
|
|
83018
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83019
|
+
level,
|
|
83020
|
+
component: "agent-manager",
|
|
83021
|
+
event,
|
|
83022
|
+
...this.context,
|
|
83023
|
+
...normalizeFields(fields)
|
|
83024
|
+
});
|
|
83025
|
+
console[level](JSON.stringify(record2));
|
|
83026
|
+
}
|
|
83027
|
+
};
|
|
83028
|
+
function lifecycleContextFromEnv(env) {
|
|
83029
|
+
return normalizeContext({
|
|
83030
|
+
taskId: env.ALAN_TASK_ID,
|
|
83031
|
+
conversationId: env.ALAN_SESSION_ID,
|
|
83032
|
+
runId: env.ALAN_RUN_ID,
|
|
83033
|
+
sandboxId: env.ALAN_SANDBOX_ID,
|
|
83034
|
+
provider: env.ALAN_SANDBOX_PROVIDER,
|
|
83035
|
+
backendKind: env.ALAN_BACKEND_KIND,
|
|
83036
|
+
agentVersion: AGENT_VERSION
|
|
83037
|
+
});
|
|
82475
83038
|
}
|
|
82476
|
-
|
|
82477
|
-
|
|
82478
|
-
|
|
82479
|
-
|
|
82480
|
-
|
|
82481
|
-
|
|
82482
|
-
|
|
82483
|
-
|
|
82484
|
-
|
|
82485
|
-
|
|
82486
|
-
|
|
83039
|
+
function normalizeContext(context) {
|
|
83040
|
+
return omitUndefined({
|
|
83041
|
+
...context,
|
|
83042
|
+
agentVersion: context.agentVersion ?? AGENT_VERSION
|
|
83043
|
+
});
|
|
83044
|
+
}
|
|
83045
|
+
function normalizeFields(fields) {
|
|
83046
|
+
const normalized = {};
|
|
83047
|
+
for (const [key, value2] of Object.entries(fields)) {
|
|
83048
|
+
if (value2 instanceof Error) {
|
|
83049
|
+
normalized[key] = {
|
|
83050
|
+
name: value2.name,
|
|
83051
|
+
message: value2.message,
|
|
83052
|
+
stack: value2.stack
|
|
83053
|
+
};
|
|
83054
|
+
} else {
|
|
83055
|
+
normalized[key] = value2;
|
|
83056
|
+
}
|
|
83057
|
+
}
|
|
83058
|
+
return normalized;
|
|
83059
|
+
}
|
|
83060
|
+
function omitUndefined(record2) {
|
|
83061
|
+
return Object.fromEntries(Object.entries(record2).filter(([, value2]) => value2 !== void 0));
|
|
83062
|
+
}
|
|
83063
|
+
|
|
83064
|
+
// ../../node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
|
|
83065
|
+
var __create3 = Object.create;
|
|
83066
|
+
var __defProp3 = Object.defineProperty;
|
|
83067
|
+
var __getOwnPropDesc3 = Object.getOwnPropertyDescriptor;
|
|
83068
|
+
var __getOwnPropNames3 = Object.getOwnPropertyNames;
|
|
83069
|
+
var __getProtoOf3 = Object.getPrototypeOf;
|
|
83070
|
+
var __hasOwnProp3 = Object.prototype.hasOwnProperty;
|
|
83071
|
+
var __commonJSMin2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
83072
|
+
var __exportAll2 = (all, symbols) => {
|
|
83073
|
+
let target = {};
|
|
83074
|
+
for (var name in all) {
|
|
83075
|
+
__defProp3(target, name, {
|
|
83076
|
+
get: all[name],
|
|
83077
|
+
enumerable: true
|
|
83078
|
+
});
|
|
83079
|
+
}
|
|
83080
|
+
if (symbols) {
|
|
83081
|
+
__defProp3(target, Symbol.toStringTag, { value: "Module" });
|
|
83082
|
+
}
|
|
83083
|
+
return target;
|
|
83084
|
+
};
|
|
83085
|
+
var __copyProps3 = (to, from, except, desc) => {
|
|
83086
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
83087
|
+
for (var keys = __getOwnPropNames3(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
83088
|
+
key = keys[i];
|
|
83089
|
+
if (!__hasOwnProp3.call(to, key) && key !== except) {
|
|
83090
|
+
__defProp3(to, key, {
|
|
83091
|
+
get: ((k) => from[k]).bind(null, key),
|
|
83092
|
+
enumerable: !(desc = __getOwnPropDesc3(from, key)) || desc.enumerable
|
|
83093
|
+
});
|
|
83094
|
+
}
|
|
83095
|
+
}
|
|
83096
|
+
}
|
|
83097
|
+
return to;
|
|
83098
|
+
};
|
|
83099
|
+
var __toESM3 = (mod, isNodeMode, target) => (target = mod != null ? __create3(__getProtoOf3(mod)) : {}, __copyProps3(isNodeMode || !mod || !mod.__esModule ? __defProp3(target, "default", {
|
|
83100
|
+
value: mod,
|
|
83101
|
+
enumerable: true
|
|
83102
|
+
}) : target, mod));
|
|
83103
|
+
|
|
83104
|
+
// ../../node_modules/@modelcontextprotocol/server/dist/dialects-DoSzNhcb.mjs
|
|
83105
|
+
var DRAFT_2020_12_URIS2 = /* @__PURE__ */ new Set(["https://json-schema.org/draft/2020-12/schema", "http://json-schema.org/draft/2020-12/schema"]);
|
|
83106
|
+
var DRAFT_2019_09_URIS2 = /* @__PURE__ */ new Set(["https://json-schema.org/draft/2019-09/schema", "http://json-schema.org/draft/2019-09/schema"]);
|
|
83107
|
+
var DRAFT_07_URIS2 = /* @__PURE__ */ new Set(["https://json-schema.org/draft-07/schema", "http://json-schema.org/draft-07/schema"]);
|
|
83108
|
+
var DRAFT_06_URIS2 = /* @__PURE__ */ new Set(["https://json-schema.org/draft-06/schema", "http://json-schema.org/draft-06/schema"]);
|
|
83109
|
+
function declares2019Dialect2($schema) {
|
|
83110
|
+
return typeof $schema === "string" && DRAFT_2019_09_URIS2.has($schema.replace(/#$/, ""));
|
|
83111
|
+
}
|
|
83112
|
+
function declaredDialect2(schema, remedy) {
|
|
83113
|
+
if (!("$schema" in schema) || typeof schema.$schema !== "string") return "2020-12";
|
|
83114
|
+
const declared = schema.$schema.replace(/#$/, "");
|
|
83115
|
+
if (DRAFT_2020_12_URIS2.has(declared)) return "2020-12";
|
|
83116
|
+
if (DRAFT_2019_09_URIS2.has(declared)) return "2019-09";
|
|
83117
|
+
if (DRAFT_07_URIS2.has(declared) || DRAFT_06_URIS2.has(declared)) return "draft-7";
|
|
83118
|
+
throw new Error(`JSON Schema declares an unsupported dialect ("$schema": "${schema.$schema.slice(0, 200)}"). The default validator supports JSON Schema 2020-12, 2019-09, draft-07, and draft-06; ${remedy}`);
|
|
83119
|
+
}
|
|
83120
|
+
|
|
83121
|
+
// ../../node_modules/@modelcontextprotocol/server/dist/src-CX2iR2pK.mjs
|
|
83122
|
+
var BRANDS2 = /* @__PURE__ */ Symbol.for("mcp.sdk.errorBrands");
|
|
83123
|
+
function stampErrorBrands2(instance, ctor) {
|
|
83124
|
+
const brands = /* @__PURE__ */ new Set();
|
|
83125
|
+
let current = ctor;
|
|
83126
|
+
while (typeof current === "function") {
|
|
83127
|
+
const brand = current.mcpBrand;
|
|
83128
|
+
if (Object.prototype.hasOwnProperty.call(current, "mcpBrand") && typeof brand === "string") brands.add(brand);
|
|
83129
|
+
current = Object.getPrototypeOf(current);
|
|
83130
|
+
}
|
|
83131
|
+
if (brands.size === 0) return;
|
|
83132
|
+
Object.defineProperty(instance, BRANDS2, {
|
|
83133
|
+
value: brands,
|
|
83134
|
+
enumerable: false,
|
|
83135
|
+
configurable: true
|
|
83136
|
+
});
|
|
83137
|
+
}
|
|
83138
|
+
function brandedHasInstance2(cls, value2) {
|
|
83139
|
+
try {
|
|
83140
|
+
if (typeof value2 === "object" && value2 !== null && Object.prototype.hasOwnProperty.call(cls, "mcpBrand") && typeof cls.mcpBrand === "string" && Object.prototype.hasOwnProperty.call(value2, BRANDS2)) {
|
|
83141
|
+
const carried = value2[BRANDS2];
|
|
83142
|
+
if (carried && typeof carried.has === "function" && carried.has(cls.mcpBrand)) return true;
|
|
83143
|
+
}
|
|
83144
|
+
} catch {
|
|
83145
|
+
}
|
|
83146
|
+
return Function.prototype[Symbol.hasInstance].call(cls, value2);
|
|
83147
|
+
}
|
|
83148
|
+
var OAuthError3 = class OAuthError4 extends Error {
|
|
83149
|
+
static {
|
|
83150
|
+
Object.defineProperty(this, "mcpBrand", { value: "mcp.OAuthError" });
|
|
83151
|
+
}
|
|
83152
|
+
static [Symbol.hasInstance](value2) {
|
|
83153
|
+
return brandedHasInstance2(this, value2);
|
|
83154
|
+
}
|
|
83155
|
+
/**
|
|
83156
|
+
* Brand-based type guard: equivalent to `value instanceof this`, as an
|
|
83157
|
+
* explicit static predicate (the axios/AWS-SDK `isInstance` style). Reads
|
|
83158
|
+
* the caller's own brand via `this`, so every branded subclass gets a
|
|
83159
|
+
* correctly-scoped guard by inheritance. Must be invoked on the class —
|
|
83160
|
+
* in callback position write `v => SdkError.isInstance(v)`, not
|
|
83161
|
+
* `.filter(SdkError.isInstance)` (detached calls throw rather than
|
|
83162
|
+
* silently matching nothing).
|
|
83163
|
+
*/
|
|
83164
|
+
static isInstance(value2) {
|
|
83165
|
+
if (typeof this !== "function") throw new TypeError("isInstance must be called on the class (e.g. `SdkError.isInstance(value)`); for callbacks use `v => SdkError.isInstance(v)`");
|
|
83166
|
+
return brandedHasInstance2(this, value2);
|
|
83167
|
+
}
|
|
83168
|
+
constructor(code, message, errorUri) {
|
|
83169
|
+
super(message);
|
|
83170
|
+
this.code = code;
|
|
83171
|
+
this.errorUri = errorUri;
|
|
83172
|
+
this.name = "OAuthError";
|
|
83173
|
+
stampErrorBrands2(this, new.target);
|
|
83174
|
+
}
|
|
83175
|
+
/**
|
|
83176
|
+
* Converts the error to a standard OAuth error response object.
|
|
83177
|
+
*/
|
|
83178
|
+
toResponseObject() {
|
|
83179
|
+
const response = {
|
|
83180
|
+
error: this.code,
|
|
83181
|
+
error_description: this.message
|
|
83182
|
+
};
|
|
83183
|
+
if (this.errorUri) response.error_uri = this.errorUri;
|
|
83184
|
+
return response;
|
|
83185
|
+
}
|
|
83186
|
+
/**
|
|
83187
|
+
* Creates an {@linkcode OAuthError} from an OAuth error response.
|
|
83188
|
+
*/
|
|
83189
|
+
static fromResponse(response) {
|
|
83190
|
+
return new OAuthError4(response.error, response.error_description ?? response.error, response.error_uri);
|
|
83191
|
+
}
|
|
83192
|
+
};
|
|
83193
|
+
var SdkErrorCode2 = /* @__PURE__ */ (function(SdkErrorCode$1) {
|
|
83194
|
+
SdkErrorCode$1["NotConnected"] = "NOT_CONNECTED";
|
|
83195
|
+
SdkErrorCode$1["AlreadyConnected"] = "ALREADY_CONNECTED";
|
|
83196
|
+
SdkErrorCode$1["NotInitialized"] = "NOT_INITIALIZED";
|
|
83197
|
+
SdkErrorCode$1["CapabilityNotSupported"] = "CAPABILITY_NOT_SUPPORTED";
|
|
83198
|
+
SdkErrorCode$1["RequestTimeout"] = "REQUEST_TIMEOUT";
|
|
83199
|
+
SdkErrorCode$1["ConnectionClosed"] = "CONNECTION_CLOSED";
|
|
83200
|
+
SdkErrorCode$1["SendFailed"] = "SEND_FAILED";
|
|
83201
|
+
SdkErrorCode$1["InvalidResult"] = "INVALID_RESULT";
|
|
83202
|
+
SdkErrorCode$1["UnsupportedResultType"] = "UNSUPPORTED_RESULT_TYPE";
|
|
83203
|
+
SdkErrorCode$1["InputRequiredRoundsExceeded"] = "INPUT_REQUIRED_ROUNDS_EXCEEDED";
|
|
83204
|
+
SdkErrorCode$1["ListPaginationExceeded"] = "LIST_PAGINATION_EXCEEDED";
|
|
83205
|
+
SdkErrorCode$1["MethodNotSupportedByProtocolVersion"] = "METHOD_NOT_SUPPORTED_BY_PROTOCOL_VERSION";
|
|
83206
|
+
SdkErrorCode$1["EraNegotiationFailed"] = "ERA_NEGOTIATION_FAILED";
|
|
83207
|
+
SdkErrorCode$1["ClientHttpNotImplemented"] = "CLIENT_HTTP_NOT_IMPLEMENTED";
|
|
83208
|
+
SdkErrorCode$1["ClientHttpAuthentication"] = "CLIENT_HTTP_AUTHENTICATION";
|
|
83209
|
+
SdkErrorCode$1["ClientHttpForbidden"] = "CLIENT_HTTP_FORBIDDEN";
|
|
83210
|
+
SdkErrorCode$1["ClientHttpUnexpectedContent"] = "CLIENT_HTTP_UNEXPECTED_CONTENT";
|
|
83211
|
+
SdkErrorCode$1["ClientHttpFailedToOpenStream"] = "CLIENT_HTTP_FAILED_TO_OPEN_STREAM";
|
|
83212
|
+
SdkErrorCode$1["ClientHttpFailedToTerminateSession"] = "CLIENT_HTTP_FAILED_TO_TERMINATE_SESSION";
|
|
83213
|
+
return SdkErrorCode$1;
|
|
83214
|
+
})({});
|
|
83215
|
+
var SdkError2 = class extends Error {
|
|
83216
|
+
static {
|
|
83217
|
+
Object.defineProperty(this, "mcpBrand", { value: "mcp.SdkError" });
|
|
83218
|
+
}
|
|
83219
|
+
static [Symbol.hasInstance](value2) {
|
|
83220
|
+
return brandedHasInstance2(this, value2);
|
|
83221
|
+
}
|
|
83222
|
+
/**
|
|
83223
|
+
* Brand-based type guard: equivalent to `value instanceof this`, as an
|
|
83224
|
+
* explicit static predicate (the axios/AWS-SDK `isInstance` style). Reads
|
|
83225
|
+
* the caller's own brand via `this`, so every branded subclass gets a
|
|
83226
|
+
* correctly-scoped guard by inheritance. Must be invoked on the class —
|
|
83227
|
+
* in callback position write `v => SdkError.isInstance(v)`, not
|
|
83228
|
+
* `.filter(SdkError.isInstance)` (detached calls throw rather than
|
|
83229
|
+
* silently matching nothing).
|
|
83230
|
+
*/
|
|
83231
|
+
static isInstance(value2) {
|
|
83232
|
+
if (typeof this !== "function") throw new TypeError("isInstance must be called on the class (e.g. `SdkError.isInstance(value)`); for callbacks use `v => SdkError.isInstance(v)`");
|
|
83233
|
+
return brandedHasInstance2(this, value2);
|
|
83234
|
+
}
|
|
83235
|
+
constructor(code, message, data) {
|
|
83236
|
+
super(message);
|
|
83237
|
+
this.code = code;
|
|
83238
|
+
this.data = data;
|
|
83239
|
+
this.name = "SdkError";
|
|
83240
|
+
stampErrorBrands2(this, new.target);
|
|
83241
|
+
}
|
|
83242
|
+
};
|
|
83243
|
+
var SdkHttpError2 = class extends SdkError2 {
|
|
83244
|
+
static {
|
|
83245
|
+
Object.defineProperty(this, "mcpBrand", { value: "mcp.SdkHttpError" });
|
|
83246
|
+
}
|
|
83247
|
+
constructor(code, message, data) {
|
|
83248
|
+
super(code, message, data);
|
|
83249
|
+
this.name = "SdkHttpError";
|
|
83250
|
+
}
|
|
83251
|
+
get status() {
|
|
83252
|
+
return this.data.status;
|
|
83253
|
+
}
|
|
83254
|
+
get statusText() {
|
|
83255
|
+
return this.data.statusText;
|
|
83256
|
+
}
|
|
83257
|
+
};
|
|
83258
|
+
function isPlainObject$7(value2) {
|
|
83259
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
83260
|
+
}
|
|
83261
|
+
function isImpliedCapabilityMember(capability, member, declaredValue) {
|
|
83262
|
+
return capability === "elicitation" && member === "form" && declaredValue["form"] === void 0 && declaredValue["url"] === void 0;
|
|
83263
|
+
}
|
|
83264
|
+
function requiredClientCapabilitiesForInputRequest(entry) {
|
|
83265
|
+
switch (entry.method) {
|
|
83266
|
+
case "elicitation/create":
|
|
83267
|
+
if (entry.params?.["mode"] === "url") return { elicitation: { url: {} } };
|
|
83268
|
+
return { elicitation: { form: {} } };
|
|
83269
|
+
case "sampling/createMessage": {
|
|
83270
|
+
const params = entry.params;
|
|
83271
|
+
if (params !== void 0 && (params["tools"] !== void 0 || params["toolChoice"] !== void 0)) return { sampling: { tools: {} } };
|
|
83272
|
+
return { sampling: {} };
|
|
83273
|
+
}
|
|
83274
|
+
case "roots/list":
|
|
83275
|
+
return { roots: {} };
|
|
83276
|
+
default:
|
|
83277
|
+
return;
|
|
83278
|
+
}
|
|
83279
|
+
}
|
|
83280
|
+
function missingClientCapabilities(required2, declared) {
|
|
83281
|
+
const missing = {};
|
|
83282
|
+
for (const [capability, requirement] of Object.entries(required2)) {
|
|
83283
|
+
if (requirement === void 0) continue;
|
|
83284
|
+
const declaredValue = declared === void 0 ? void 0 : declared[capability];
|
|
83285
|
+
if (declaredValue === void 0) {
|
|
83286
|
+
missing[capability] = requirement;
|
|
83287
|
+
continue;
|
|
83288
|
+
}
|
|
83289
|
+
if (isPlainObject$7(requirement) && isPlainObject$7(declaredValue)) {
|
|
83290
|
+
const missingMembers = {};
|
|
83291
|
+
for (const [member, memberRequirement] of Object.entries(requirement)) if (memberRequirement !== void 0 && declaredValue[member] === void 0 && !isImpliedCapabilityMember(capability, member, declaredValue)) missingMembers[member] = memberRequirement;
|
|
83292
|
+
if (Object.keys(missingMembers).length > 0) missing[capability] = missingMembers;
|
|
83293
|
+
}
|
|
83294
|
+
}
|
|
83295
|
+
return Object.keys(missing).length > 0 ? missing : void 0;
|
|
83296
|
+
}
|
|
83297
|
+
var FIRST_MODERN_PROTOCOL_VERSION2 = "2026-07-28";
|
|
83298
|
+
function isModernProtocolVersion2(version2) {
|
|
83299
|
+
return version2 >= FIRST_MODERN_PROTOCOL_VERSION2;
|
|
83300
|
+
}
|
|
83301
|
+
function legacyProtocolVersions2(versions) {
|
|
83302
|
+
return versions.filter((version2) => !isModernProtocolVersion2(version2));
|
|
83303
|
+
}
|
|
83304
|
+
function modernProtocolVersions2(versions) {
|
|
83305
|
+
return versions.filter((version2) => isModernProtocolVersion2(version2));
|
|
83306
|
+
}
|
|
83307
|
+
function appendTextFallbackForNonObject2(result) {
|
|
83308
|
+
const sc = result.structuredContent;
|
|
83309
|
+
if (sc === void 0) return result;
|
|
83310
|
+
if (!(typeof sc !== "object" || sc === null || Array.isArray(sc))) return result;
|
|
83311
|
+
if (result.content?.some((c) => c.type === "text") ?? false) return result;
|
|
83312
|
+
return {
|
|
83313
|
+
...result,
|
|
83314
|
+
content: [...result.content ?? [], {
|
|
83315
|
+
type: "text",
|
|
83316
|
+
text: JSON.stringify(sc)
|
|
83317
|
+
}]
|
|
83318
|
+
};
|
|
83319
|
+
}
|
|
83320
|
+
var TOOL_RESULT_FOREIGN_FAMILY_KEYS2 = [
|
|
83321
|
+
"task",
|
|
83322
|
+
"inputRequests",
|
|
83323
|
+
"requestState"
|
|
83324
|
+
];
|
|
83325
|
+
function normalizeContentlessToolResult2(value2) {
|
|
83326
|
+
if (value2 === null || typeof value2 !== "object" || Array.isArray(value2) || value2.content !== void 0 || TOOL_RESULT_FOREIGN_FAMILY_KEYS2.some((key) => key in value2)) return value2;
|
|
83327
|
+
return {
|
|
83328
|
+
...value2,
|
|
83329
|
+
content: []
|
|
83330
|
+
};
|
|
82487
83331
|
}
|
|
82488
83332
|
function build$12() {
|
|
82489
83333
|
const JSONValueSchema$1 = lazy(() => union([
|
|
@@ -94584,27 +95428,27 @@ async function runMcpStdioProxy(env = process.env, local = new StdioServerTransp
|
|
|
94584
95428
|
|
|
94585
95429
|
// src/native-hook-command.ts
|
|
94586
95430
|
var import_node_crypto21 = require("crypto");
|
|
94587
|
-
var
|
|
94588
|
-
var
|
|
94589
|
-
var
|
|
95431
|
+
var import_node_fs27 = require("fs");
|
|
95432
|
+
var import_node_os17 = require("os");
|
|
95433
|
+
var import_node_path29 = require("path");
|
|
94590
95434
|
|
|
94591
95435
|
// src/native-project-config.ts
|
|
94592
|
-
var
|
|
94593
|
-
var
|
|
95436
|
+
var import_node_fs26 = require("fs");
|
|
95437
|
+
var import_node_path28 = require("path");
|
|
94594
95438
|
var MAX_ALAN_PROJECT_CONFIG_BYTES = 64 * 1024;
|
|
94595
95439
|
var ORGANIZATION_SLUG_PATTERN = /^[a-z0-9-]+$/;
|
|
94596
95440
|
var TEAM_IDENTIFIER_PATTERN = /^[A-Z0-9]{2,4}$/i;
|
|
94597
95441
|
function readAlanProjectPin(cwd) {
|
|
94598
95442
|
let fd;
|
|
94599
95443
|
try {
|
|
94600
|
-
fd = (0,
|
|
94601
|
-
(0,
|
|
94602
|
-
|
|
95444
|
+
fd = (0, import_node_fs26.openSync)(
|
|
95445
|
+
(0, import_node_path28.join)(cwd, "alan.json"),
|
|
95446
|
+
import_node_fs26.constants.O_RDONLY | import_node_fs26.constants.O_NONBLOCK | (import_node_fs26.constants.O_NOFOLLOW ?? 0)
|
|
94603
95447
|
);
|
|
94604
|
-
const stat2 = (0,
|
|
95448
|
+
const stat2 = (0, import_node_fs26.fstatSync)(fd);
|
|
94605
95449
|
if (!stat2.isFile() || stat2.size > MAX_ALAN_PROJECT_CONFIG_BYTES) return void 0;
|
|
94606
95450
|
const buffer = Buffer.allocUnsafe(MAX_ALAN_PROJECT_CONFIG_BYTES + 1);
|
|
94607
|
-
const bytesRead = (0,
|
|
95451
|
+
const bytesRead = (0, import_node_fs26.readSync)(fd, buffer, 0, buffer.byteLength, 0);
|
|
94608
95452
|
if (bytesRead > MAX_ALAN_PROJECT_CONFIG_BYTES) return void 0;
|
|
94609
95453
|
const parsed = JSON.parse(buffer.subarray(0, bytesRead).toString("utf8"));
|
|
94610
95454
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
@@ -94620,7 +95464,7 @@ function readAlanProjectPin(cwd) {
|
|
|
94620
95464
|
} finally {
|
|
94621
95465
|
if (fd !== void 0) {
|
|
94622
95466
|
try {
|
|
94623
|
-
(0,
|
|
95467
|
+
(0, import_node_fs26.closeSync)(fd);
|
|
94624
95468
|
} catch {
|
|
94625
95469
|
}
|
|
94626
95470
|
}
|
|
@@ -94859,19 +95703,19 @@ function nonNegativeIntegerField(payload, ...names) {
|
|
|
94859
95703
|
return void 0;
|
|
94860
95704
|
}
|
|
94861
95705
|
function resolveCodexSessionIdFromTranscriptPath(transcriptPath) {
|
|
94862
|
-
const fileName = (0,
|
|
95706
|
+
const fileName = (0, import_node_path29.basename)(transcriptPath);
|
|
94863
95707
|
const match = /^rollout-.*-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i.exec(
|
|
94864
95708
|
fileName
|
|
94865
95709
|
);
|
|
94866
95710
|
return match?.[1];
|
|
94867
95711
|
}
|
|
94868
|
-
function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0,
|
|
94869
|
-
if ((0,
|
|
94870
|
-
const sessionsDir = (0,
|
|
94871
|
-
if (!(0,
|
|
94872
|
-
for (const workspace of (0,
|
|
95712
|
+
function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path29.join)((0, import_node_os17.homedir)(), ".kimi-code")) {
|
|
95713
|
+
if ((0, import_node_path29.basename)(externalSessionId) !== externalSessionId) return void 0;
|
|
95714
|
+
const sessionsDir = (0, import_node_path29.join)(kimiHomeDir, "sessions");
|
|
95715
|
+
if (!(0, import_node_fs27.existsSync)(sessionsDir)) return void 0;
|
|
95716
|
+
for (const workspace of (0, import_node_fs27.readdirSync)(sessionsDir, { withFileTypes: true })) {
|
|
94873
95717
|
if (!workspace.isDirectory()) continue;
|
|
94874
|
-
const transcriptPath = (0,
|
|
95718
|
+
const transcriptPath = (0, import_node_path29.join)(
|
|
94875
95719
|
sessionsDir,
|
|
94876
95720
|
workspace.name,
|
|
94877
95721
|
externalSessionId,
|
|
@@ -94879,7 +95723,7 @@ function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.
|
|
|
94879
95723
|
"main",
|
|
94880
95724
|
"wire.jsonl"
|
|
94881
95725
|
);
|
|
94882
|
-
if ((0,
|
|
95726
|
+
if ((0, import_node_fs27.existsSync)(transcriptPath)) return transcriptPath;
|
|
94883
95727
|
}
|
|
94884
95728
|
return void 0;
|
|
94885
95729
|
}
|
|
@@ -94914,7 +95758,7 @@ function parseNativeHookEnvelope(input2) {
|
|
|
94914
95758
|
const rawHookEvent = input2.hookEvent ?? stringField4(payload, "hook_event_name", "hookEvent", "hookEventName", "type") ?? "notification";
|
|
94915
95759
|
const eventType = normalizeHookEvent(rawHookEvent);
|
|
94916
95760
|
const cwd = stringField4(payload, "cwd", "working_directory", "workingDirectory") ?? firstStringArrayField(payload, "workspace_roots", "workspaceRoots");
|
|
94917
|
-
const resolvedCwd = cwd ? (0,
|
|
95761
|
+
const resolvedCwd = cwd ? (0, import_node_path29.resolve)(cwd) : void 0;
|
|
94918
95762
|
const transcriptPath = eventType === "subagent_start" || eventType === "subagent_end" ? stringField4(
|
|
94919
95763
|
payload,
|
|
94920
95764
|
"agent_transcript_path",
|
|
@@ -94960,7 +95804,7 @@ function parseNativeHookEnvelope(input2) {
|
|
|
94960
95804
|
...(eventType === "subagent_start" || eventType === "subagent_end") && parentSessionId ? { parentExternalSessionId: parentSessionId } : {},
|
|
94961
95805
|
...resolvedCwd ? { cwd: resolvedCwd } : {},
|
|
94962
95806
|
...projectPin,
|
|
94963
|
-
...transcriptPath ? { transcriptPath: (0,
|
|
95807
|
+
...transcriptPath ? { transcriptPath: (0, import_node_path29.resolve)(transcriptPath) } : {},
|
|
94964
95808
|
...cursor ? { sourceCursor: cursor } : {},
|
|
94965
95809
|
providerPayload
|
|
94966
95810
|
};
|
|
@@ -95007,7 +95851,7 @@ function readBoundedHookPayload(fd = 0, maxBytes = MAX_NATIVE_HOOK_STDIN_BYTES)
|
|
|
95007
95851
|
let totalBytes = 0;
|
|
95008
95852
|
while (true) {
|
|
95009
95853
|
const chunk = Buffer.allocUnsafe(Math.min(64 * 1024, maxBytes + 1 - totalBytes));
|
|
95010
|
-
const bytesRead = (0,
|
|
95854
|
+
const bytesRead = (0, import_node_fs27.readSync)(fd, chunk, 0, chunk.byteLength, null);
|
|
95011
95855
|
if (bytesRead === 0) break;
|
|
95012
95856
|
totalBytes += bytesRead;
|
|
95013
95857
|
if (totalBytes > maxBytes) throw new Error(`hook input exceeds ${maxBytes} bytes`);
|
|
@@ -95090,7 +95934,7 @@ function collectNativeIntegrationStatus(args = []) {
|
|
|
95090
95934
|
const config2 = readConfig();
|
|
95091
95935
|
const configPath = getConfigPath();
|
|
95092
95936
|
const env = getDaemonCliEnvironment();
|
|
95093
|
-
const homeDir = (0,
|
|
95937
|
+
const homeDir = (0, import_node_os17.homedir)();
|
|
95094
95938
|
return NATIVE_SESSION_PROVIDER_CAPABILITIES.map((capability) => ({
|
|
95095
95939
|
provider: capability.providerKind,
|
|
95096
95940
|
command: capability.command,
|
|
@@ -95119,7 +95963,7 @@ function decodeResumeFallbackContext(encoded) {
|
|
|
95119
95963
|
}
|
|
95120
95964
|
|
|
95121
95965
|
// src/sandbox.ts
|
|
95122
|
-
var
|
|
95966
|
+
var import_node_os18 = require("os");
|
|
95123
95967
|
|
|
95124
95968
|
// src/execution-activity-tracker.ts
|
|
95125
95969
|
var ExecutionActivityTracker = class {
|
|
@@ -95733,7 +96577,7 @@ var agentProbeAckSchema = external_exports.object({
|
|
|
95733
96577
|
|
|
95734
96578
|
// src/sandbox-outbox.ts
|
|
95735
96579
|
var import_node_crypto23 = require("crypto");
|
|
95736
|
-
var
|
|
96580
|
+
var import_node_fs28 = require("fs");
|
|
95737
96581
|
function deriveSandboxOutboxKey(sessionToken) {
|
|
95738
96582
|
if (!sessionToken) {
|
|
95739
96583
|
throw new Error("sandbox event outbox requires ALAN_SESSION_TOKEN for key derivation");
|
|
@@ -95754,24 +96598,24 @@ function assertValidOutboxKey(key, path2) {
|
|
|
95754
96598
|
}
|
|
95755
96599
|
function loadOrCreateSandboxOutboxKey(input2) {
|
|
95756
96600
|
const keyPath = sandboxOutboxKeyPath(input2.spoolPath);
|
|
95757
|
-
if ((0,
|
|
95758
|
-
(0,
|
|
95759
|
-
return assertValidOutboxKey((0,
|
|
96601
|
+
if ((0, import_node_fs28.existsSync)(keyPath)) {
|
|
96602
|
+
(0, import_node_fs28.chmodSync)(keyPath, 384);
|
|
96603
|
+
return assertValidOutboxKey((0, import_node_fs28.readFileSync)(keyPath, "utf8").trim(), keyPath);
|
|
95760
96604
|
}
|
|
95761
96605
|
const initialKey = deriveSandboxOutboxKey(input2.sessionToken);
|
|
95762
96606
|
try {
|
|
95763
|
-
(0,
|
|
96607
|
+
(0, import_node_fs28.writeFileSync)(keyPath, initialKey, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
95764
96608
|
return initialKey;
|
|
95765
96609
|
} catch (error61) {
|
|
95766
96610
|
if (error61.code !== "EEXIST") throw error61;
|
|
95767
|
-
(0,
|
|
95768
|
-
return assertValidOutboxKey((0,
|
|
96611
|
+
(0, import_node_fs28.chmodSync)(keyPath, 384);
|
|
96612
|
+
return assertValidOutboxKey((0, import_node_fs28.readFileSync)(keyPath, "utf8").trim(), keyPath);
|
|
95769
96613
|
}
|
|
95770
96614
|
}
|
|
95771
96615
|
function quarantineUnusableOutbox(path2) {
|
|
95772
96616
|
const suffix = `corrupt-${Date.now()}-${process.pid}`;
|
|
95773
96617
|
for (const candidate of [path2, eventJournalDir(path2)]) {
|
|
95774
|
-
if ((0,
|
|
96618
|
+
if ((0, import_node_fs28.existsSync)(candidate)) (0, import_node_fs28.renameSync)(candidate, `${candidate}.${suffix}`);
|
|
95775
96619
|
}
|
|
95776
96620
|
}
|
|
95777
96621
|
function createSandboxEventOutbox(input2) {
|
|
@@ -96183,6 +97027,7 @@ var WSClient = class {
|
|
|
96183
97027
|
providerSessionId: data.providerSessionId,
|
|
96184
97028
|
resumeFallbackContext: data.resumeFallbackContext,
|
|
96185
97029
|
backendKind: data.backendKind,
|
|
97030
|
+
providerApiKey: data.providerApiKey,
|
|
96186
97031
|
agentId: data.agentId,
|
|
96187
97032
|
agentPrompt: data.agentPrompt,
|
|
96188
97033
|
selectedModel: data.selectedModel,
|
|
@@ -96200,7 +97045,10 @@ var WSClient = class {
|
|
|
96200
97045
|
cloudEnvironmentId: data.cloudEnvironmentId,
|
|
96201
97046
|
conversationId: data.conversationId,
|
|
96202
97047
|
teamId: data.teamId,
|
|
96203
|
-
currentUser: data.currentUser
|
|
97048
|
+
currentUser: data.currentUser,
|
|
97049
|
+
terminalContextRefs: data.terminalContextRefs,
|
|
97050
|
+
terminalSnapshots: data.terminalSnapshots,
|
|
97051
|
+
externalMcpServers: data.externalMcpServers
|
|
96204
97052
|
};
|
|
96205
97053
|
const acceptDelivery = () => {
|
|
96206
97054
|
if (data.messageId) this.rememberAcceptedMessageId(data.messageId);
|
|
@@ -96224,6 +97072,9 @@ var WSClient = class {
|
|
|
96224
97072
|
this.socket.on("stop", () => {
|
|
96225
97073
|
callbacks.onStop();
|
|
96226
97074
|
});
|
|
97075
|
+
this.socket.on("agent.abort", (data) => {
|
|
97076
|
+
callbacks.onAbort?.({ runId: data?.runId, reason: data?.reason });
|
|
97077
|
+
});
|
|
96227
97078
|
this.socket.on("tool_response", (data) => {
|
|
96228
97079
|
if (data?.toolId && typeof data.response === "string") {
|
|
96229
97080
|
callbacks.onToolResponse?.(data.toolId, data.response);
|
|
@@ -96281,6 +97132,7 @@ async function runSandbox(config2) {
|
|
|
96281
97132
|
let currentTaskMeta;
|
|
96282
97133
|
let currentPrMeta;
|
|
96283
97134
|
let currentWorkflowTools;
|
|
97135
|
+
let currentExternalMcpServers;
|
|
96284
97136
|
let currentMaxIterations = config2.maxIterations ?? 50;
|
|
96285
97137
|
let currentTaskId = config2.taskId;
|
|
96286
97138
|
let currentConversationId = config2.sessionId;
|
|
@@ -96375,6 +97227,14 @@ async function runSandbox(config2) {
|
|
|
96375
97227
|
lifecycle.info("sandbox_agent_stop_received");
|
|
96376
97228
|
stopActiveAgent();
|
|
96377
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
|
+
},
|
|
96378
97238
|
onToolResponse: (toolId, response) => {
|
|
96379
97239
|
if (currentAgent) {
|
|
96380
97240
|
const sent = currentAgent.sendToolResponse(toolId, response);
|
|
@@ -96431,7 +97291,7 @@ async function runSandbox(config2) {
|
|
|
96431
97291
|
}
|
|
96432
97292
|
const presenter = new WebPresenter(wsClient, config2.sessionId, config2.projectPath);
|
|
96433
97293
|
presenter.setSuppressSessionLifecycle(true);
|
|
96434
|
-
const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0,
|
|
97294
|
+
const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os18.homedir)() });
|
|
96435
97295
|
let lastProviderSessionId = config2.providerSessionId;
|
|
96436
97296
|
let resumeFallbackContext = config2.resumeFallbackContext;
|
|
96437
97297
|
let activeBackendKind = config2.backendKind || "claude_cli";
|
|
@@ -96571,6 +97431,7 @@ async function runSandbox(config2) {
|
|
|
96571
97431
|
resumeFallbackContext,
|
|
96572
97432
|
taskMeta: currentTaskMeta,
|
|
96573
97433
|
prMeta: currentPrMeta,
|
|
97434
|
+
externalMcpServers: currentExternalMcpServers,
|
|
96574
97435
|
taskId: currentTaskId,
|
|
96575
97436
|
conversationId: currentConversationId,
|
|
96576
97437
|
alanMcp: currentAlanMcp,
|
|
@@ -96688,6 +97549,7 @@ async function runSandbox(config2) {
|
|
|
96688
97549
|
activeMode = nextPayload.mode;
|
|
96689
97550
|
}
|
|
96690
97551
|
currentAlanMcp = nextPayload.alanMcp;
|
|
97552
|
+
currentExternalMcpServers = nextPayload.externalMcpServers;
|
|
96691
97553
|
if (nextPayload.taskMeta !== void 0) {
|
|
96692
97554
|
currentTaskMeta = nextPayload.taskMeta;
|
|
96693
97555
|
}
|
|
@@ -96728,616 +97590,6 @@ async function runSandbox(config2) {
|
|
|
96728
97590
|
wsClient.close();
|
|
96729
97591
|
}
|
|
96730
97592
|
|
|
96731
|
-
// src/service-manager.ts
|
|
96732
|
-
var import_node_child_process9 = require("child_process");
|
|
96733
|
-
var import_node_fs28 = require("fs");
|
|
96734
|
-
var import_node_os18 = require("os");
|
|
96735
|
-
var import_node_path29 = require("path");
|
|
96736
|
-
var SERVICE_LABEL = "ai.tryalan.agent";
|
|
96737
|
-
var SYSTEMD_UNIT = "alan-agent.service";
|
|
96738
|
-
var WINDOWS_TASK = "Alan Agent";
|
|
96739
|
-
function xml(value2) {
|
|
96740
|
-
return value2.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
96741
|
-
}
|
|
96742
|
-
function systemdArg(value2) {
|
|
96743
|
-
return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
96744
|
-
}
|
|
96745
|
-
function powershellLiteral(value2) {
|
|
96746
|
-
return `'${value2.replaceAll("'", "''")}'`;
|
|
96747
|
-
}
|
|
96748
|
-
function serviceNames(profile) {
|
|
96749
|
-
if (profile === "production") {
|
|
96750
|
-
return { launchd: SERVICE_LABEL, systemd: SYSTEMD_UNIT, windows: WINDOWS_TASK };
|
|
96751
|
-
}
|
|
96752
|
-
const suffix = profile === "custom" ? "prod" : profile;
|
|
96753
|
-
const title = `${suffix[0]?.toUpperCase()}${suffix.slice(1)}`;
|
|
96754
|
-
return {
|
|
96755
|
-
launchd: `${SERVICE_LABEL}.${suffix}`,
|
|
96756
|
-
systemd: `alan-agent-${suffix}.service`,
|
|
96757
|
-
windows: `${WINDOWS_TASK} ${title}`
|
|
96758
|
-
};
|
|
96759
|
-
}
|
|
96760
|
-
function buildDaemonServicePlan(input2) {
|
|
96761
|
-
const daemonArgs = [input2.nodeExecutable, input2.cliEntry, "daemon", "--profile", input2.profile];
|
|
96762
|
-
const names = serviceNames(input2.profile);
|
|
96763
|
-
if (input2.platform === "darwin") {
|
|
96764
|
-
const userId = input2.userId ?? process.getuid?.();
|
|
96765
|
-
if (userId === void 0) throw new Error("Cannot determine the current macOS user ID");
|
|
96766
|
-
const domain2 = `gui/${userId}`;
|
|
96767
|
-
const serviceTarget = `${domain2}/${names.launchd}`;
|
|
96768
|
-
const manifestPath = (0, import_node_path29.join)(input2.homeDir, "Library", "LaunchAgents", `${names.launchd}.plist`);
|
|
96769
|
-
const logDir = (0, import_node_path29.join)(resolveAgentConfigDirectory(input2.profile, input2.homeDir), "logs");
|
|
96770
|
-
const programArguments = daemonArgs.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
|
|
96771
|
-
const environmentEntries = Object.entries(input2.environment ?? {}).map(([key, value2]) => ` <key>${xml(key)}</key>
|
|
96772
|
-
<string>${xml(value2)}</string>`).join("\n");
|
|
96773
|
-
const environmentBlock = environmentEntries ? ` <key>EnvironmentVariables</key>
|
|
96774
|
-
<dict>
|
|
96775
|
-
${environmentEntries}
|
|
96776
|
-
</dict>
|
|
96777
|
-
` : "";
|
|
96778
|
-
const manifest = `<?xml version="1.0" encoding="UTF-8"?>
|
|
96779
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
96780
|
-
<plist version="1.0">
|
|
96781
|
-
<dict>
|
|
96782
|
-
<key>Label</key>
|
|
96783
|
-
<string>${names.launchd}</string>
|
|
96784
|
-
<key>ProgramArguments</key>
|
|
96785
|
-
<array>
|
|
96786
|
-
${programArguments}
|
|
96787
|
-
</array>
|
|
96788
|
-
${environmentBlock} <key>RunAtLoad</key>
|
|
96789
|
-
<true/>
|
|
96790
|
-
<key>KeepAlive</key>
|
|
96791
|
-
<dict>
|
|
96792
|
-
<key>SuccessfulExit</key>
|
|
96793
|
-
<false/>
|
|
96794
|
-
</dict>
|
|
96795
|
-
<key>ThrottleInterval</key>
|
|
96796
|
-
<integer>5</integer>
|
|
96797
|
-
<key>StandardOutPath</key>
|
|
96798
|
-
<string>${xml((0, import_node_path29.join)(logDir, "daemon.log"))}</string>
|
|
96799
|
-
<key>StandardErrorPath</key>
|
|
96800
|
-
<string>${xml((0, import_node_path29.join)(logDir, "daemon-error.log"))}</string>
|
|
96801
|
-
</dict>
|
|
96802
|
-
</plist>
|
|
96803
|
-
`;
|
|
96804
|
-
return {
|
|
96805
|
-
platform: "darwin",
|
|
96806
|
-
manifestPath,
|
|
96807
|
-
manifest,
|
|
96808
|
-
logDirectory: logDir,
|
|
96809
|
-
loadDefinitionCommands: [
|
|
96810
|
-
{
|
|
96811
|
-
command: "launchctl",
|
|
96812
|
-
args: ["bootstrap", domain2, manifestPath],
|
|
96813
|
-
tolerateFailure: true
|
|
96814
|
-
}
|
|
96815
|
-
],
|
|
96816
|
-
reloadDefinitionCommands: [
|
|
96817
|
-
{
|
|
96818
|
-
command: "launchctl",
|
|
96819
|
-
args: ["bootout", domain2, manifestPath],
|
|
96820
|
-
tolerateFailure: true
|
|
96821
|
-
},
|
|
96822
|
-
{
|
|
96823
|
-
command: "launchctl",
|
|
96824
|
-
args: ["bootstrap", domain2, manifestPath],
|
|
96825
|
-
tolerateFailure: false
|
|
96826
|
-
}
|
|
96827
|
-
],
|
|
96828
|
-
enableCommands: [
|
|
96829
|
-
{
|
|
96830
|
-
command: "launchctl",
|
|
96831
|
-
args: ["enable", serviceTarget],
|
|
96832
|
-
tolerateFailure: true
|
|
96833
|
-
}
|
|
96834
|
-
],
|
|
96835
|
-
startCommands: [
|
|
96836
|
-
{
|
|
96837
|
-
command: "launchctl",
|
|
96838
|
-
args: ["kickstart", serviceTarget],
|
|
96839
|
-
tolerateFailure: false
|
|
96840
|
-
}
|
|
96841
|
-
],
|
|
96842
|
-
stopCommands: [
|
|
96843
|
-
{
|
|
96844
|
-
command: "launchctl",
|
|
96845
|
-
args: ["kill", "SIGTERM", serviceTarget],
|
|
96846
|
-
tolerateFailure: true
|
|
96847
|
-
}
|
|
96848
|
-
],
|
|
96849
|
-
replaceCommands: [
|
|
96850
|
-
{
|
|
96851
|
-
command: "launchctl",
|
|
96852
|
-
args: ["bootout", domain2, manifestPath],
|
|
96853
|
-
tolerateFailure: true
|
|
96854
|
-
},
|
|
96855
|
-
{
|
|
96856
|
-
command: "launchctl",
|
|
96857
|
-
args: ["bootstrap", domain2, manifestPath],
|
|
96858
|
-
tolerateFailure: false
|
|
96859
|
-
},
|
|
96860
|
-
{
|
|
96861
|
-
command: "launchctl",
|
|
96862
|
-
args: ["kickstart", "-k", serviceTarget],
|
|
96863
|
-
tolerateFailure: false
|
|
96864
|
-
}
|
|
96865
|
-
],
|
|
96866
|
-
uninstallCommands: [
|
|
96867
|
-
{
|
|
96868
|
-
command: "launchctl",
|
|
96869
|
-
args: ["bootout", domain2, manifestPath],
|
|
96870
|
-
tolerateFailure: true
|
|
96871
|
-
}
|
|
96872
|
-
],
|
|
96873
|
-
statusCommand: {
|
|
96874
|
-
command: "launchctl",
|
|
96875
|
-
args: ["print", serviceTarget],
|
|
96876
|
-
tolerateFailure: true
|
|
96877
|
-
},
|
|
96878
|
-
isActiveCommand: {
|
|
96879
|
-
command: "launchctl",
|
|
96880
|
-
args: ["print", serviceTarget],
|
|
96881
|
-
tolerateFailure: true
|
|
96882
|
-
},
|
|
96883
|
-
lingerStatusCommand: null
|
|
96884
|
-
};
|
|
96885
|
-
}
|
|
96886
|
-
if (input2.platform === "linux") {
|
|
96887
|
-
const manifestPath = (0, import_node_path29.join)(input2.homeDir, ".config", "systemd", "user", names.systemd);
|
|
96888
|
-
const environmentLines = Object.entries(input2.environment ?? {}).map(([key, value2]) => `Environment=${systemdArg(`${key}=${value2}`)}`).join("\n");
|
|
96889
|
-
const manifest = `[Unit]
|
|
96890
|
-
Description=Alan local agent daemon
|
|
96891
|
-
After=network-online.target
|
|
96892
|
-
Wants=network-online.target
|
|
96893
|
-
StartLimitIntervalSec=300
|
|
96894
|
-
StartLimitBurst=3
|
|
96895
|
-
|
|
96896
|
-
[Service]
|
|
96897
|
-
Type=simple
|
|
96898
|
-
${environmentLines ? `${environmentLines}
|
|
96899
|
-
` : ""}ExecStart=${daemonArgs.map(systemdArg).join(" ")}
|
|
96900
|
-
Restart=on-failure
|
|
96901
|
-
RestartSec=5
|
|
96902
|
-
|
|
96903
|
-
[Install]
|
|
96904
|
-
WantedBy=default.target
|
|
96905
|
-
`;
|
|
96906
|
-
return {
|
|
96907
|
-
platform: "linux",
|
|
96908
|
-
manifestPath,
|
|
96909
|
-
manifest,
|
|
96910
|
-
logDirectory: null,
|
|
96911
|
-
loadDefinitionCommands: [
|
|
96912
|
-
{
|
|
96913
|
-
command: "systemctl",
|
|
96914
|
-
args: ["--user", "daemon-reload"],
|
|
96915
|
-
tolerateFailure: false
|
|
96916
|
-
}
|
|
96917
|
-
],
|
|
96918
|
-
reloadDefinitionCommands: [
|
|
96919
|
-
{
|
|
96920
|
-
command: "systemctl",
|
|
96921
|
-
args: ["--user", "daemon-reload"],
|
|
96922
|
-
tolerateFailure: false
|
|
96923
|
-
}
|
|
96924
|
-
],
|
|
96925
|
-
enableCommands: [
|
|
96926
|
-
{
|
|
96927
|
-
command: "systemctl",
|
|
96928
|
-
args: ["--user", "enable", names.systemd],
|
|
96929
|
-
tolerateFailure: false
|
|
96930
|
-
}
|
|
96931
|
-
],
|
|
96932
|
-
startCommands: [
|
|
96933
|
-
{
|
|
96934
|
-
command: "systemctl",
|
|
96935
|
-
args: ["--user", "start", names.systemd],
|
|
96936
|
-
tolerateFailure: false
|
|
96937
|
-
}
|
|
96938
|
-
],
|
|
96939
|
-
stopCommands: [
|
|
96940
|
-
{
|
|
96941
|
-
command: "systemctl",
|
|
96942
|
-
args: ["--user", "stop", names.systemd],
|
|
96943
|
-
tolerateFailure: true
|
|
96944
|
-
}
|
|
96945
|
-
],
|
|
96946
|
-
replaceCommands: [
|
|
96947
|
-
{
|
|
96948
|
-
command: "systemctl",
|
|
96949
|
-
args: ["--user", "daemon-reload"],
|
|
96950
|
-
tolerateFailure: false
|
|
96951
|
-
},
|
|
96952
|
-
{
|
|
96953
|
-
command: "systemctl",
|
|
96954
|
-
args: ["--user", "restart", names.systemd],
|
|
96955
|
-
tolerateFailure: false
|
|
96956
|
-
}
|
|
96957
|
-
],
|
|
96958
|
-
uninstallCommands: [
|
|
96959
|
-
{
|
|
96960
|
-
command: "systemctl",
|
|
96961
|
-
args: ["--user", "disable", "--now", names.systemd],
|
|
96962
|
-
tolerateFailure: true
|
|
96963
|
-
},
|
|
96964
|
-
{
|
|
96965
|
-
command: "systemctl",
|
|
96966
|
-
args: ["--user", "daemon-reload"],
|
|
96967
|
-
tolerateFailure: false
|
|
96968
|
-
}
|
|
96969
|
-
],
|
|
96970
|
-
statusCommand: {
|
|
96971
|
-
command: "systemctl",
|
|
96972
|
-
args: ["--user", "status", names.systemd, "--no-pager"],
|
|
96973
|
-
tolerateFailure: true
|
|
96974
|
-
},
|
|
96975
|
-
isActiveCommand: {
|
|
96976
|
-
command: "systemctl",
|
|
96977
|
-
args: ["--user", "is-active", names.systemd],
|
|
96978
|
-
tolerateFailure: true
|
|
96979
|
-
},
|
|
96980
|
-
lingerStatusCommand: {
|
|
96981
|
-
command: "loginctl",
|
|
96982
|
-
args: ["show-user", "$(id -un)", "-p", "Linger"],
|
|
96983
|
-
tolerateFailure: true
|
|
96984
|
-
}
|
|
96985
|
-
};
|
|
96986
|
-
}
|
|
96987
|
-
const environmentPrefix = Object.entries(input2.environment ?? {}).map(([key, value2]) => `$env:${key} = ${powershellLiteral(value2)}`).join("; ");
|
|
96988
|
-
const directArgument = [input2.cliEntry, "daemon", "--profile", input2.profile].map((part) => part.includes(" ") ? `"${part}"` : part).join(" ");
|
|
96989
|
-
const executable = powershellLiteral(environmentPrefix ? "powershell.exe" : input2.nodeExecutable);
|
|
96990
|
-
const argument = powershellLiteral(
|
|
96991
|
-
environmentPrefix ? `-NoProfile -NonInteractive -WindowStyle Hidden -Command "${environmentPrefix}; & ${powershellLiteral(input2.nodeExecutable)} ${powershellLiteral(input2.cliEntry)} daemon --profile ${input2.profile}"` : directArgument
|
|
96992
|
-
);
|
|
96993
|
-
const registerScript = [
|
|
96994
|
-
"$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name",
|
|
96995
|
-
`$action = New-ScheduledTaskAction -Execute ${executable} -Argument ${argument}`,
|
|
96996
|
-
"$trigger = New-ScheduledTaskTrigger -AtLogOn -User $currentUser",
|
|
96997
|
-
"$principal = New-ScheduledTaskPrincipal -UserId $currentUser -LogonType Interactive -RunLevel Limited",
|
|
96998
|
-
"$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero)",
|
|
96999
|
-
`Register-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null`
|
|
97000
|
-
].join("; ");
|
|
97001
|
-
return {
|
|
97002
|
-
platform: "win32",
|
|
97003
|
-
manifestPath: null,
|
|
97004
|
-
manifest: null,
|
|
97005
|
-
logDirectory: null,
|
|
97006
|
-
loadDefinitionCommands: [
|
|
97007
|
-
{
|
|
97008
|
-
command: "powershell.exe",
|
|
97009
|
-
args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
|
|
97010
|
-
tolerateFailure: false
|
|
97011
|
-
}
|
|
97012
|
-
],
|
|
97013
|
-
reloadDefinitionCommands: [
|
|
97014
|
-
{
|
|
97015
|
-
command: "powershell.exe",
|
|
97016
|
-
args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
|
|
97017
|
-
tolerateFailure: false
|
|
97018
|
-
}
|
|
97019
|
-
],
|
|
97020
|
-
enableCommands: [],
|
|
97021
|
-
startCommands: [
|
|
97022
|
-
{
|
|
97023
|
-
command: "powershell.exe",
|
|
97024
|
-
args: [
|
|
97025
|
-
"-NoProfile",
|
|
97026
|
-
"-NonInteractive",
|
|
97027
|
-
"-Command",
|
|
97028
|
-
`Start-ScheduledTask -TaskName ${powershellLiteral(names.windows)}`
|
|
97029
|
-
],
|
|
97030
|
-
tolerateFailure: false
|
|
97031
|
-
}
|
|
97032
|
-
],
|
|
97033
|
-
stopCommands: [
|
|
97034
|
-
{
|
|
97035
|
-
command: "powershell.exe",
|
|
97036
|
-
args: [
|
|
97037
|
-
"-NoProfile",
|
|
97038
|
-
"-NonInteractive",
|
|
97039
|
-
"-Command",
|
|
97040
|
-
`Stop-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -ErrorAction SilentlyContinue`
|
|
97041
|
-
],
|
|
97042
|
-
tolerateFailure: true
|
|
97043
|
-
}
|
|
97044
|
-
],
|
|
97045
|
-
replaceCommands: [
|
|
97046
|
-
{
|
|
97047
|
-
command: "powershell.exe",
|
|
97048
|
-
args: [
|
|
97049
|
-
"-NoProfile",
|
|
97050
|
-
"-NonInteractive",
|
|
97051
|
-
"-Command",
|
|
97052
|
-
`${registerScript}; Start-ScheduledTask -TaskName ${powershellLiteral(names.windows)}`
|
|
97053
|
-
],
|
|
97054
|
-
tolerateFailure: false
|
|
97055
|
-
}
|
|
97056
|
-
],
|
|
97057
|
-
uninstallCommands: [
|
|
97058
|
-
{
|
|
97059
|
-
command: "powershell.exe",
|
|
97060
|
-
args: [
|
|
97061
|
-
"-NoProfile",
|
|
97062
|
-
"-NonInteractive",
|
|
97063
|
-
"-Command",
|
|
97064
|
-
`Unregister-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -Confirm:$false -ErrorAction SilentlyContinue`
|
|
97065
|
-
],
|
|
97066
|
-
tolerateFailure: true
|
|
97067
|
-
}
|
|
97068
|
-
],
|
|
97069
|
-
statusCommand: {
|
|
97070
|
-
command: "powershell.exe",
|
|
97071
|
-
args: [
|
|
97072
|
-
"-NoProfile",
|
|
97073
|
-
"-NonInteractive",
|
|
97074
|
-
"-Command",
|
|
97075
|
-
`Get-ScheduledTask -TaskName ${powershellLiteral(names.windows)} | Format-List TaskName,State`
|
|
97076
|
-
],
|
|
97077
|
-
tolerateFailure: true
|
|
97078
|
-
},
|
|
97079
|
-
isActiveCommand: {
|
|
97080
|
-
command: "powershell.exe",
|
|
97081
|
-
args: [
|
|
97082
|
-
"-NoProfile",
|
|
97083
|
-
"-NonInteractive",
|
|
97084
|
-
"-Command",
|
|
97085
|
-
`(Get-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -ErrorAction SilentlyContinue).State`
|
|
97086
|
-
],
|
|
97087
|
-
tolerateFailure: true
|
|
97088
|
-
},
|
|
97089
|
-
lingerStatusCommand: null
|
|
97090
|
-
};
|
|
97091
|
-
}
|
|
97092
|
-
function resolveCurrentPlatform() {
|
|
97093
|
-
const currentPlatform = (0, import_node_os18.platform)();
|
|
97094
|
-
if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
|
|
97095
|
-
throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
|
|
97096
|
-
}
|
|
97097
|
-
return currentPlatform;
|
|
97098
|
-
}
|
|
97099
|
-
function currentServicePlan(args, runtime) {
|
|
97100
|
-
const currentPlatform = resolveCurrentPlatform();
|
|
97101
|
-
const profile = resolveEndpointProfileFromArgs(args);
|
|
97102
|
-
const cliEntry = runtime?.cliEntry ?? process.argv[1];
|
|
97103
|
-
if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
|
|
97104
|
-
return buildDaemonServicePlan({
|
|
97105
|
-
platform: currentPlatform,
|
|
97106
|
-
homeDir: (0, import_node_os18.homedir)(),
|
|
97107
|
-
nodeExecutable: runtime?.executable ?? process.execPath,
|
|
97108
|
-
cliEntry: (0, import_node_path29.resolve)(cliEntry),
|
|
97109
|
-
profile,
|
|
97110
|
-
environment: runtime?.environment
|
|
97111
|
-
});
|
|
97112
|
-
}
|
|
97113
|
-
function writeManifestAtomic(path2, contents) {
|
|
97114
|
-
(0, import_node_fs28.mkdirSync)((0, import_node_path29.dirname)(path2), { recursive: true, mode: 448 });
|
|
97115
|
-
const pendingPath = `${path2}.pending-${process.pid}`;
|
|
97116
|
-
try {
|
|
97117
|
-
(0, import_node_fs28.writeFileSync)(pendingPath, contents, { mode: 384 });
|
|
97118
|
-
(0, import_node_fs28.chmodSync)(pendingPath, 384);
|
|
97119
|
-
(0, import_node_fs28.renameSync)(pendingPath, path2);
|
|
97120
|
-
} finally {
|
|
97121
|
-
(0, import_node_fs28.rmSync)(pendingPath, { force: true });
|
|
97122
|
-
}
|
|
97123
|
-
}
|
|
97124
|
-
function defaultReadManifest(path2) {
|
|
97125
|
-
if (!(0, import_node_fs28.existsSync)(path2)) return null;
|
|
97126
|
-
return (0, import_node_fs28.readFileSync)(path2, "utf8");
|
|
97127
|
-
}
|
|
97128
|
-
function runServiceCommand(command) {
|
|
97129
|
-
const result = (0, import_node_child_process9.spawnSync)(command.command, command.args, { encoding: "utf8", shell: false });
|
|
97130
|
-
const status = result.status ?? 1;
|
|
97131
|
-
const output2 = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
97132
|
-
if (status !== 0 && !command.tolerateFailure) {
|
|
97133
|
-
throw new Error(
|
|
97134
|
-
`Service command failed (${command.command} ${command.args.join(" ")}): ${output2 || `exit ${status}`}`
|
|
97135
|
-
);
|
|
97136
|
-
}
|
|
97137
|
-
return { status, output: output2 };
|
|
97138
|
-
}
|
|
97139
|
-
function defaultSleep(ms) {
|
|
97140
|
-
return new Promise((resolveSleep) => {
|
|
97141
|
-
setTimeout(resolveSleep, ms);
|
|
97142
|
-
});
|
|
97143
|
-
}
|
|
97144
|
-
function parseServiceHostState(servicePlatform, result) {
|
|
97145
|
-
const output2 = result.output;
|
|
97146
|
-
if (servicePlatform === "linux") {
|
|
97147
|
-
const trimmed = output2.trim().toLowerCase();
|
|
97148
|
-
if (trimmed === "inactive" || trimmed === "failed" || trimmed === "dead" || /\binactive\b/i.test(output2) || /\bfailed\b/i.test(output2)) {
|
|
97149
|
-
return "stopped";
|
|
97150
|
-
}
|
|
97151
|
-
}
|
|
97152
|
-
if (result.status !== 0) return "unknown";
|
|
97153
|
-
if (servicePlatform === "darwin") {
|
|
97154
|
-
if (/\bstate\s*=\s*running\b/i.test(output2)) return "running";
|
|
97155
|
-
if (/\bstate\s*=\s*(not running|waiting|stopped)\b/i.test(output2)) return "stopped";
|
|
97156
|
-
if (/\bpid\s*=\s*[1-9]\d*\b/i.test(output2)) return "running";
|
|
97157
|
-
if (/could not find service/i.test(output2)) return "stopped";
|
|
97158
|
-
return "unknown";
|
|
97159
|
-
}
|
|
97160
|
-
if (servicePlatform === "linux") {
|
|
97161
|
-
const trimmed = output2.trim().toLowerCase();
|
|
97162
|
-
if (trimmed === "active" || /\bactive\s*\(running\)/i.test(output2)) return "running";
|
|
97163
|
-
if (trimmed === "activating" || trimmed === "reloading") return "starting";
|
|
97164
|
-
return "unknown";
|
|
97165
|
-
}
|
|
97166
|
-
const stateMatch = output2.match(/\b(?:State|state)\s*[:=]\s*(\w+)/);
|
|
97167
|
-
const state = (stateMatch?.[1] ?? output2.trim()).toLowerCase();
|
|
97168
|
-
if (state === "running") return "running";
|
|
97169
|
-
if (state === "ready" || state === "disabled" || state === "queued") return "stopped";
|
|
97170
|
-
return "unknown";
|
|
97171
|
-
}
|
|
97172
|
-
function resolveEnsureDefinitionOutcome(input2) {
|
|
97173
|
-
if (!input2.definitionChanged) {
|
|
97174
|
-
return { changed: false, updatePending: false };
|
|
97175
|
-
}
|
|
97176
|
-
if (input2.hostState === "running" || input2.hostState === "starting") {
|
|
97177
|
-
return { changed: true, updatePending: true };
|
|
97178
|
-
}
|
|
97179
|
-
return { changed: true, updatePending: false };
|
|
97180
|
-
}
|
|
97181
|
-
function shouldStartOnInstall(hostState) {
|
|
97182
|
-
return hostState === "stopped";
|
|
97183
|
-
}
|
|
97184
|
-
function resolveUsername(options) {
|
|
97185
|
-
if (options?.username) return options.username;
|
|
97186
|
-
try {
|
|
97187
|
-
return (0, import_node_os18.userInfo)().username;
|
|
97188
|
-
} catch {
|
|
97189
|
-
return process.env.USER || process.env.USERNAME || "unknown";
|
|
97190
|
-
}
|
|
97191
|
-
}
|
|
97192
|
-
function buildLingerStatusCommand(username) {
|
|
97193
|
-
return {
|
|
97194
|
-
command: "loginctl",
|
|
97195
|
-
args: ["show-user", username, "-p", "Linger"],
|
|
97196
|
-
tolerateFailure: true
|
|
97197
|
-
};
|
|
97198
|
-
}
|
|
97199
|
-
function assertSystemdUserLingerEnabled(options = {}) {
|
|
97200
|
-
const username = resolveUsername(options);
|
|
97201
|
-
const run = options.runCommand ?? runServiceCommand;
|
|
97202
|
-
const result = run(buildLingerStatusCommand(username));
|
|
97203
|
-
if (result.status !== 0) {
|
|
97204
|
-
throw new Error(
|
|
97205
|
-
`Cannot verify systemd user linger for ${username} (loginctl failed). For durable headless VM boot run: sudo loginctl enable-linger ${username}`
|
|
97206
|
-
);
|
|
97207
|
-
}
|
|
97208
|
-
if (!/Linger=yes/i.test(result.output)) {
|
|
97209
|
-
throw new Error(
|
|
97210
|
-
`systemd user linger is disabled for ${username}. For durable headless VM boot run: sudo loginctl enable-linger ${username}`
|
|
97211
|
-
);
|
|
97212
|
-
}
|
|
97213
|
-
}
|
|
97214
|
-
function createHostContext(options = {}) {
|
|
97215
|
-
const args = options.args ?? [];
|
|
97216
|
-
const plan = currentServicePlan(args, options.runtime);
|
|
97217
|
-
const run = options.runCommand ?? runServiceCommand;
|
|
97218
|
-
const sleep4 = options.sleep ?? defaultSleep;
|
|
97219
|
-
const nowMs = options.nowMs ?? Date.now;
|
|
97220
|
-
const readManifest = options.readManifest ?? defaultReadManifest;
|
|
97221
|
-
const writeManifest = options.writeManifest ?? writeManifestAtomic;
|
|
97222
|
-
const removeManifest = options.removeManifest ?? ((path2) => (0, import_node_fs28.rmSync)(path2, { force: true }));
|
|
97223
|
-
const ensureLogDir = options.ensureLogDir ?? (() => {
|
|
97224
|
-
if (plan.logDirectory) (0, import_node_fs28.mkdirSync)(plan.logDirectory, { recursive: true, mode: 448 });
|
|
97225
|
-
});
|
|
97226
|
-
return {
|
|
97227
|
-
args,
|
|
97228
|
-
plan,
|
|
97229
|
-
run,
|
|
97230
|
-
sleep: sleep4,
|
|
97231
|
-
nowMs,
|
|
97232
|
-
readManifest,
|
|
97233
|
-
writeManifest,
|
|
97234
|
-
removeManifest,
|
|
97235
|
-
ensureLogDir,
|
|
97236
|
-
profile: resolveEndpointProfileFromArgs(args)
|
|
97237
|
-
};
|
|
97238
|
-
}
|
|
97239
|
-
function inspectDaemonService(options = {}) {
|
|
97240
|
-
const { plan, run, nowMs } = createHostContext(options);
|
|
97241
|
-
const result = run(plan.isActiveCommand);
|
|
97242
|
-
const state = parseServiceHostState(plan.platform, result);
|
|
97243
|
-
return {
|
|
97244
|
-
state,
|
|
97245
|
-
platform: plan.platform,
|
|
97246
|
-
detail: result.output || void 0,
|
|
97247
|
-
observedAtMs: nowMs()
|
|
97248
|
-
};
|
|
97249
|
-
}
|
|
97250
|
-
function ensureDaemonServiceDefinition(options = {}) {
|
|
97251
|
-
const ctx = createHostContext(options);
|
|
97252
|
-
const { plan, run, readManifest, writeManifest, ensureLogDir } = ctx;
|
|
97253
|
-
let definitionChanged = false;
|
|
97254
|
-
if (plan.manifestPath && plan.manifest) {
|
|
97255
|
-
ensureLogDir();
|
|
97256
|
-
const existing = readManifest(plan.manifestPath);
|
|
97257
|
-
definitionChanged = existing !== plan.manifest;
|
|
97258
|
-
if (definitionChanged) {
|
|
97259
|
-
writeManifest(plan.manifestPath, plan.manifest);
|
|
97260
|
-
}
|
|
97261
|
-
} else if (plan.platform === "win32") {
|
|
97262
|
-
definitionChanged = true;
|
|
97263
|
-
}
|
|
97264
|
-
const inspection = inspectDaemonService(options);
|
|
97265
|
-
const outcome = resolveEnsureDefinitionOutcome({
|
|
97266
|
-
definitionChanged,
|
|
97267
|
-
hostState: inspection.state
|
|
97268
|
-
});
|
|
97269
|
-
if (outcome.updatePending) {
|
|
97270
|
-
return outcome;
|
|
97271
|
-
}
|
|
97272
|
-
if (inspection.state === "running" || inspection.state === "starting") {
|
|
97273
|
-
return outcome;
|
|
97274
|
-
}
|
|
97275
|
-
const definitionCommands = inspection.state === "stopped" ? plan.reloadDefinitionCommands : plan.loadDefinitionCommands;
|
|
97276
|
-
for (const command of definitionCommands) run(command);
|
|
97277
|
-
return outcome;
|
|
97278
|
-
}
|
|
97279
|
-
function enableDaemonService(options = {}) {
|
|
97280
|
-
const { plan, run } = createHostContext(options);
|
|
97281
|
-
for (const command of plan.enableCommands) run(command);
|
|
97282
|
-
}
|
|
97283
|
-
function startDaemonService(options = {}) {
|
|
97284
|
-
const { plan, run } = createHostContext(options);
|
|
97285
|
-
for (const command of plan.startCommands) run(command);
|
|
97286
|
-
}
|
|
97287
|
-
function uninstallDaemonService(args = [], options = {}) {
|
|
97288
|
-
const ctx = createHostContext({ ...options, args: options.args ?? args });
|
|
97289
|
-
for (const command of ctx.plan.uninstallCommands) ctx.run(command);
|
|
97290
|
-
if (ctx.plan.manifestPath) ctx.removeManifest(ctx.plan.manifestPath);
|
|
97291
|
-
console.info("[alan-agent] Per-user daemon service removed");
|
|
97292
|
-
}
|
|
97293
|
-
function installDaemonService(args = [], runtime, options = {}) {
|
|
97294
|
-
const profile = resolveEndpointProfileFromArgs(args);
|
|
97295
|
-
const configPath = resolveAgentConfigPath({ profile });
|
|
97296
|
-
if (!configExistsAtPath(configPath)) {
|
|
97297
|
-
throw new Error(`No ${profile} runtime is configured. Run alan-agent setup or login first.`);
|
|
97298
|
-
}
|
|
97299
|
-
const headless = options.headless ?? args.includes("--headless");
|
|
97300
|
-
const merged = { ...options, args, runtime, headless };
|
|
97301
|
-
const ctx = createHostContext(merged);
|
|
97302
|
-
if (headless) {
|
|
97303
|
-
if (ctx.plan.platform !== "linux") {
|
|
97304
|
-
throw new Error("--headless is only supported on Linux systemd user services");
|
|
97305
|
-
}
|
|
97306
|
-
assertSystemdUserLingerEnabled(merged);
|
|
97307
|
-
}
|
|
97308
|
-
const ensured = ensureDaemonServiceDefinition(merged);
|
|
97309
|
-
enableDaemonService(merged);
|
|
97310
|
-
const inspection = inspectDaemonService(merged);
|
|
97311
|
-
if (ensured.updatePending) {
|
|
97312
|
-
console.info("[alan-agent] Daemon service definition update pending; leaving running service", {
|
|
97313
|
-
profile,
|
|
97314
|
-
state: inspection.state
|
|
97315
|
-
});
|
|
97316
|
-
return;
|
|
97317
|
-
}
|
|
97318
|
-
if (!shouldStartOnInstall(inspection.state)) {
|
|
97319
|
-
console.info("[alan-agent] Per-user daemon service already present", {
|
|
97320
|
-
profile,
|
|
97321
|
-
state: inspection.state
|
|
97322
|
-
});
|
|
97323
|
-
return;
|
|
97324
|
-
}
|
|
97325
|
-
startDaemonService(merged);
|
|
97326
|
-
console.info("[alan-agent] Per-user daemon service installed", { profile });
|
|
97327
|
-
}
|
|
97328
|
-
function printDaemonServiceStatus(args = []) {
|
|
97329
|
-
const plan = currentServicePlan(args);
|
|
97330
|
-
const result = runServiceCommand({ ...plan.statusCommand, tolerateFailure: true });
|
|
97331
|
-
if (result.status !== 0) {
|
|
97332
|
-
process.stdout.write(`unknown
|
|
97333
|
-
${result.output}
|
|
97334
|
-
`);
|
|
97335
|
-
return;
|
|
97336
|
-
}
|
|
97337
|
-
process.stdout.write(`${result.output}
|
|
97338
|
-
`);
|
|
97339
|
-
}
|
|
97340
|
-
|
|
97341
97593
|
// src/skills/skill-cli.ts
|
|
97342
97594
|
var import_promises6 = require("fs/promises");
|
|
97343
97595
|
var import_node_os19 = require("os");
|
|
@@ -97536,13 +97788,7 @@ async function main() {
|
|
|
97536
97788
|
return;
|
|
97537
97789
|
}
|
|
97538
97790
|
if (command === "install") {
|
|
97539
|
-
|
|
97540
|
-
const configured = readConfig();
|
|
97541
|
-
const configurationMode = resolveInstallConfigurationMode(commandArgs, configured);
|
|
97542
|
-
const setup = configurationMode === "setup" ? await setupDaemon(commandArgs) : null;
|
|
97543
|
-
if (configurationMode === "login") await loginWithDeviceCode(commandArgs);
|
|
97544
|
-
if (!setup?.daemonAlreadyRunning) installDaemonService(commandArgs);
|
|
97545
|
-
runMcpIntegrationCommand(["reconcile", ...commandArgs]);
|
|
97791
|
+
await runInstallCommand(commandArgs);
|
|
97546
97792
|
return;
|
|
97547
97793
|
}
|
|
97548
97794
|
if (command === "login") {
|