@alan-ai-hq/agent-manager 0.1.88 → 0.1.89
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 +328 -173
- package/package.json +2 -3
package/dist/index.cjs
CHANGED
|
@@ -15180,7 +15180,7 @@ function resolveCommand(args, env) {
|
|
|
15180
15180
|
|
|
15181
15181
|
// src/daemon.ts
|
|
15182
15182
|
var import_node_crypto19 = require("crypto");
|
|
15183
|
-
var
|
|
15183
|
+
var import_node_os13 = require("os");
|
|
15184
15184
|
|
|
15185
15185
|
// src/sleep-inhibitor.ts
|
|
15186
15186
|
var import_node_child_process2 = require("child_process");
|
|
@@ -15447,7 +15447,7 @@ function describeError(error61) {
|
|
|
15447
15447
|
}
|
|
15448
15448
|
|
|
15449
15449
|
// src/version.ts
|
|
15450
|
-
var AGENT_VERSION = "0.1.
|
|
15450
|
+
var AGENT_VERSION = "0.1.89";
|
|
15451
15451
|
|
|
15452
15452
|
// src/daemon-worktree.ts
|
|
15453
15453
|
var import_node_child_process3 = require("child_process");
|
|
@@ -19549,9 +19549,9 @@ var asciiTabOrNewline = /[\t\n\r]/g;
|
|
|
19549
19549
|
function stripTabAndNewline(value2) {
|
|
19550
19550
|
return value2.replace(asciiTabOrNewline, "");
|
|
19551
19551
|
}
|
|
19552
|
-
function urlHostnameOk(url3,
|
|
19553
|
-
|
|
19554
|
-
return
|
|
19552
|
+
function urlHostnameOk(url3, hostname5) {
|
|
19553
|
+
hostname5.lastIndex = 0;
|
|
19554
|
+
return hostname5.test(url3.hostname);
|
|
19555
19555
|
}
|
|
19556
19556
|
function urlProtocolOk(url3, protocol4) {
|
|
19557
19557
|
protocol4.lastIndex = 0;
|
|
@@ -50894,7 +50894,7 @@ function scheduleRuntimeModelScan(getBaseMetadata, options) {
|
|
|
50894
50894
|
var import_node_crypto18 = require("crypto");
|
|
50895
50895
|
var import_node_fs22 = require("fs");
|
|
50896
50896
|
var import_node_http = __toESM(require("http"), 1);
|
|
50897
|
-
var
|
|
50897
|
+
var import_node_os12 = require("os");
|
|
50898
50898
|
var import_node_path24 = require("path");
|
|
50899
50899
|
|
|
50900
50900
|
// ../../node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.node.js
|
|
@@ -51480,8 +51480,8 @@ var Transport = class extends Emitter {
|
|
|
51480
51480
|
return schema + "://" + this._hostname() + this._port() + this.opts.path + this._query(query);
|
|
51481
51481
|
}
|
|
51482
51482
|
_hostname() {
|
|
51483
|
-
const
|
|
51484
|
-
return
|
|
51483
|
+
const hostname5 = this.opts.hostname;
|
|
51484
|
+
return hostname5.indexOf(":") === -1 ? hostname5 : "[" + hostname5 + "]";
|
|
51485
51485
|
}
|
|
51486
51486
|
_port() {
|
|
51487
51487
|
if (this.opts.port && (this.opts.secure && Number(this.opts.port) !== 443 || !this.opts.secure && Number(this.opts.port) !== 80)) {
|
|
@@ -70429,8 +70429,8 @@ function applyPostAuth(clientId, clientSecret, params) {
|
|
|
70429
70429
|
function applyPublicAuth(clientId, params) {
|
|
70430
70430
|
params.set("client_id", clientId);
|
|
70431
70431
|
}
|
|
70432
|
-
function isLoopbackHost(
|
|
70433
|
-
return
|
|
70432
|
+
function isLoopbackHost(hostname5) {
|
|
70433
|
+
return hostname5 === "localhost" || hostname5 === "127.0.0.1" || hostname5 === "[::1]" || hostname5 === "::1";
|
|
70434
70434
|
}
|
|
70435
70435
|
function assertSecureTokenEndpoint(tokenEndpoint) {
|
|
70436
70436
|
const url3 = new URL(String(tokenEndpoint));
|
|
@@ -75335,7 +75335,8 @@ function createLocalDaemonHttpHandler(deps) {
|
|
|
75335
75335
|
queueFullShutdown,
|
|
75336
75336
|
wsUrl,
|
|
75337
75337
|
inspectLocalSkill,
|
|
75338
|
-
readLocalSkillFile
|
|
75338
|
+
readLocalSkillFile,
|
|
75339
|
+
adoptRuntimeSetupGrant
|
|
75339
75340
|
} = deps;
|
|
75340
75341
|
const localApiPort = getLocalApiPort2();
|
|
75341
75342
|
const heartbeatSeq = getHeartbeatSeq();
|
|
@@ -75393,6 +75394,15 @@ function createLocalDaemonHttpHandler(deps) {
|
|
|
75393
75394
|
res.writeHead(401, { "content-type": "application/json" }).end(JSON.stringify({ error: "Unauthorized" }));
|
|
75394
75395
|
return;
|
|
75395
75396
|
}
|
|
75397
|
+
if (req.method === "POST" && req.url === "/credentials/setup") {
|
|
75398
|
+
void readJsonRequest(req).then((value2) => parseRuntimeSetupGrantInput(value2)).then(adoptRuntimeSetupGrant).then((result) => {
|
|
75399
|
+
res.writeHead(200, { "cache-control": "no-store", "content-type": "application/json" }).end(JSON.stringify(result));
|
|
75400
|
+
}).catch((error61) => {
|
|
75401
|
+
pushLog(`runtime-credential-setup-failed ${error61.message}`);
|
|
75402
|
+
res.writeHead(409, { "cache-control": "no-store", "content-type": "application/json" }).end(JSON.stringify({ error: error61.message }));
|
|
75403
|
+
});
|
|
75404
|
+
return;
|
|
75405
|
+
}
|
|
75396
75406
|
if (req.method === "GET" && req.url?.startsWith("/skills/preview/file?")) {
|
|
75397
75407
|
const url3 = new URL(req.url, "http://127.0.0.1");
|
|
75398
75408
|
const input2 = localSkillRequestInput(url3, true);
|
|
@@ -75574,6 +75584,31 @@ function createLocalDaemonHttpHandler(deps) {
|
|
|
75574
75584
|
res.writeHead(404, { "content-type": "application/json" }).end(JSON.stringify({ error: "Not found" }));
|
|
75575
75585
|
};
|
|
75576
75586
|
}
|
|
75587
|
+
async function readJsonRequest(req) {
|
|
75588
|
+
const chunks = [];
|
|
75589
|
+
let size = 0;
|
|
75590
|
+
for await (const chunk of req) {
|
|
75591
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
75592
|
+
size += buffer.length;
|
|
75593
|
+
if (size > 16384) throw new Error("credential setup request is too large");
|
|
75594
|
+
chunks.push(buffer);
|
|
75595
|
+
}
|
|
75596
|
+
try {
|
|
75597
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
75598
|
+
} catch {
|
|
75599
|
+
throw new Error("credential setup request must be valid JSON");
|
|
75600
|
+
}
|
|
75601
|
+
}
|
|
75602
|
+
function parseRuntimeSetupGrantInput(value2) {
|
|
75603
|
+
if (!value2 || typeof value2 !== "object") {
|
|
75604
|
+
throw new Error("credential setup request must be an object");
|
|
75605
|
+
}
|
|
75606
|
+
const input2 = value2;
|
|
75607
|
+
if (typeof input2.apiUrl !== "string" || typeof input2.wsUrl !== "string" || input2.endpointProfile !== "production" && input2.endpointProfile !== "local" && input2.endpointProfile !== "staging" && input2.endpointProfile !== "custom" || typeof input2.setupToken !== "string" || input2.setupToken.length === 0 || typeof input2.displayName !== "string" || input2.displayName.length === 0 || typeof input2.installationId !== "string" || input2.installationId.length === 0 || input2.teamId !== void 0 && typeof input2.teamId !== "string") {
|
|
75608
|
+
throw new Error("credential setup request is incomplete");
|
|
75609
|
+
}
|
|
75610
|
+
return input2;
|
|
75611
|
+
}
|
|
75577
75612
|
function localSkillRequestInput(url3, requirePath) {
|
|
75578
75613
|
const localKey = url3.searchParams.get("localKey") ?? "";
|
|
75579
75614
|
const expectedContentHash = url3.searchParams.get("expectedContentHash") ?? "";
|
|
@@ -76463,6 +76498,123 @@ var RuntimeRunJournal = class {
|
|
|
76463
76498
|
}
|
|
76464
76499
|
};
|
|
76465
76500
|
|
|
76501
|
+
// src/runtime-registration.ts
|
|
76502
|
+
var import_node_os11 = require("os");
|
|
76503
|
+
var RuntimeSetupGrantExpiredError = class extends Error {
|
|
76504
|
+
constructor() {
|
|
76505
|
+
super("Runtime setup grant expired");
|
|
76506
|
+
this.name = "RuntimeSetupGrantExpiredError";
|
|
76507
|
+
}
|
|
76508
|
+
};
|
|
76509
|
+
async function createRuntimeSetupGrant(input2) {
|
|
76510
|
+
const response = await fetch(`${input2.apiUrl}/public/runtimes/setup-tokens`, {
|
|
76511
|
+
method: "POST",
|
|
76512
|
+
headers: {
|
|
76513
|
+
authorization: `Bearer ${input2.accessToken}`,
|
|
76514
|
+
"content-type": "application/json"
|
|
76515
|
+
},
|
|
76516
|
+
body: JSON.stringify({
|
|
76517
|
+
scope: input2.scope,
|
|
76518
|
+
...input2.scope === "team" ? { teamId: input2.teamId } : {},
|
|
76519
|
+
ttlMinutes: 5
|
|
76520
|
+
}),
|
|
76521
|
+
signal: AbortSignal.timeout(1e4)
|
|
76522
|
+
});
|
|
76523
|
+
const body = await response.json();
|
|
76524
|
+
if (!response.ok || typeof body.setupToken !== "string") {
|
|
76525
|
+
const detail = typeof body.error === "string" ? `: ${body.error}` : "";
|
|
76526
|
+
throw new Error(`runtime setup grant creation failed with HTTP ${response.status}${detail}`);
|
|
76527
|
+
}
|
|
76528
|
+
return body.setupToken;
|
|
76529
|
+
}
|
|
76530
|
+
async function exchangeRuntimeSetupGrant(input2) {
|
|
76531
|
+
const registrationAttemptId = getOrCreateSetupAttemptId(input2.setupToken);
|
|
76532
|
+
const registrationInit = {
|
|
76533
|
+
method: "POST",
|
|
76534
|
+
headers: { "content-type": "application/json" },
|
|
76535
|
+
body: JSON.stringify({
|
|
76536
|
+
...input2.teamId ? { teamId: input2.teamId } : {},
|
|
76537
|
+
setupToken: input2.setupToken,
|
|
76538
|
+
registrationAttemptId,
|
|
76539
|
+
displayName: input2.displayName,
|
|
76540
|
+
hostname: (0, import_node_os11.hostname)(),
|
|
76541
|
+
runtimeKind: "machine",
|
|
76542
|
+
managementKind: "user_managed",
|
|
76543
|
+
hostKind: "daemon",
|
|
76544
|
+
lifecycle: "durable",
|
|
76545
|
+
capabilities: discoverCapabilities(),
|
|
76546
|
+
metadata: {
|
|
76547
|
+
...await collectRuntimeMetadataWithProviderLimits(),
|
|
76548
|
+
installationId: input2.installationId
|
|
76549
|
+
}
|
|
76550
|
+
})
|
|
76551
|
+
};
|
|
76552
|
+
let response;
|
|
76553
|
+
let transportError;
|
|
76554
|
+
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
76555
|
+
try {
|
|
76556
|
+
response = await fetch(
|
|
76557
|
+
`${input2.apiUrl}/public/runtimes/register-with-setup-token`,
|
|
76558
|
+
registrationInit
|
|
76559
|
+
);
|
|
76560
|
+
transportError = void 0;
|
|
76561
|
+
} catch (error61) {
|
|
76562
|
+
transportError = error61;
|
|
76563
|
+
}
|
|
76564
|
+
const retriable = response && (response.status === 408 || response.status === 429 || response.status >= 500);
|
|
76565
|
+
if (response && (!retriable || response.ok) || attempt === 3) break;
|
|
76566
|
+
await new Promise((resolve15) => setTimeout(resolve15, attempt * 100));
|
|
76567
|
+
}
|
|
76568
|
+
if (!response) {
|
|
76569
|
+
const detail = transportError instanceof Error ? transportError.message : String(transportError);
|
|
76570
|
+
throw new Error(`runtime registration failed: unable to reach Alan (${detail})`);
|
|
76571
|
+
}
|
|
76572
|
+
if (!response.ok) {
|
|
76573
|
+
const responseBody = await response.text();
|
|
76574
|
+
let errorCode2;
|
|
76575
|
+
try {
|
|
76576
|
+
const parsed = JSON.parse(responseBody);
|
|
76577
|
+
if (typeof parsed.error === "string") errorCode2 = parsed.error;
|
|
76578
|
+
} catch {
|
|
76579
|
+
}
|
|
76580
|
+
if (response.status === 401 && errorCode2 === "setup_token_expired") {
|
|
76581
|
+
clearPendingSetupIntent();
|
|
76582
|
+
throw new RuntimeSetupGrantExpiredError();
|
|
76583
|
+
}
|
|
76584
|
+
throw new Error(`runtime registration failed: ${response.status} ${responseBody}`);
|
|
76585
|
+
}
|
|
76586
|
+
const body = await response.json();
|
|
76587
|
+
if (typeof body.runtime?.id !== "string" || typeof body.runtime.credentialGeneration !== "number" || typeof body.runtimeToken !== "string" || !body.runtimeToken.startsWith("alan_runtime_") || typeof body.runtimeRenewalToken !== "string" || !body.runtimeRenewalToken.startsWith("alan_runtime_renew_")) {
|
|
76588
|
+
throw new Error("runtime registration returned an invalid credential bundle");
|
|
76589
|
+
}
|
|
76590
|
+
return {
|
|
76591
|
+
runtimeId: body.runtime.id,
|
|
76592
|
+
displayName: typeof body.runtime.displayName === "string" ? body.runtime.displayName : input2.displayName,
|
|
76593
|
+
credentialGeneration: body.runtime.credentialGeneration,
|
|
76594
|
+
runtimeToken: body.runtimeToken,
|
|
76595
|
+
runtimeRenewalToken: body.runtimeRenewalToken
|
|
76596
|
+
};
|
|
76597
|
+
}
|
|
76598
|
+
async function handoffRuntimeSetupGrant(input2) {
|
|
76599
|
+
const response = await fetch(`http://127.0.0.1:${input2.port}/credentials/setup`, {
|
|
76600
|
+
method: "POST",
|
|
76601
|
+
headers: {
|
|
76602
|
+
authorization: `Bearer ${input2.localApiToken}`,
|
|
76603
|
+
"content-type": "application/json"
|
|
76604
|
+
},
|
|
76605
|
+
body: JSON.stringify(input2.setup),
|
|
76606
|
+
signal: AbortSignal.timeout(input2.timeoutMs ?? 2e4)
|
|
76607
|
+
});
|
|
76608
|
+
const body = await response.json();
|
|
76609
|
+
if (!response.ok) {
|
|
76610
|
+
throw new Error(body.error ?? `daemon credential setup failed with HTTP ${response.status}`);
|
|
76611
|
+
}
|
|
76612
|
+
if (typeof body.runtimeId !== "string" || typeof body.credentialGeneration !== "number") {
|
|
76613
|
+
throw new Error("daemon credential setup returned an invalid activation receipt");
|
|
76614
|
+
}
|
|
76615
|
+
return { runtimeId: body.runtimeId, credentialGeneration: body.credentialGeneration };
|
|
76616
|
+
}
|
|
76617
|
+
|
|
76466
76618
|
// src/skills/local-skill-source.ts
|
|
76467
76619
|
var import_node_buffer2 = require("buffer");
|
|
76468
76620
|
var import_node_crypto14 = require("crypto");
|
|
@@ -78923,7 +79075,7 @@ async function startDaemon(args) {
|
|
|
78923
79075
|
getRuntimeToken: () => runtimeToken
|
|
78924
79076
|
});
|
|
78925
79077
|
const runtimeSkillManager = await RuntimeSkillManager.open({
|
|
78926
|
-
homeDirectory: (0,
|
|
79078
|
+
homeDirectory: (0, import_node_os12.homedir)(),
|
|
78927
79079
|
endpointProfile,
|
|
78928
79080
|
profileStorageIdentity: configPath,
|
|
78929
79081
|
controlClient: skillControl
|
|
@@ -78931,7 +79083,7 @@ async function startDaemon(args) {
|
|
|
78931
79083
|
const runtimeSkillCoordinator = new RuntimeSkillCoordinator(
|
|
78932
79084
|
runtimeSkillManager,
|
|
78933
79085
|
skillControl,
|
|
78934
|
-
(input2) => resolveSkillScanInput((0,
|
|
79086
|
+
(input2) => resolveSkillScanInput((0, import_node_os12.homedir)(), input2)
|
|
78935
79087
|
);
|
|
78936
79088
|
const runSkillSync = async (reason) => {
|
|
78937
79089
|
const operation = reason === "startup" ? runtimeSkillCoordinator.runStartup() : reason === "interval" ? runtimeSkillCoordinator.runIncremental() : reason === "refresh" ? runtimeSkillCoordinator.runAudit() : runtimeSkillCoordinator.run();
|
|
@@ -79250,27 +79402,7 @@ async function startDaemon(args) {
|
|
|
79250
79402
|
const renewRuntimeLease = () => {
|
|
79251
79403
|
if (runtimeRenewalInFlight) return runtimeRenewalInFlight;
|
|
79252
79404
|
const attempt = (async () => {
|
|
79253
|
-
const adoptRewrittenCredentials = () => {
|
|
79254
|
-
const current2 = readConfig();
|
|
79255
|
-
if (current2.runtimeId !== runtimeId) return false;
|
|
79256
|
-
const nextToken = current2.runtimeToken;
|
|
79257
|
-
const nextRenewal = current2.runtimeRenewalToken;
|
|
79258
|
-
if (typeof nextToken !== "string" || !nextToken.startsWith("alan_runtime_") || typeof nextRenewal !== "string" || !nextRenewal.startsWith("alan_runtime_renew_")) {
|
|
79259
|
-
return false;
|
|
79260
|
-
}
|
|
79261
|
-
if (nextToken === runtimeToken && nextRenewal === runtimeRenewalToken) {
|
|
79262
|
-
return false;
|
|
79263
|
-
}
|
|
79264
|
-
runtimeToken = nextToken;
|
|
79265
|
-
runtimeRenewalToken = nextRenewal;
|
|
79266
|
-
socket.auth = { token: nextToken };
|
|
79267
|
-
clearConnectErrors();
|
|
79268
|
-
pushLog("runtime-credentials-reloaded-from-config");
|
|
79269
|
-
socket.connect();
|
|
79270
|
-
return true;
|
|
79271
|
-
};
|
|
79272
79405
|
if (!stored.apiUrl || !runtimeRenewalToken) {
|
|
79273
|
-
if (adoptRewrittenCredentials()) return true;
|
|
79274
79406
|
return false;
|
|
79275
79407
|
}
|
|
79276
79408
|
let response = null;
|
|
@@ -79302,9 +79434,6 @@ async function startDaemon(args) {
|
|
|
79302
79434
|
return false;
|
|
79303
79435
|
}
|
|
79304
79436
|
if (!response.ok) {
|
|
79305
|
-
if (response.status === 401 && adoptRewrittenCredentials()) {
|
|
79306
|
-
return true;
|
|
79307
|
-
}
|
|
79308
79437
|
const code = response.status === 401 ? "runtime_renewal_rejected" : response.status === 403 ? "runtime_disabled" : response.status === 410 ? "runtime_deleted" : response.status >= 500 ? "backend_unreachable" : "runtime_renewal_failed";
|
|
79309
79438
|
rememberConnectErrorCode(code);
|
|
79310
79439
|
lastConnectError = `Runtime renewal failed: ${response.status} ${await response.text()}`;
|
|
@@ -79320,7 +79449,6 @@ async function startDaemon(args) {
|
|
|
79320
79449
|
}
|
|
79321
79450
|
const current = readConfig();
|
|
79322
79451
|
if (current.runtimeId !== runtimeId || current.runtimeRenewalToken !== runtimeRenewalToken) {
|
|
79323
|
-
if (adoptRewrittenCredentials()) return true;
|
|
79324
79452
|
rememberConnectErrorCode("runtime_renewal_superseded");
|
|
79325
79453
|
lastConnectError = "Runtime credentials changed while renewal was in progress";
|
|
79326
79454
|
pushLog("runtime-renewal-superseded");
|
|
@@ -79348,6 +79476,64 @@ async function startDaemon(args) {
|
|
|
79348
79476
|
});
|
|
79349
79477
|
return attempt;
|
|
79350
79478
|
};
|
|
79479
|
+
let runtimeSetupInFlight = null;
|
|
79480
|
+
const adoptRuntimeSetupGrant = (input2) => {
|
|
79481
|
+
if (runtimeSetupInFlight) return runtimeSetupInFlight;
|
|
79482
|
+
const attempt = (async () => {
|
|
79483
|
+
const current = readConfig();
|
|
79484
|
+
if (current.runtimeId !== runtimeId || current.installationId !== installationId || input2.installationId !== installationId) {
|
|
79485
|
+
throw new Error("credential setup does not belong to this daemon installation");
|
|
79486
|
+
}
|
|
79487
|
+
if (input2.apiUrl !== stored.apiUrl || input2.wsUrl !== wsUrl) {
|
|
79488
|
+
throw new Error("credential setup cannot change a running daemon's endpoints");
|
|
79489
|
+
}
|
|
79490
|
+
const bundle = await exchangeRuntimeSetupGrant(input2);
|
|
79491
|
+
if (bundle.runtimeId !== runtimeId) {
|
|
79492
|
+
throw new Error("credential setup resolved to a different runtime");
|
|
79493
|
+
}
|
|
79494
|
+
writeConfig({
|
|
79495
|
+
...current,
|
|
79496
|
+
runtimeToken: bundle.runtimeToken,
|
|
79497
|
+
runtimeRenewalToken: bundle.runtimeRenewalToken,
|
|
79498
|
+
displayName: bundle.displayName
|
|
79499
|
+
});
|
|
79500
|
+
clearPendingSetupIntent();
|
|
79501
|
+
runtimeToken = bundle.runtimeToken;
|
|
79502
|
+
runtimeRenewalToken = bundle.runtimeRenewalToken;
|
|
79503
|
+
socket.auth = { token: bundle.runtimeToken };
|
|
79504
|
+
clearConnectErrors();
|
|
79505
|
+
const ready = new Promise((resolveReady, rejectReady) => {
|
|
79506
|
+
const timeout = setTimeout(() => {
|
|
79507
|
+
socket.off("runtime.ready", onReady);
|
|
79508
|
+
rejectReady(
|
|
79509
|
+
new Error("backend did not acknowledge the replacement credential generation")
|
|
79510
|
+
);
|
|
79511
|
+
}, 15e3);
|
|
79512
|
+
const onReady = (payload) => {
|
|
79513
|
+
if (payload?.credentialGeneration !== bundle.credentialGeneration) return;
|
|
79514
|
+
clearTimeout(timeout);
|
|
79515
|
+
socket.off("runtime.ready", onReady);
|
|
79516
|
+
resolveReady();
|
|
79517
|
+
};
|
|
79518
|
+
socket.on("runtime.ready", onReady);
|
|
79519
|
+
});
|
|
79520
|
+
pushLog(`runtime-credential-setup-redial generation=${bundle.credentialGeneration}`);
|
|
79521
|
+
if (socket.connected) socket.disconnect();
|
|
79522
|
+
socket.connect();
|
|
79523
|
+
await ready;
|
|
79524
|
+
pushLog(`runtime-credential-setup-ready generation=${bundle.credentialGeneration}`);
|
|
79525
|
+
return {
|
|
79526
|
+
runtimeId: bundle.runtimeId,
|
|
79527
|
+
credentialGeneration: bundle.credentialGeneration
|
|
79528
|
+
};
|
|
79529
|
+
})();
|
|
79530
|
+
runtimeSetupInFlight = attempt;
|
|
79531
|
+
void attempt.finally(() => {
|
|
79532
|
+
if (runtimeSetupInFlight === attempt) runtimeSetupInFlight = null;
|
|
79533
|
+
}).catch(() => {
|
|
79534
|
+
});
|
|
79535
|
+
return attempt;
|
|
79536
|
+
};
|
|
79351
79537
|
const relocationInFlight = /* @__PURE__ */ new Set();
|
|
79352
79538
|
const persistWorkspaceRelocations = () => {
|
|
79353
79539
|
const current = readConfig();
|
|
@@ -79773,7 +79959,8 @@ async function startDaemon(args) {
|
|
|
79773
79959
|
queueFullShutdown: () => queueFullShutdown(),
|
|
79774
79960
|
wsUrl,
|
|
79775
79961
|
inspectLocalSkill: (input2) => runtimeSkillManager.inspectLocalPackage(input2),
|
|
79776
|
-
readLocalSkillFile: (input2) => runtimeSkillManager.readLocalPackageFile(input2)
|
|
79962
|
+
readLocalSkillFile: (input2) => runtimeSkillManager.readLocalPackageFile(input2),
|
|
79963
|
+
adoptRuntimeSetupGrant
|
|
79777
79964
|
})
|
|
79778
79965
|
);
|
|
79779
79966
|
const occupiedProbe = await probeLocalDaemonEndpoint(localApiPort, localApiToken);
|
|
@@ -79967,7 +80154,7 @@ async function setupDaemon(args) {
|
|
|
79967
80154
|
const teamId = argValue(args, "--team") ?? process.env.ALAN_TEAM_ID;
|
|
79968
80155
|
const setupToken = argValue(args, "--setup-token") ?? process.env.ALAN_RUNTIME_SETUP_TOKEN;
|
|
79969
80156
|
const token = argValue(args, "--token") ?? process.env.ALAN_SETUP_TOKEN;
|
|
79970
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
80157
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os13.hostname)();
|
|
79971
80158
|
const scope = argValue(args, "--scope") ?? process.env.ALAN_RUNTIME_SCOPE ?? (setupToken ? "team" : "user");
|
|
79972
80159
|
const installationId = argValue(args, "--installation-id") ?? previousConfig.installationId ?? (0, import_node_crypto19.randomUUID)();
|
|
79973
80160
|
if (scope !== "team" && scope !== "user") {
|
|
@@ -79978,69 +80165,65 @@ async function setupDaemon(args) {
|
|
|
79978
80165
|
"setup requires --setup-token <token> or --token <Alan access token>.\nFor normal setup, copy the setup token from Alan and run: alan-agent setup --setup-token <token>\nFor browser authorization, run: alan-agent login"
|
|
79979
80166
|
);
|
|
79980
80167
|
}
|
|
79981
|
-
const
|
|
79982
|
-
|
|
79983
|
-
|
|
79984
|
-
|
|
79985
|
-
|
|
79986
|
-
|
|
79987
|
-
|
|
79988
|
-
|
|
79989
|
-
|
|
79990
|
-
|
|
79991
|
-
|
|
79992
|
-
|
|
79993
|
-
|
|
79994
|
-
|
|
79995
|
-
managementKind: "user_managed",
|
|
79996
|
-
hostKind: "daemon",
|
|
79997
|
-
lifecycle: "durable",
|
|
79998
|
-
capabilities: discoverCapabilities(),
|
|
79999
|
-
metadata: {
|
|
80000
|
-
...await collectRuntimeMetadataWithProviderLimits(),
|
|
80001
|
-
installationId
|
|
80002
|
-
}
|
|
80003
|
-
})
|
|
80168
|
+
const registrationGrant = setupToken ?? await createRuntimeSetupGrant({
|
|
80169
|
+
apiUrl,
|
|
80170
|
+
accessToken: token,
|
|
80171
|
+
scope,
|
|
80172
|
+
teamId
|
|
80173
|
+
});
|
|
80174
|
+
const setup = {
|
|
80175
|
+
apiUrl,
|
|
80176
|
+
wsUrl,
|
|
80177
|
+
endpointProfile,
|
|
80178
|
+
setupToken: registrationGrant,
|
|
80179
|
+
teamId,
|
|
80180
|
+
displayName,
|
|
80181
|
+
installationId
|
|
80004
80182
|
};
|
|
80005
|
-
let
|
|
80006
|
-
|
|
80007
|
-
|
|
80008
|
-
|
|
80009
|
-
|
|
80010
|
-
|
|
80011
|
-
|
|
80012
|
-
|
|
80183
|
+
let liveConfig = previousConfig;
|
|
80184
|
+
const localApiPort = getLocalApiPort(args, liveConfig);
|
|
80185
|
+
let live = liveConfig.localApiToken ? await probeLocalDaemon(localApiPort, liveConfig.localApiToken) : null;
|
|
80186
|
+
if (!live && liveConfig.localServiceId && liveConfig.localServiceSecret) {
|
|
80187
|
+
live = await adoptConfiguredLocalDaemon(args);
|
|
80188
|
+
liveConfig = readConfigForRegistration();
|
|
80189
|
+
}
|
|
80190
|
+
if (live) {
|
|
80191
|
+
if (!liveConfig.localApiToken) {
|
|
80192
|
+
throw new Error("running daemon could not be authenticated for credential setup");
|
|
80013
80193
|
}
|
|
80014
|
-
const
|
|
80015
|
-
|
|
80016
|
-
|
|
80194
|
+
const body2 = await handoffRuntimeSetupGrant({
|
|
80195
|
+
port: localApiPort,
|
|
80196
|
+
localApiToken: liveConfig.localApiToken,
|
|
80197
|
+
setup
|
|
80198
|
+
});
|
|
80199
|
+
console.info("[alan-agent] Runtime credentials adopted by running daemon", {
|
|
80200
|
+
runtimeId: body2.runtimeId,
|
|
80201
|
+
credentialGeneration: body2.credentialGeneration,
|
|
80202
|
+
configPath: getConfigPath()
|
|
80203
|
+
});
|
|
80204
|
+
return;
|
|
80017
80205
|
}
|
|
80018
|
-
if (
|
|
80019
|
-
|
|
80020
|
-
|
|
80206
|
+
if (readLocalDaemonOwnerLease(getConfigPath())) {
|
|
80207
|
+
throw new Error(
|
|
80208
|
+
"the daemon still owns this runtime configuration, but its authenticated local API is unreachable; recover or stop the daemon before running setup again"
|
|
80209
|
+
);
|
|
80021
80210
|
}
|
|
80022
|
-
|
|
80023
|
-
|
|
80024
|
-
|
|
80025
|
-
|
|
80026
|
-
|
|
80027
|
-
if (typeof parsed.error === "string") errorCode2 = parsed.error;
|
|
80028
|
-
} catch {
|
|
80029
|
-
}
|
|
80030
|
-
if (setupToken && response.status === 401 && errorCode2 === "setup_token_expired") {
|
|
80031
|
-
clearPendingSetupIntent();
|
|
80211
|
+
let body;
|
|
80212
|
+
try {
|
|
80213
|
+
body = await exchangeRuntimeSetupGrant(setup);
|
|
80214
|
+
} catch (error61) {
|
|
80215
|
+
if (setupToken && error61 instanceof RuntimeSetupGrantExpiredError) {
|
|
80032
80216
|
console.info("[alan-agent] Setup link expired; continuing with browser authorization");
|
|
80033
80217
|
await loginWithDeviceCode(args);
|
|
80034
80218
|
return;
|
|
80035
80219
|
}
|
|
80036
|
-
throw
|
|
80220
|
+
throw error61;
|
|
80037
80221
|
}
|
|
80038
|
-
const body = await response.json();
|
|
80039
80222
|
writeConfig({
|
|
80040
80223
|
apiUrl,
|
|
80041
80224
|
wsUrl,
|
|
80042
80225
|
endpointProfile,
|
|
80043
|
-
runtimeId: body.
|
|
80226
|
+
runtimeId: body.runtimeId,
|
|
80044
80227
|
runtimeToken: body.runtimeToken,
|
|
80045
80228
|
runtimeRenewalToken: body.runtimeRenewalToken,
|
|
80046
80229
|
localApiPort: getLocalApiPort(args, {}),
|
|
@@ -80049,12 +80232,12 @@ async function setupDaemon(args) {
|
|
|
80049
80232
|
localServiceSecret: previousConfig.localServiceSecret ?? (0, import_node_crypto19.randomBytes)(32).toString("base64url"),
|
|
80050
80233
|
eventSpoolKey: previousConfig.eventSpoolKey ?? (0, import_node_crypto19.randomBytes)(32).toString("base64url"),
|
|
80051
80234
|
daemonEpoch: previousConfig.daemonEpoch,
|
|
80052
|
-
displayName: body.
|
|
80235
|
+
displayName: body.displayName,
|
|
80053
80236
|
installationId
|
|
80054
80237
|
});
|
|
80055
|
-
|
|
80238
|
+
clearPendingSetupIntent();
|
|
80056
80239
|
console.info("[alan-agent] Runtime registered", {
|
|
80057
|
-
runtimeId: body.
|
|
80240
|
+
runtimeId: body.runtimeId,
|
|
80058
80241
|
configPath: getConfigPath()
|
|
80059
80242
|
});
|
|
80060
80243
|
}
|
|
@@ -80074,7 +80257,7 @@ async function loginWithDeviceCode(args) {
|
|
|
80074
80257
|
}
|
|
80075
80258
|
const previousConfig = readConfigForRegistration();
|
|
80076
80259
|
const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
|
|
80077
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
80260
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os13.hostname)();
|
|
80078
80261
|
const maxPolls = Number.parseInt(argValue(args, "--max-polls") ?? "300", 10);
|
|
80079
80262
|
const resumed = readPendingDeviceAuthorization(apiUrl);
|
|
80080
80263
|
const installationId = resumed?.installationId ?? previousConfig.installationId ?? (0, import_node_crypto19.randomUUID)();
|
|
@@ -80086,7 +80269,7 @@ async function loginWithDeviceCode(args) {
|
|
|
80086
80269
|
headers: { "content-type": "application/json" },
|
|
80087
80270
|
body: JSON.stringify({
|
|
80088
80271
|
displayName,
|
|
80089
|
-
hostname: (0,
|
|
80272
|
+
hostname: (0, import_node_os13.hostname)(),
|
|
80090
80273
|
capabilities: discoverCapabilities(),
|
|
80091
80274
|
metadata: {
|
|
80092
80275
|
...await collectRuntimeMetadataWithProviderLimits(),
|
|
@@ -80516,7 +80699,7 @@ async function printDoctor(args = []) {
|
|
|
80516
80699
|
// src/mcp-config-adapters.ts
|
|
80517
80700
|
var import_node_crypto20 = require("crypto");
|
|
80518
80701
|
var import_node_fs23 = require("fs");
|
|
80519
|
-
var
|
|
80702
|
+
var import_node_os14 = require("os");
|
|
80520
80703
|
var import_node_path25 = require("path");
|
|
80521
80704
|
var log = {
|
|
80522
80705
|
info: (...args) => console.info("[mcp-config-adapters]", ...args),
|
|
@@ -80526,7 +80709,7 @@ var log = {
|
|
|
80526
80709
|
};
|
|
80527
80710
|
var homeDirectoryOverride;
|
|
80528
80711
|
function homeDirectory() {
|
|
80529
|
-
return homeDirectoryOverride ?? (0,
|
|
80712
|
+
return homeDirectoryOverride ?? (0, import_node_os14.homedir)();
|
|
80530
80713
|
}
|
|
80531
80714
|
var MalformedToolConfigError = class extends Error {
|
|
80532
80715
|
};
|
|
@@ -81271,7 +81454,7 @@ var McpSyncService = class {
|
|
|
81271
81454
|
|
|
81272
81455
|
// src/native-hook-config.ts
|
|
81273
81456
|
var import_node_fs24 = require("fs");
|
|
81274
|
-
var
|
|
81457
|
+
var import_node_os15 = require("os");
|
|
81275
81458
|
var import_node_path26 = require("path");
|
|
81276
81459
|
var ALAN_HOOK_MARKER = "# alan-native-session-hook";
|
|
81277
81460
|
var ALAN_KIMI_HOOKS_START = "# alan-native-session-hooks:start";
|
|
@@ -81365,7 +81548,7 @@ function nativeHookCommand(input2) {
|
|
|
81365
81548
|
if (environment.length === 0) {
|
|
81366
81549
|
return { type: "command", command: input2.nodeExecutable, args, timeout: 5 };
|
|
81367
81550
|
}
|
|
81368
|
-
if ((input2.platform ?? (0,
|
|
81551
|
+
if ((input2.platform ?? (0, import_node_os15.platform)()) === "win32") {
|
|
81369
81552
|
const environmentPrefix2 = environment.map(([key, value2]) => `$env:${key}=${powershellQuote(value2)}`).join("; ");
|
|
81370
81553
|
const command2 = [input2.nodeExecutable, ...args].map(powershellQuote).join(" ");
|
|
81371
81554
|
return {
|
|
@@ -81410,11 +81593,11 @@ function resolveRuntime(input2 = {}) {
|
|
|
81410
81593
|
}
|
|
81411
81594
|
return {
|
|
81412
81595
|
configPath,
|
|
81413
|
-
homeDir: input2.homeDir ?? (0,
|
|
81596
|
+
homeDir: input2.homeDir ?? (0, import_node_os15.homedir)(),
|
|
81414
81597
|
nodeExecutable: input2.nodeExecutable ?? process.execPath,
|
|
81415
81598
|
cliEntry,
|
|
81416
81599
|
environment: input2.environment,
|
|
81417
|
-
platform: input2.platform ?? (0,
|
|
81600
|
+
platform: input2.platform ?? (0, import_node_os15.platform)()
|
|
81418
81601
|
};
|
|
81419
81602
|
}
|
|
81420
81603
|
function readSettings(path2, providerLabel) {
|
|
@@ -81505,7 +81688,7 @@ function reconcileClaudeNativeHooks(input2 = {}) {
|
|
|
81505
81688
|
})
|
|
81506
81689
|
});
|
|
81507
81690
|
}
|
|
81508
|
-
function removeClaudeNativeHooks(homeDir = (0,
|
|
81691
|
+
function removeClaudeNativeHooks(homeDir = (0, import_node_os15.homedir)()) {
|
|
81509
81692
|
return removeNestedCommandHooks((0, import_node_path26.join)(homeDir, ".claude", "settings.json"), "Claude");
|
|
81510
81693
|
}
|
|
81511
81694
|
function reconcileCodexNativeHooks(input2 = {}) {
|
|
@@ -81522,7 +81705,7 @@ function reconcileCodexNativeHooks(input2 = {}) {
|
|
|
81522
81705
|
})
|
|
81523
81706
|
});
|
|
81524
81707
|
}
|
|
81525
|
-
function removeCodexNativeHooks(homeDir = (0,
|
|
81708
|
+
function removeCodexNativeHooks(homeDir = (0, import_node_os15.homedir)()) {
|
|
81526
81709
|
return removeNestedCommandHooks((0, import_node_path26.join)(homeDir, ".codex", "hooks.json"), "Codex");
|
|
81527
81710
|
}
|
|
81528
81711
|
function reconcileCopilotNativeHooks(input2 = {}) {
|
|
@@ -81546,7 +81729,7 @@ function reconcileCopilotNativeHooks(input2 = {}) {
|
|
|
81546
81729
|
);
|
|
81547
81730
|
return writeSettings(path2, { version: 1, hooks });
|
|
81548
81731
|
}
|
|
81549
|
-
function removeCopilotNativeHooks(homeDir = (0,
|
|
81732
|
+
function removeCopilotNativeHooks(homeDir = (0, import_node_os15.homedir)()) {
|
|
81550
81733
|
const path2 = (0, import_node_path26.join)(homeDir, ".copilot", "hooks", "alan-native-session.json");
|
|
81551
81734
|
if (!(0, import_node_fs24.existsSync)(path2)) return false;
|
|
81552
81735
|
if (!(0, import_node_fs24.readFileSync)(path2, "utf8").includes(ALAN_HOOK_MARKER)) return false;
|
|
@@ -81571,7 +81754,7 @@ function reconcileCursorNativeHooks(input2 = {}) {
|
|
|
81571
81754
|
}
|
|
81572
81755
|
return writeSettings(path2, { ...settings, version: settings.version ?? 1, hooks });
|
|
81573
81756
|
}
|
|
81574
|
-
function removeCursorNativeHooks(homeDir = (0,
|
|
81757
|
+
function removeCursorNativeHooks(homeDir = (0, import_node_os15.homedir)()) {
|
|
81575
81758
|
const path2 = (0, import_node_path26.join)(homeDir, ".cursor", "hooks.json");
|
|
81576
81759
|
if (!(0, import_node_fs24.existsSync)(path2)) return false;
|
|
81577
81760
|
const settings = readSettings(path2, "Cursor");
|
|
@@ -81609,7 +81792,7 @@ function reconcileKimiNativeHooks(input2 = {}) {
|
|
|
81609
81792
|
`;
|
|
81610
81793
|
return writeTextFile(path2, content);
|
|
81611
81794
|
}
|
|
81612
|
-
function removeKimiNativeHooks(homeDir = (0,
|
|
81795
|
+
function removeKimiNativeHooks(homeDir = (0, import_node_os15.homedir)()) {
|
|
81613
81796
|
const path2 = (0, import_node_path26.join)(homeDir, ".kimi-code", "config.toml");
|
|
81614
81797
|
if (!(0, import_node_fs24.existsSync)(path2)) return false;
|
|
81615
81798
|
const current = (0, import_node_fs24.readFileSync)(path2, "utf8");
|
|
@@ -81635,7 +81818,7 @@ function reconcileGrokNativeHooks(input2 = {}) {
|
|
|
81635
81818
|
})
|
|
81636
81819
|
});
|
|
81637
81820
|
}
|
|
81638
|
-
function removeGrokNativeHooks(homeDir = (0,
|
|
81821
|
+
function removeGrokNativeHooks(homeDir = (0, import_node_os15.homedir)()) {
|
|
81639
81822
|
const path2 = (0, import_node_path26.join)(homeDir, ".grok", "hooks", "alan-native-session.json");
|
|
81640
81823
|
if (!(0, import_node_fs24.existsSync)(path2)) return false;
|
|
81641
81824
|
if (!(0, import_node_fs24.readFileSync)(path2, "utf8").includes(ALAN_HOOK_MARKER)) return false;
|
|
@@ -81739,7 +81922,7 @@ function reconcileOpencodeNativePlugin(input2 = {}) {
|
|
|
81739
81922
|
(0, import_node_fs24.renameSync)(temporary, path2);
|
|
81740
81923
|
return true;
|
|
81741
81924
|
}
|
|
81742
|
-
function removeOpencodeNativePlugin(homeDir = (0,
|
|
81925
|
+
function removeOpencodeNativePlugin(homeDir = (0, import_node_os15.homedir)()) {
|
|
81743
81926
|
const path2 = (0, import_node_path26.join)(homeDir, ".config", "opencode", "plugins", "alan-native-session.js");
|
|
81744
81927
|
if (!(0, import_node_fs24.existsSync)(path2)) return false;
|
|
81745
81928
|
if (!(0, import_node_fs24.readFileSync)(path2, "utf8").includes(ALAN_OPENCODE_PLUGIN_MARKER)) return false;
|
|
@@ -81754,7 +81937,7 @@ function configFileContainsMarker(path2, marker) {
|
|
|
81754
81937
|
return false;
|
|
81755
81938
|
}
|
|
81756
81939
|
}
|
|
81757
|
-
function inspectNativeHooksConfigured(providerKind, homeDir = (0,
|
|
81940
|
+
function inspectNativeHooksConfigured(providerKind, homeDir = (0, import_node_os15.homedir)(), expectedConfigPath) {
|
|
81758
81941
|
const matchesActiveProfile = (path2, marker) => {
|
|
81759
81942
|
if (!configFileContainsMarker(path2, marker)) return false;
|
|
81760
81943
|
if (!expectedConfigPath) return true;
|
|
@@ -94335,7 +94518,7 @@ async function runMcpStdioProxy(env = process.env, local = new StdioServerTransp
|
|
|
94335
94518
|
// src/native-hook-command.ts
|
|
94336
94519
|
var import_node_crypto21 = require("crypto");
|
|
94337
94520
|
var import_node_fs26 = require("fs");
|
|
94338
|
-
var
|
|
94521
|
+
var import_node_os16 = require("os");
|
|
94339
94522
|
var import_node_path28 = require("path");
|
|
94340
94523
|
|
|
94341
94524
|
// src/native-project-config.ts
|
|
@@ -94615,7 +94798,7 @@ function resolveCodexSessionIdFromTranscriptPath(transcriptPath) {
|
|
|
94615
94798
|
);
|
|
94616
94799
|
return match?.[1];
|
|
94617
94800
|
}
|
|
94618
|
-
function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path28.join)((0,
|
|
94801
|
+
function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path28.join)((0, import_node_os16.homedir)(), ".kimi-code")) {
|
|
94619
94802
|
if ((0, import_node_path28.basename)(externalSessionId) !== externalSessionId) return void 0;
|
|
94620
94803
|
const sessionsDir = (0, import_node_path28.join)(kimiHomeDir, "sessions");
|
|
94621
94804
|
if (!(0, import_node_fs26.existsSync)(sessionsDir)) return void 0;
|
|
@@ -94840,7 +95023,7 @@ function collectNativeIntegrationStatus(args = []) {
|
|
|
94840
95023
|
const config2 = readConfig();
|
|
94841
95024
|
const configPath = getConfigPath();
|
|
94842
95025
|
const env = getDaemonCliEnvironment();
|
|
94843
|
-
const homeDir = (0,
|
|
95026
|
+
const homeDir = (0, import_node_os16.homedir)();
|
|
94844
95027
|
return NATIVE_SESSION_PROVIDER_CAPABILITIES.map((capability) => ({
|
|
94845
95028
|
provider: capability.providerKind,
|
|
94846
95029
|
command: capability.command,
|
|
@@ -94869,7 +95052,7 @@ function decodeResumeFallbackContext(encoded) {
|
|
|
94869
95052
|
}
|
|
94870
95053
|
|
|
94871
95054
|
// src/sandbox.ts
|
|
94872
|
-
var
|
|
95055
|
+
var import_node_os17 = require("os");
|
|
94873
95056
|
|
|
94874
95057
|
// src/execution-activity-tracker.ts
|
|
94875
95058
|
var ExecutionActivityTracker = class {
|
|
@@ -95484,10 +95667,6 @@ var agentProbeAckSchema = external_exports.object({
|
|
|
95484
95667
|
// src/sandbox-outbox.ts
|
|
95485
95668
|
var import_node_crypto23 = require("crypto");
|
|
95486
95669
|
var import_node_fs27 = require("fs");
|
|
95487
|
-
var SANDBOX_EVENT_OUTBOX_ENV = "ALAN_EVENT_OUTBOX_ENABLED";
|
|
95488
|
-
function isSandboxEventOutboxEnabled(env = process.env) {
|
|
95489
|
-
return env[SANDBOX_EVENT_OUTBOX_ENV] === "true";
|
|
95490
|
-
}
|
|
95491
95670
|
function deriveSandboxOutboxKey(sessionToken) {
|
|
95492
95671
|
if (!sessionToken) {
|
|
95493
95672
|
throw new Error("sandbox event outbox requires ALAN_SESSION_TOKEN for key derivation");
|
|
@@ -95507,6 +95686,7 @@ function createSandboxEventOutbox(input2) {
|
|
|
95507
95686
|
`sandbox_outbox_spool_reset ${error61 instanceof Error ? error61.message : String(error61)}`
|
|
95508
95687
|
);
|
|
95509
95688
|
(0, import_node_fs27.rmSync)(path2, { force: true });
|
|
95689
|
+
(0, import_node_fs27.rmSync)(eventJournalDir(path2), { recursive: true, force: true });
|
|
95510
95690
|
return new EncryptedEventOutbox(path2, key, input2.pushLog, input2.options);
|
|
95511
95691
|
}
|
|
95512
95692
|
}
|
|
@@ -95526,7 +95706,12 @@ var SandboxOutboxSocket = class {
|
|
|
95526
95706
|
seq = this.seqCounter;
|
|
95527
95707
|
this.seqByEventId.set(payload.eventId, seq);
|
|
95528
95708
|
}
|
|
95529
|
-
const wirePayload = {
|
|
95709
|
+
const wirePayload = {
|
|
95710
|
+
...payload.event,
|
|
95711
|
+
eventId: payload.eventId,
|
|
95712
|
+
seq,
|
|
95713
|
+
deliveryRunId: payload.runId
|
|
95714
|
+
};
|
|
95530
95715
|
this.socket.emit("agent_event", wirePayload, (result) => {
|
|
95531
95716
|
if (result?.ok) this.seqByEventId.delete(payload.eventId);
|
|
95532
95717
|
acknowledge({ ok: Boolean(result?.ok), retryable: result?.retryable });
|
|
@@ -95540,54 +95725,38 @@ var SandboxEventDispatcher = class {
|
|
|
95540
95725
|
currentRunId;
|
|
95541
95726
|
constructor(input2) {
|
|
95542
95727
|
this.conversationId = input2.conversationId;
|
|
95543
|
-
|
|
95544
|
-
|
|
95545
|
-
|
|
95546
|
-
|
|
95547
|
-
|
|
95548
|
-
|
|
95549
|
-
|
|
95550
|
-
|
|
95551
|
-
});
|
|
95552
|
-
this.outboxSocket = new SandboxOutboxSocket(input2.socket);
|
|
95553
|
-
} catch (error61) {
|
|
95554
|
-
input2.onInitError?.(error61);
|
|
95555
|
-
this.outbox = void 0;
|
|
95556
|
-
this.outboxSocket = void 0;
|
|
95557
|
-
}
|
|
95558
|
-
}
|
|
95559
|
-
/** True when events are being durably queued rather than fired-and-forgotten. */
|
|
95560
|
-
get active() {
|
|
95561
|
-
return this.outbox !== void 0 && this.outboxSocket !== void 0;
|
|
95728
|
+
this.outbox = createSandboxEventOutbox({
|
|
95729
|
+
conversationId: input2.conversationId,
|
|
95730
|
+
sessionToken: input2.sessionToken,
|
|
95731
|
+
pushLog: input2.pushLog,
|
|
95732
|
+
options: input2.options,
|
|
95733
|
+
spoolPath: input2.spoolPath
|
|
95734
|
+
});
|
|
95735
|
+
this.outboxSocket = new SandboxOutboxSocket(input2.socket);
|
|
95562
95736
|
}
|
|
95563
95737
|
/** Set the run id used for fair replay and per-run heartbeat pruning. */
|
|
95564
95738
|
setRunId(runId) {
|
|
95565
95739
|
this.currentRunId = runId;
|
|
95566
95740
|
}
|
|
95567
95741
|
/**
|
|
95568
|
-
* Durably deliver one event (enqueue-before-send, remove-on-ack).
|
|
95569
|
-
* outbox is inactive, defers to `fireAndForget` so behaviour is unchanged.
|
|
95742
|
+
* Durably deliver one event (enqueue-before-send, remove-on-ack).
|
|
95570
95743
|
*/
|
|
95571
|
-
emit(event
|
|
95572
|
-
if (!this.outbox || !this.outboxSocket) {
|
|
95573
|
-
fireAndForget(event);
|
|
95574
|
-
return;
|
|
95575
|
-
}
|
|
95744
|
+
emit(event) {
|
|
95576
95745
|
if (isBackgroundHeartbeat(event) && !this.outboxSocket.connected) return;
|
|
95577
95746
|
this.outbox.enqueue(this.conversationId, this.currentRunId ?? this.conversationId, event);
|
|
95578
95747
|
this.outbox.flush(this.outboxSocket);
|
|
95579
95748
|
}
|
|
95580
95749
|
/** Replay un-acked events in order — called on (re)connect before new events. */
|
|
95581
95750
|
flush() {
|
|
95582
|
-
|
|
95751
|
+
this.outbox.flush(this.outboxSocket);
|
|
95583
95752
|
}
|
|
95584
95753
|
/** Reset in-flight state on disconnect so the next flush replays from the head. */
|
|
95585
95754
|
disconnect() {
|
|
95586
|
-
this.outbox
|
|
95755
|
+
this.outbox.disconnect();
|
|
95587
95756
|
}
|
|
95588
95757
|
/** Diagnostics: number of events still awaiting a server ack. */
|
|
95589
95758
|
pendingCount() {
|
|
95590
|
-
return this.outbox
|
|
95759
|
+
return this.outbox.pendingCount();
|
|
95591
95760
|
}
|
|
95592
95761
|
};
|
|
95593
95762
|
|
|
@@ -95631,20 +95800,13 @@ var WSClient = class {
|
|
|
95631
95800
|
upgrade: false,
|
|
95632
95801
|
extraHeaders: { "ngrok-skip-browser-warning": "1" }
|
|
95633
95802
|
});
|
|
95634
|
-
const outboxEnabled = isSandboxEventOutboxEnabled();
|
|
95635
95803
|
this.eventDispatcher = new SandboxEventDispatcher({
|
|
95636
95804
|
conversationId: sessionId,
|
|
95637
95805
|
sessionToken: token,
|
|
95638
|
-
enabled: outboxEnabled,
|
|
95639
95806
|
socket: this.socket,
|
|
95640
|
-
pushLog: (message) => this.lifecycle?.info("sandbox_agent_event_outbox", { detail: message })
|
|
95641
|
-
onInitError: (error61) => this.lifecycle?.warn("sandbox_agent_event_outbox_init_failed", {
|
|
95642
|
-
error: error61 instanceof Error ? error61 : new Error(String(error61))
|
|
95643
|
-
})
|
|
95807
|
+
pushLog: (message) => this.lifecycle?.info("sandbox_agent_event_outbox", { detail: message })
|
|
95644
95808
|
});
|
|
95645
|
-
|
|
95646
|
-
this.lifecycle?.info("sandbox_agent_event_outbox_enabled", { conversationId: sessionId });
|
|
95647
|
-
}
|
|
95809
|
+
this.lifecycle?.info("sandbox_agent_event_outbox_enabled", { conversationId: sessionId });
|
|
95648
95810
|
this.setupListeners(callbacks);
|
|
95649
95811
|
}
|
|
95650
95812
|
socket;
|
|
@@ -95659,11 +95821,7 @@ var WSClient = class {
|
|
|
95659
95821
|
intentionalClose = false;
|
|
95660
95822
|
agentVersion;
|
|
95661
95823
|
getRunState;
|
|
95662
|
-
/**
|
|
95663
|
-
* Durable at-least-once delivery for stream events. Active only when
|
|
95664
|
-
* `ALAN_EVENT_OUTBOX_ENABLED === "true"`; otherwise events are fired-and-
|
|
95665
|
-
* forgotten exactly as before (see {@link SandboxEventDispatcher}).
|
|
95666
|
-
*/
|
|
95824
|
+
/** Durable at-least-once delivery for stream events (see {@link SandboxEventDispatcher}). */
|
|
95667
95825
|
eventDispatcher;
|
|
95668
95826
|
/**
|
|
95669
95827
|
* Bounded record of `messageId`s whose handoff to `onUserMessage` already
|
|
@@ -95686,8 +95844,7 @@ var WSClient = class {
|
|
|
95686
95844
|
}
|
|
95687
95845
|
/**
|
|
95688
95846
|
* Record the run id for events emitted from here on, so the durable outbox can
|
|
95689
|
-
* bucket per-run caps and terminal-event condensation correctly.
|
|
95690
|
-
* outbox is disabled.
|
|
95847
|
+
* bucket per-run caps and terminal-event condensation correctly.
|
|
95691
95848
|
*/
|
|
95692
95849
|
setCurrentRunId(runId) {
|
|
95693
95850
|
this.eventDispatcher.setRunId(runId);
|
|
@@ -95728,9 +95885,7 @@ var WSClient = class {
|
|
|
95728
95885
|
}
|
|
95729
95886
|
}
|
|
95730
95887
|
emitEvent(event) {
|
|
95731
|
-
this.eventDispatcher.emit(event
|
|
95732
|
-
this.socket.emit("agent_event", payload);
|
|
95733
|
-
});
|
|
95888
|
+
this.eventDispatcher.emit(event);
|
|
95734
95889
|
}
|
|
95735
95890
|
waitForConnection(timeoutMs = 15e3) {
|
|
95736
95891
|
return new Promise((resolve15, reject) => {
|
|
@@ -96172,7 +96327,7 @@ async function runSandbox(config2) {
|
|
|
96172
96327
|
}
|
|
96173
96328
|
const presenter = new WebPresenter(wsClient, config2.sessionId, config2.projectPath);
|
|
96174
96329
|
presenter.setSuppressSessionLifecycle(true);
|
|
96175
|
-
const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0,
|
|
96330
|
+
const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os17.homedir)() });
|
|
96176
96331
|
let lastProviderSessionId = config2.providerSessionId;
|
|
96177
96332
|
let resumeFallbackContext = config2.resumeFallbackContext;
|
|
96178
96333
|
let activeBackendKind = config2.backendKind || "claude_cli";
|
|
@@ -96472,7 +96627,7 @@ async function runSandbox(config2) {
|
|
|
96472
96627
|
// src/service-manager.ts
|
|
96473
96628
|
var import_node_child_process9 = require("child_process");
|
|
96474
96629
|
var import_node_fs28 = require("fs");
|
|
96475
|
-
var
|
|
96630
|
+
var import_node_os18 = require("os");
|
|
96476
96631
|
var import_node_path29 = require("path");
|
|
96477
96632
|
var SERVICE_LABEL = "ai.tryalan.agent";
|
|
96478
96633
|
var SYSTEMD_UNIT = "alan-agent.service";
|
|
@@ -96789,7 +96944,7 @@ WantedBy=default.target
|
|
|
96789
96944
|
};
|
|
96790
96945
|
}
|
|
96791
96946
|
function resolveCurrentPlatform() {
|
|
96792
|
-
const currentPlatform = (0,
|
|
96947
|
+
const currentPlatform = (0, import_node_os18.platform)();
|
|
96793
96948
|
if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
|
|
96794
96949
|
throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
|
|
96795
96950
|
}
|
|
@@ -96802,7 +96957,7 @@ function currentServicePlan(args, runtime) {
|
|
|
96802
96957
|
if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
|
|
96803
96958
|
return buildDaemonServicePlan({
|
|
96804
96959
|
platform: currentPlatform,
|
|
96805
|
-
homeDir: (0,
|
|
96960
|
+
homeDir: (0, import_node_os18.homedir)(),
|
|
96806
96961
|
nodeExecutable: runtime?.executable ?? process.execPath,
|
|
96807
96962
|
cliEntry: (0, import_node_path29.resolve)(cliEntry),
|
|
96808
96963
|
profile,
|
|
@@ -96883,7 +97038,7 @@ function shouldStartOnInstall(hostState) {
|
|
|
96883
97038
|
function resolveUsername(options) {
|
|
96884
97039
|
if (options?.username) return options.username;
|
|
96885
97040
|
try {
|
|
96886
|
-
return (0,
|
|
97041
|
+
return (0, import_node_os18.userInfo)().username;
|
|
96887
97042
|
} catch {
|
|
96888
97043
|
return process.env.USER || process.env.USERNAME || "unknown";
|
|
96889
97044
|
}
|
|
@@ -96921,7 +97076,7 @@ function createHostContext(options = {}) {
|
|
|
96921
97076
|
const removeManifest = options.removeManifest ?? ((path2) => (0, import_node_fs28.rmSync)(path2, { force: true }));
|
|
96922
97077
|
const ensureLogDir = options.ensureLogDir ?? (() => {
|
|
96923
97078
|
if (plan.platform === "darwin") {
|
|
96924
|
-
(0, import_node_fs28.mkdirSync)((0, import_node_path29.join)((0,
|
|
97079
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path29.join)((0, import_node_os18.homedir)(), ".alan", "agent", "logs"), { recursive: true, mode: 448 });
|
|
96925
97080
|
}
|
|
96926
97081
|
});
|
|
96927
97082
|
return {
|
|
@@ -97037,11 +97192,11 @@ ${result.output}
|
|
|
97037
97192
|
|
|
97038
97193
|
// src/skills/skill-cli.ts
|
|
97039
97194
|
var import_promises6 = require("fs/promises");
|
|
97040
|
-
var
|
|
97195
|
+
var import_node_os19 = require("os");
|
|
97041
97196
|
var import_node_path30 = require("path");
|
|
97042
97197
|
async function runSkillsCommand(args) {
|
|
97043
97198
|
const [subcommand, ...options] = args;
|
|
97044
|
-
const homeDirectory2 = option(options, "--home") ?? (0,
|
|
97199
|
+
const homeDirectory2 = option(options, "--home") ?? (0, import_node_os19.homedir)();
|
|
97045
97200
|
const manager = await RuntimeSkillManager.open({ homeDirectory: homeDirectory2 });
|
|
97046
97201
|
if (subcommand === "scan") {
|
|
97047
97202
|
const inputPath = option(options, "--input");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alan-ai-hq/agent-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.89",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Alan agent runtime — cloud sandbox and local daemon (alan-agent CLI)",
|
|
6
6
|
"bin": {
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"test:coverage": "vitest run --coverage",
|
|
41
41
|
"test:watch": "vitest",
|
|
42
42
|
"type-check": "tsc --noEmit",
|
|
43
|
-
"publish:npm": "node ../../scripts/publish-agent-manager.mjs"
|
|
44
|
-
"publish:npm:legacy": "node ../../scripts/publish-agent-manager.mjs --legacy-only"
|
|
43
|
+
"publish:npm": "node ../../scripts/publish-agent-manager.mjs"
|
|
45
44
|
}
|
|
46
45
|
}
|