@aiden-ade/sandbox-agent 0.1.79 → 0.1.82
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 +1362 -612
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -14973,7 +14973,7 @@ function resolveCommand(args, env) {
|
|
|
14973
14973
|
|
|
14974
14974
|
// src/daemon.ts
|
|
14975
14975
|
var import_node_crypto17 = require("crypto");
|
|
14976
|
-
var
|
|
14976
|
+
var import_node_os12 = require("os");
|
|
14977
14977
|
|
|
14978
14978
|
// src/sleep-inhibitor.ts
|
|
14979
14979
|
var import_node_child_process2 = require("child_process");
|
|
@@ -15240,7 +15240,7 @@ function describeError(error61) {
|
|
|
15240
15240
|
}
|
|
15241
15241
|
|
|
15242
15242
|
// src/version.ts
|
|
15243
|
-
var AGENT_VERSION = "0.1.
|
|
15243
|
+
var AGENT_VERSION = "0.1.82";
|
|
15244
15244
|
|
|
15245
15245
|
// src/daemon-worktree.ts
|
|
15246
15246
|
var import_node_child_process3 = require("child_process");
|
|
@@ -15296,104 +15296,6 @@ function isInteractiveToolName(name, input2) {
|
|
|
15296
15296
|
var ALAN_AGENT_WORKOS_USER_ID_PREFIX = "alan-agent:";
|
|
15297
15297
|
var ALAN_AGENT_WORKOS_USER_ID_LIKE_PATTERN = `${ALAN_AGENT_WORKOS_USER_ID_PREFIX}%`;
|
|
15298
15298
|
|
|
15299
|
-
// ../shared/dist/constants/colors.js
|
|
15300
|
-
var CATEGORICAL_COLORS = {
|
|
15301
|
-
slate: "#7280a0",
|
|
15302
|
-
slateMuted: "#8892a4",
|
|
15303
|
-
slateCool: "#6b7a96",
|
|
15304
|
-
slateDeep: "#64748b",
|
|
15305
|
-
slateClosed: "#7a8295",
|
|
15306
|
-
slateLight: "#94a3b8",
|
|
15307
|
-
slatePale: "#cbd5e1",
|
|
15308
|
-
blue: "#5583b5",
|
|
15309
|
-
blueMuted: "#6a90b0",
|
|
15310
|
-
blueBright: "#3b82f6",
|
|
15311
|
-
blueSoft: "#7d9fc2",
|
|
15312
|
-
cyan: "#3a92a8",
|
|
15313
|
-
cyanBright: "#2f9ab5",
|
|
15314
|
-
cyanSoft: "#6dadb8",
|
|
15315
|
-
teal: "#4895a5",
|
|
15316
|
-
tealDeep: "#2e9e80",
|
|
15317
|
-
green: "#3d9170",
|
|
15318
|
-
greenBright: "#3a9c6f",
|
|
15319
|
-
greenMuted: "#5a9a6a",
|
|
15320
|
-
greenSoft: "#6daa94",
|
|
15321
|
-
greenLeaf: "#74b080",
|
|
15322
|
-
purple: "#7e6db2",
|
|
15323
|
-
dubaiPurple: "#6366f1",
|
|
15324
|
-
purpleMuted: "#9a6daa",
|
|
15325
|
-
purpleSoft: "#9a8cbd",
|
|
15326
|
-
violet: "#8b6bbf",
|
|
15327
|
-
indigo: "#6b75d6",
|
|
15328
|
-
indigoMuted: "#838cc0",
|
|
15329
|
-
gold: "#b08a45",
|
|
15330
|
-
goldMuted: "#a89248",
|
|
15331
|
-
amber: "#c49a30",
|
|
15332
|
-
yellow: "#eab308",
|
|
15333
|
-
orange: "#c27058",
|
|
15334
|
-
orangeDeep: "#c47d3a",
|
|
15335
|
-
orangeBright: "#f97316",
|
|
15336
|
-
orangeSoft: "#d49872",
|
|
15337
|
-
orangePale: "#fdba74",
|
|
15338
|
-
red: "#c25858",
|
|
15339
|
-
redBright: "#ef4444",
|
|
15340
|
-
redSoft: "#c47474",
|
|
15341
|
-
pink: "#b25a8a",
|
|
15342
|
-
pinkMuted: "#b86078",
|
|
15343
|
-
pinkSoft: "#c07a9a",
|
|
15344
|
-
rose: "#c44d8a",
|
|
15345
|
-
bronze: "#8a8258",
|
|
15346
|
-
avatarBlue: "#4a7fc4",
|
|
15347
|
-
avatarPurple: "#7b62c4",
|
|
15348
|
-
avatarOrange: "#c4703a"
|
|
15349
|
-
};
|
|
15350
|
-
var CATEGORICAL_COLOR_VALUES = Object.values(CATEGORICAL_COLORS);
|
|
15351
|
-
var CATEGORICAL_COLOR_VALUE_SET = new Set(CATEGORICAL_COLOR_VALUES);
|
|
15352
|
-
|
|
15353
|
-
// ../shared/dist/constants/labels.js
|
|
15354
|
-
var LABEL_COLOR_PRESETS = {
|
|
15355
|
-
bug: CATEGORICAL_COLORS.red,
|
|
15356
|
-
feature: CATEGORICAL_COLORS.purple,
|
|
15357
|
-
improvement: CATEGORICAL_COLORS.blue,
|
|
15358
|
-
refactor: CATEGORICAL_COLORS.gold,
|
|
15359
|
-
docs: CATEGORICAL_COLORS.green,
|
|
15360
|
-
chore: CATEGORICAL_COLORS.slate,
|
|
15361
|
-
design: CATEGORICAL_COLORS.pink,
|
|
15362
|
-
research: CATEGORICAL_COLORS.cyan
|
|
15363
|
-
};
|
|
15364
|
-
var LABEL_COLOR_PALETTE = [
|
|
15365
|
-
CATEGORICAL_COLORS.orange,
|
|
15366
|
-
CATEGORICAL_COLORS.goldMuted,
|
|
15367
|
-
CATEGORICAL_COLORS.greenMuted,
|
|
15368
|
-
CATEGORICAL_COLORS.teal,
|
|
15369
|
-
CATEGORICAL_COLORS.indigo,
|
|
15370
|
-
CATEGORICAL_COLORS.purpleMuted,
|
|
15371
|
-
CATEGORICAL_COLORS.pinkMuted,
|
|
15372
|
-
CATEGORICAL_COLORS.bronze,
|
|
15373
|
-
CATEGORICAL_COLORS.blueMuted
|
|
15374
|
-
];
|
|
15375
|
-
var LABEL_COLOR_CHOICES = [
|
|
15376
|
-
CATEGORICAL_COLORS.slate,
|
|
15377
|
-
CATEGORICAL_COLORS.blue,
|
|
15378
|
-
CATEGORICAL_COLORS.purple,
|
|
15379
|
-
CATEGORICAL_COLORS.green,
|
|
15380
|
-
CATEGORICAL_COLORS.red,
|
|
15381
|
-
CATEGORICAL_COLORS.orange,
|
|
15382
|
-
CATEGORICAL_COLORS.gold,
|
|
15383
|
-
CATEGORICAL_COLORS.pink,
|
|
15384
|
-
CATEGORICAL_COLORS.cyan,
|
|
15385
|
-
CATEGORICAL_COLORS.teal
|
|
15386
|
-
];
|
|
15387
|
-
var AVATAR_COLOR_PALETTE = [
|
|
15388
|
-
CATEGORICAL_COLORS.avatarBlue,
|
|
15389
|
-
CATEGORICAL_COLORS.avatarPurple,
|
|
15390
|
-
CATEGORICAL_COLORS.indigo,
|
|
15391
|
-
CATEGORICAL_COLORS.rose,
|
|
15392
|
-
CATEGORICAL_COLORS.avatarOrange,
|
|
15393
|
-
CATEGORICAL_COLORS.greenBright,
|
|
15394
|
-
CATEGORICAL_COLORS.cyanBright
|
|
15395
|
-
];
|
|
15396
|
-
|
|
15397
15299
|
// ../shared/dist/constants/local-workspace.js
|
|
15398
15300
|
var ALAN_DEFAULT_WORKSPACE_URI = "alan://workspace";
|
|
15399
15301
|
function isAlanDefaultWorkspace(value2) {
|
|
@@ -15412,172 +15314,12 @@ Before create_task:
|
|
|
15412
15314
|
4. Use list_team_labels and apply matching labels when creating or updating; do not invent label variants.
|
|
15413
15315
|
5. Similarity hits are hints only \u2014 synthesize context and use judgment, not fixed thresholds.`;
|
|
15414
15316
|
|
|
15415
|
-
// ../shared/dist/constants/tasks.js
|
|
15416
|
-
var STATUS_OPTIONS = [
|
|
15417
|
-
{
|
|
15418
|
-
value: "backlog",
|
|
15419
|
-
label: "Backlog",
|
|
15420
|
-
color: CATEGORICAL_COLORS.slateMuted,
|
|
15421
|
-
group: "not_started",
|
|
15422
|
-
dotClass: "text-muted-foreground",
|
|
15423
|
-
headerBg: "bg-muted/60"
|
|
15424
|
-
},
|
|
15425
|
-
{
|
|
15426
|
-
value: "todo",
|
|
15427
|
-
label: "Todo",
|
|
15428
|
-
color: CATEGORICAL_COLORS.slateCool,
|
|
15429
|
-
group: "not_started",
|
|
15430
|
-
dotClass: "text-muted-foreground/70",
|
|
15431
|
-
headerBg: "bg-muted/40"
|
|
15432
|
-
},
|
|
15433
|
-
{
|
|
15434
|
-
value: "in_progress",
|
|
15435
|
-
label: "In Progress",
|
|
15436
|
-
color: CATEGORICAL_COLORS.amber,
|
|
15437
|
-
group: "active",
|
|
15438
|
-
dotClass: "text-amber-700 dark:text-amber-400",
|
|
15439
|
-
headerBg: "bg-amber-400/15"
|
|
15440
|
-
},
|
|
15441
|
-
{
|
|
15442
|
-
value: "in_review",
|
|
15443
|
-
label: "In Review",
|
|
15444
|
-
color: CATEGORICAL_COLORS.violet,
|
|
15445
|
-
group: "active",
|
|
15446
|
-
dotClass: "text-violet-500 dark:text-violet-400",
|
|
15447
|
-
headerBg: "bg-violet-400/15"
|
|
15448
|
-
},
|
|
15449
|
-
{
|
|
15450
|
-
value: "done",
|
|
15451
|
-
label: "Done",
|
|
15452
|
-
color: CATEGORICAL_COLORS.tealDeep,
|
|
15453
|
-
group: "done",
|
|
15454
|
-
dotClass: "text-teal-600 dark:text-teal-400",
|
|
15455
|
-
headerBg: "bg-teal-400/15"
|
|
15456
|
-
},
|
|
15457
|
-
{
|
|
15458
|
-
value: "cancelled",
|
|
15459
|
-
label: "Cancelled",
|
|
15460
|
-
color: CATEGORICAL_COLORS.slateClosed,
|
|
15461
|
-
group: "closed",
|
|
15462
|
-
dotClass: "text-muted-foreground/60",
|
|
15463
|
-
headerBg: "bg-muted/60"
|
|
15464
|
-
}
|
|
15465
|
-
];
|
|
15466
|
-
var DEFAULT_TEAM_STATUSES = STATUS_OPTIONS.map((o) => ({
|
|
15467
|
-
id: o.value,
|
|
15468
|
-
label: o.label,
|
|
15469
|
-
color: o.color,
|
|
15470
|
-
group: o.group
|
|
15471
|
-
}));
|
|
15472
|
-
var EPIC_STATUS_OPTIONS = [
|
|
15473
|
-
{
|
|
15474
|
-
value: "backlog",
|
|
15475
|
-
label: "Backlog",
|
|
15476
|
-
color: CATEGORICAL_COLORS.slateMuted,
|
|
15477
|
-
group: "not_started"
|
|
15478
|
-
},
|
|
15479
|
-
{
|
|
15480
|
-
value: "planned",
|
|
15481
|
-
label: "Planned",
|
|
15482
|
-
color: CATEGORICAL_COLORS.blueSoft,
|
|
15483
|
-
group: "not_started"
|
|
15484
|
-
},
|
|
15485
|
-
{
|
|
15486
|
-
value: "in_progress",
|
|
15487
|
-
label: "In Progress",
|
|
15488
|
-
color: CATEGORICAL_COLORS.amber,
|
|
15489
|
-
group: "active"
|
|
15490
|
-
},
|
|
15491
|
-
{
|
|
15492
|
-
value: "completed",
|
|
15493
|
-
label: "Completed",
|
|
15494
|
-
color: CATEGORICAL_COLORS.tealDeep,
|
|
15495
|
-
group: "done"
|
|
15496
|
-
},
|
|
15497
|
-
{
|
|
15498
|
-
value: "canceled",
|
|
15499
|
-
label: "Canceled",
|
|
15500
|
-
color: CATEGORICAL_COLORS.slateClosed,
|
|
15501
|
-
group: "closed"
|
|
15502
|
-
}
|
|
15503
|
-
];
|
|
15504
|
-
var DEFAULT_EPIC_STATUSES = EPIC_STATUS_OPTIONS.map((o) => ({
|
|
15505
|
-
id: o.value,
|
|
15506
|
-
label: o.label,
|
|
15507
|
-
color: o.color,
|
|
15508
|
-
group: o.group
|
|
15509
|
-
}));
|
|
15510
|
-
var PRIORITY_OPTIONS = [
|
|
15511
|
-
{
|
|
15512
|
-
value: "p0",
|
|
15513
|
-
label: "Urgent",
|
|
15514
|
-
detail: "Urgent",
|
|
15515
|
-
color: CATEGORICAL_COLORS.redBright,
|
|
15516
|
-
iconClass: "text-red-500/70",
|
|
15517
|
-
flagClass: "text-red-600 dark:text-red-400"
|
|
15518
|
-
},
|
|
15519
|
-
{
|
|
15520
|
-
value: "p1",
|
|
15521
|
-
label: "High",
|
|
15522
|
-
detail: "High",
|
|
15523
|
-
color: CATEGORICAL_COLORS.orangeBright,
|
|
15524
|
-
iconClass: "text-orange-500/70",
|
|
15525
|
-
flagClass: "text-orange-600 dark:text-orange-400"
|
|
15526
|
-
},
|
|
15527
|
-
{
|
|
15528
|
-
value: "p2",
|
|
15529
|
-
label: "Medium",
|
|
15530
|
-
detail: "Medium",
|
|
15531
|
-
color: CATEGORICAL_COLORS.yellow,
|
|
15532
|
-
iconClass: "text-amber-500/70 dark:text-amber-400/70",
|
|
15533
|
-
flagClass: "text-amber-600 dark:text-amber-400"
|
|
15534
|
-
},
|
|
15535
|
-
{
|
|
15536
|
-
value: "p3",
|
|
15537
|
-
label: "Low",
|
|
15538
|
-
detail: "Low",
|
|
15539
|
-
color: CATEGORICAL_COLORS.blueBright,
|
|
15540
|
-
iconClass: "text-blue-500/70 dark:text-blue-400/70",
|
|
15541
|
-
flagClass: "text-blue-600 dark:text-blue-400"
|
|
15542
|
-
},
|
|
15543
|
-
{
|
|
15544
|
-
value: "none",
|
|
15545
|
-
label: "No priority",
|
|
15546
|
-
detail: "No priority",
|
|
15547
|
-
color: CATEGORICAL_COLORS.slateDeep,
|
|
15548
|
-
iconClass: "text-muted-foreground/40",
|
|
15549
|
-
flagClass: "text-muted-foreground/50"
|
|
15550
|
-
}
|
|
15551
|
-
];
|
|
15552
|
-
|
|
15553
|
-
// ../shared/dist/constants/workspace-retention.js
|
|
15554
|
-
var RESOURCE_CLASS_GC_TIME_MS = {
|
|
15555
|
-
/**
|
|
15556
|
-
* Small, stable, expensive-to-refetch descriptors: team lists, member lists,
|
|
15557
|
-
* label sets, status metadata. Kilobytes that rarely change.
|
|
15558
|
-
*/
|
|
15559
|
-
metadata: 30 * 6e4,
|
|
15560
|
-
/** Everything not explicitly classified. The previous global default. */
|
|
15561
|
-
standard: 10 * 6e4,
|
|
15562
|
-
/**
|
|
15563
|
-
* Large per-entity payloads: transcripts, diffs, file trees, image sets,
|
|
15564
|
-
* paginated bulk lists. Megabytes that are cheap to re-fetch on return.
|
|
15565
|
-
*/
|
|
15566
|
-
bulk: 9e4,
|
|
15567
|
-
/**
|
|
15568
|
-
* Immutable content addressed by a content hash (commit diffs). Retaining it
|
|
15569
|
-
* is a pure win while it fits the budget, and the budget controller drops it
|
|
15570
|
-
* first under pressure precisely because it can always be re-derived.
|
|
15571
|
-
*/
|
|
15572
|
-
immutable: 60 * 6e4
|
|
15573
|
-
};
|
|
15574
|
-
|
|
15575
15317
|
// ../shared/dist/node/local-workspace.js
|
|
15576
15318
|
var import_node_fs2 = require("fs");
|
|
15577
15319
|
var import_node_os2 = require("os");
|
|
15578
15320
|
var import_node_path2 = require("path");
|
|
15579
|
-
function resolveAlanDefaultWorkspacePath(
|
|
15580
|
-
return (0, import_node_path2.join)(
|
|
15321
|
+
function resolveAlanDefaultWorkspacePath(homeDirectory2 = (0, import_node_os2.homedir)()) {
|
|
15322
|
+
return (0, import_node_path2.join)(homeDirectory2, ".alan", "workspace");
|
|
15581
15323
|
}
|
|
15582
15324
|
|
|
15583
15325
|
// src/local-workspace-migration.ts
|
|
@@ -35665,6 +35407,22 @@ var import_node_os4 = require("os");
|
|
|
35665
35407
|
var import_node_path5 = require("path");
|
|
35666
35408
|
var DEFAULT_AGENT_DIR = (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan", "agent");
|
|
35667
35409
|
var LEGACY_AGENT_DIR = (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".aiden", "agent");
|
|
35410
|
+
function configuredConfigPathFromEnvironment() {
|
|
35411
|
+
const explicit = process.env.ALAN_AGENT_CONFIG_PATH?.trim() || process.env.ALAN_AGENT_CONFIG?.trim();
|
|
35412
|
+
return explicit || void 0;
|
|
35413
|
+
}
|
|
35414
|
+
function resolveIsolatedAgentBaseDir(profile) {
|
|
35415
|
+
switch (profile) {
|
|
35416
|
+
case "local":
|
|
35417
|
+
return (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan-dev", "agent");
|
|
35418
|
+
case "staging":
|
|
35419
|
+
return (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan-staging", "agent");
|
|
35420
|
+
case "custom":
|
|
35421
|
+
return (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan-prod", "agent");
|
|
35422
|
+
default:
|
|
35423
|
+
return null;
|
|
35424
|
+
}
|
|
35425
|
+
}
|
|
35668
35426
|
var AGENT_CONFIG_KEYS = /* @__PURE__ */ new Map([
|
|
35669
35427
|
["apiUrl", "string"],
|
|
35670
35428
|
["wsUrl", "string"],
|
|
@@ -35742,9 +35500,13 @@ function resolveAgentConfigPath(input2) {
|
|
|
35742
35500
|
const profile = normalizeAgentEndpointProfile(
|
|
35743
35501
|
typeof input2?.profile === "string" ? input2.profile : input2?.profile ?? null
|
|
35744
35502
|
) ?? "production";
|
|
35745
|
-
|
|
35746
|
-
|
|
35747
|
-
|
|
35503
|
+
if (input2?.baseDir !== void 0) {
|
|
35504
|
+
return (0, import_node_path5.join)(input2.baseDir, resolveAgentConfigFileName(profile));
|
|
35505
|
+
}
|
|
35506
|
+
const isolatedBaseDir = profile === "production" ? null : resolveIsolatedAgentBaseDir(profile);
|
|
35507
|
+
if (isolatedBaseDir) return (0, import_node_path5.join)(isolatedBaseDir, "config.json");
|
|
35508
|
+
migrateLegacyAgentConfig({ profile });
|
|
35509
|
+
return (0, import_node_path5.join)(DEFAULT_AGENT_DIR, resolveAgentConfigFileName(profile));
|
|
35748
35510
|
}
|
|
35749
35511
|
function configExistsAtPath(configPath) {
|
|
35750
35512
|
return (0, import_node_fs5.existsSync)(configPath);
|
|
@@ -35760,13 +35522,22 @@ function explicitConfigPathFromArgs(args) {
|
|
|
35760
35522
|
const prefix = "--config-path=";
|
|
35761
35523
|
return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length).trim() || void 0;
|
|
35762
35524
|
}
|
|
35525
|
+
function hasExplicitProfileArg(args) {
|
|
35526
|
+
return args.some((arg) => arg === "--profile" || arg.startsWith("--profile="));
|
|
35527
|
+
}
|
|
35763
35528
|
function bindAgentConfigPathFromArgs(args) {
|
|
35764
35529
|
const argumentPath = explicitConfigPathFromArgs(args);
|
|
35765
35530
|
if (argumentPath) {
|
|
35766
35531
|
process.env.ALAN_AGENT_CONFIG_PATH = argumentPath;
|
|
35767
35532
|
return argumentPath;
|
|
35768
35533
|
}
|
|
35769
|
-
|
|
35534
|
+
if (hasExplicitProfileArg(args)) {
|
|
35535
|
+
const profile2 = resolveEndpointProfileFromArgs(args);
|
|
35536
|
+
const configPath2 = resolveAgentConfigPath({ profile: profile2 });
|
|
35537
|
+
process.env.ALAN_AGENT_CONFIG_PATH = configPath2;
|
|
35538
|
+
return configPath2;
|
|
35539
|
+
}
|
|
35540
|
+
const explicit = configuredConfigPathFromEnvironment();
|
|
35770
35541
|
if (explicit) return explicit;
|
|
35771
35542
|
const profile = resolveEndpointProfileFromArgs(args);
|
|
35772
35543
|
const configPath = resolveAgentConfigPath({ profile });
|
|
@@ -37182,16 +36953,6 @@ function isCodexTransientReconnectNotice(message) {
|
|
|
37182
36953
|
return false;
|
|
37183
36954
|
}
|
|
37184
36955
|
|
|
37185
|
-
// ../shared/dist/utils/agent-run-status.js
|
|
37186
|
-
var ACTIVE_AGENT_RUN_STATUSES = [
|
|
37187
|
-
"pending",
|
|
37188
|
-
"awaiting_agent",
|
|
37189
|
-
"awaiting_sandbox",
|
|
37190
|
-
"dispatched",
|
|
37191
|
-
"running"
|
|
37192
|
-
];
|
|
37193
|
-
var STOPPABLE_AGENT_RUN_STATUSES = [...ACTIVE_AGENT_RUN_STATUSES, "paused"];
|
|
37194
|
-
|
|
37195
36956
|
// ../shared/dist/agent/types.js
|
|
37196
36957
|
function resolveEffectiveBackendKind(backendKind) {
|
|
37197
36958
|
if (backendKind === "codex")
|
|
@@ -39162,6 +38923,8 @@ function classifyCliErrorDetailed(stderr, _exitCode, opts) {
|
|
|
39162
38923
|
"grok build usage balance"
|
|
39163
38924
|
) || has("payment required") && has("status 402"))
|
|
39164
38925
|
return specForErrorKind("usage_limit");
|
|
38926
|
+
if (has("creditserror", "no payment method")) return specForErrorKind("subscription_required");
|
|
38927
|
+
if (has("datapolicyerror", "requires explicit opt in")) return specForErrorKind("model_mismatch");
|
|
39165
38928
|
if (has("no chat found", "chat not found", "session not found", "could not resume"))
|
|
39166
38929
|
return specForErrorKind("resume_failed");
|
|
39167
38930
|
if (has("rate_limit", "rate limit") || /\b429\b/.test(haystack))
|
|
@@ -45744,6 +45507,20 @@ function classifyOpenCodeError(errorRecord, fallbackMessage) {
|
|
|
45744
45507
|
recoveryClass: "user_fixable"
|
|
45745
45508
|
};
|
|
45746
45509
|
}
|
|
45510
|
+
if (name === "CreditsError") {
|
|
45511
|
+
return {
|
|
45512
|
+
message: extracted || fallbackMessage,
|
|
45513
|
+
errorKind: "subscription_required",
|
|
45514
|
+
recoveryClass: "user_fixable"
|
|
45515
|
+
};
|
|
45516
|
+
}
|
|
45517
|
+
if (name === "DataPolicyError") {
|
|
45518
|
+
return {
|
|
45519
|
+
message: extracted || fallbackMessage,
|
|
45520
|
+
errorKind: "model_mismatch",
|
|
45521
|
+
recoveryClass: "user_fixable"
|
|
45522
|
+
};
|
|
45523
|
+
}
|
|
45747
45524
|
const message = extracted || fallbackMessage;
|
|
45748
45525
|
const detailed = classifyCliErrorDetailed(message, 1);
|
|
45749
45526
|
return { message, errorKind: detailed.errorKind, recoveryClass: detailed.recoveryClass };
|
|
@@ -49088,9 +48865,14 @@ function removeAlanOwnedLocalArtifacts() {
|
|
|
49088
48865
|
|
|
49089
48866
|
// src/provider-model-discovery.ts
|
|
49090
48867
|
var import_node_fs12 = require("fs");
|
|
48868
|
+
var import_node_os6 = require("os");
|
|
48869
|
+
var import_node_path11 = require("path");
|
|
49091
48870
|
var MODEL_DISCOVERY_TIMEOUT_MS = 8e3;
|
|
49092
48871
|
var ANTIGRAVITY_MODEL_DISCOVERY_TIMEOUT_MS = 12e3;
|
|
49093
48872
|
var OPENCODE_ZEN_MODEL_IDS = OPENCODE_ZEN_MODELS.map((model) => model.id);
|
|
48873
|
+
var OPENCODE_ZEN_STATIC_BILLING = new Map(
|
|
48874
|
+
OPENCODE_ZEN_MODELS.filter((model) => model.billing).map((model) => [model.id, model.billing])
|
|
48875
|
+
);
|
|
49094
48876
|
var CLAUDE_MODEL_ID_PATTERN = /claude-(?:sonnet|opus|haiku|fable)-[a-z0-9][a-z0-9-]*/g;
|
|
49095
48877
|
var CLAUDE_MODEL_ALIASES = ["sonnet", "opus", "haiku", "fable"];
|
|
49096
48878
|
var CLAUDE_MODEL_ALIAS_SET = new Set(CLAUDE_MODEL_ALIASES);
|
|
@@ -49162,7 +48944,7 @@ function extractCodexDiscoveredModelIdsFromDebugJson(value2) {
|
|
|
49162
48944
|
}
|
|
49163
48945
|
return [...new Set(ids)];
|
|
49164
48946
|
}
|
|
49165
|
-
var OPENCODE_MODEL_ID_LINE_PATTERN = /^[a-z0-9][\w.-]
|
|
48947
|
+
var OPENCODE_MODEL_ID_LINE_PATTERN = /^[a-z0-9][\w.-]*(?:\/[\w.-]+)+$/i;
|
|
49166
48948
|
function parseOpenCodeVerboseModelOutput(text) {
|
|
49167
48949
|
const entries = [];
|
|
49168
48950
|
const lines = text.split(/\r?\n/);
|
|
@@ -49350,7 +49132,190 @@ async function probeJsonOrTextModels(executable, env, argSets, options) {
|
|
|
49350
49132
|
}
|
|
49351
49133
|
return [];
|
|
49352
49134
|
}
|
|
49135
|
+
var OPENCODE_ZEN_MODELS_URL = "https://opencode.ai/zen/v1/models";
|
|
49136
|
+
var ZEN_ENTITLEMENT_TIMEOUT_MS = 5e3;
|
|
49137
|
+
var OPENCODE_ZEN_ID_PREFIX = "opencode/";
|
|
49138
|
+
function readOpenCodeZenCredential(env) {
|
|
49139
|
+
const direct = env.OPENCODE_API_KEY?.trim();
|
|
49140
|
+
if (direct) return direct;
|
|
49141
|
+
return readZenCredentialFromAuthDocument(readOpenCodeAuthDocument(env) ?? void 0);
|
|
49142
|
+
}
|
|
49143
|
+
function readOpenCodeAuthDocument(env) {
|
|
49144
|
+
const injected = env.OPENCODE_AUTH_CONTENT?.trim();
|
|
49145
|
+
if (injected) return injected;
|
|
49146
|
+
const dataHome = env.XDG_DATA_HOME?.trim() || (0, import_node_path11.join)((0, import_node_os6.homedir)(), ".local", "share");
|
|
49147
|
+
try {
|
|
49148
|
+
return (0, import_node_fs12.readFileSync)((0, import_node_path11.join)(dataHome, "opencode", "auth.json"), "utf8");
|
|
49149
|
+
} catch {
|
|
49150
|
+
return null;
|
|
49151
|
+
}
|
|
49152
|
+
}
|
|
49153
|
+
var OPENCODE_PROVIDER_ENV_KEYS = [
|
|
49154
|
+
["OPENROUTER_API_KEY", "openrouter"],
|
|
49155
|
+
["ANTHROPIC_API_KEY", "anthropic"],
|
|
49156
|
+
["OPENAI_API_KEY", "openai"],
|
|
49157
|
+
["GEMINI_API_KEY", "google"],
|
|
49158
|
+
["GOOGLE_GENERATIVE_AI_API_KEY", "google"],
|
|
49159
|
+
["XAI_API_KEY", "xai"],
|
|
49160
|
+
["GROQ_API_KEY", "groq"],
|
|
49161
|
+
["MISTRAL_API_KEY", "mistral"],
|
|
49162
|
+
["DEEPSEEK_API_KEY", "deepseek"]
|
|
49163
|
+
];
|
|
49164
|
+
function readConfiguredOpenCodeProviders(env) {
|
|
49165
|
+
const configured = /* @__PURE__ */ new Set(["opencode", "opencode-go"]);
|
|
49166
|
+
const document2 = readOpenCodeAuthDocument(env);
|
|
49167
|
+
if (document2) {
|
|
49168
|
+
try {
|
|
49169
|
+
const parsed = JSON.parse(document2);
|
|
49170
|
+
if (parsed && typeof parsed === "object") {
|
|
49171
|
+
for (const providerId of Object.keys(parsed)) configured.add(providerId);
|
|
49172
|
+
}
|
|
49173
|
+
} catch {
|
|
49174
|
+
}
|
|
49175
|
+
}
|
|
49176
|
+
for (const [envKey, namespace] of OPENCODE_PROVIDER_ENV_KEYS) {
|
|
49177
|
+
if (env[envKey]?.trim()) configured.add(namespace);
|
|
49178
|
+
}
|
|
49179
|
+
return configured;
|
|
49180
|
+
}
|
|
49181
|
+
function readZenCredentialFromAuthDocument(content) {
|
|
49182
|
+
const trimmed = content?.trim();
|
|
49183
|
+
if (!trimmed) return null;
|
|
49184
|
+
try {
|
|
49185
|
+
const entry = JSON.parse(trimmed).opencode;
|
|
49186
|
+
if (!entry || typeof entry !== "object") return null;
|
|
49187
|
+
const { key, access: access2 } = entry;
|
|
49188
|
+
for (const candidate of [key, access2]) {
|
|
49189
|
+
if (typeof candidate === "string" && candidate.trim()) return candidate.trim();
|
|
49190
|
+
}
|
|
49191
|
+
return null;
|
|
49192
|
+
} catch {
|
|
49193
|
+
return null;
|
|
49194
|
+
}
|
|
49195
|
+
}
|
|
49196
|
+
async function fetchZenEntitledModelIds(credential) {
|
|
49197
|
+
try {
|
|
49198
|
+
const response = await fetch(OPENCODE_ZEN_MODELS_URL, {
|
|
49199
|
+
headers: credential ? { Authorization: `Bearer ${credential}` } : {},
|
|
49200
|
+
signal: AbortSignal.timeout(ZEN_ENTITLEMENT_TIMEOUT_MS)
|
|
49201
|
+
});
|
|
49202
|
+
if (!response.ok) return null;
|
|
49203
|
+
const data = (await response.json())?.data;
|
|
49204
|
+
if (!Array.isArray(data)) return null;
|
|
49205
|
+
const ids = data.map((entry) => entry?.id).filter((id) => typeof id === "string" && id.length > 0);
|
|
49206
|
+
return ids.length > 0 ? new Set(ids) : null;
|
|
49207
|
+
} catch {
|
|
49208
|
+
return null;
|
|
49209
|
+
}
|
|
49210
|
+
}
|
|
49211
|
+
function applyZenEntitlement(discovery, entitled) {
|
|
49212
|
+
const zenId = (id) => `${OPENCODE_ZEN_ID_PREFIX}${id}`;
|
|
49213
|
+
const kept = discovery.models.filter(
|
|
49214
|
+
(id) => !id.startsWith(OPENCODE_ZEN_ID_PREFIX) || entitled.has(id.slice(OPENCODE_ZEN_ID_PREFIX.length))
|
|
49215
|
+
);
|
|
49216
|
+
const keptSet = new Set(kept);
|
|
49217
|
+
const scannedSet = new Set(discovery.models);
|
|
49218
|
+
const unscannedEntitled = [...entitled].map(zenId);
|
|
49219
|
+
return {
|
|
49220
|
+
...discovery,
|
|
49221
|
+
models: [...kept, ...unscannedEntitled.filter((id) => !keptSet.has(id))],
|
|
49222
|
+
catalogModels: [
|
|
49223
|
+
...discovery.catalogModels ?? discovery.models,
|
|
49224
|
+
...unscannedEntitled.filter((id) => !scannedSet.has(id))
|
|
49225
|
+
]
|
|
49226
|
+
};
|
|
49227
|
+
}
|
|
49228
|
+
var OPENCODE_CATALOGUE_CACHE_SEGMENTS = ["opencode", "models.json"];
|
|
49229
|
+
var OPENCODE_CACHE_PROVIDER_KEYS = ["opencode", "opencode-go"];
|
|
49230
|
+
function readOpenCodeCatalogueCache(env) {
|
|
49231
|
+
const cacheHome = env.XDG_CACHE_HOME?.trim() || (0, import_node_path11.join)((0, import_node_os6.homedir)(), ".cache");
|
|
49232
|
+
let parsed;
|
|
49233
|
+
try {
|
|
49234
|
+
parsed = JSON.parse(
|
|
49235
|
+
(0, import_node_fs12.readFileSync)((0, import_node_path11.join)(cacheHome, ...OPENCODE_CATALOGUE_CACHE_SEGMENTS), "utf8")
|
|
49236
|
+
);
|
|
49237
|
+
} catch {
|
|
49238
|
+
return null;
|
|
49239
|
+
}
|
|
49240
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
49241
|
+
const variants = {};
|
|
49242
|
+
const billing = {};
|
|
49243
|
+
const deprecated = /* @__PURE__ */ new Set();
|
|
49244
|
+
for (const providerKey of OPENCODE_CACHE_PROVIDER_KEYS) {
|
|
49245
|
+
const models = parsed[providerKey]?.models;
|
|
49246
|
+
if (!models || typeof models !== "object") continue;
|
|
49247
|
+
for (const [modelId, entry] of Object.entries(models)) {
|
|
49248
|
+
if (!entry || typeof entry !== "object") continue;
|
|
49249
|
+
const id = `${providerKey}/${modelId}`;
|
|
49250
|
+
const record2 = entry;
|
|
49251
|
+
if (record2.status === "deprecated") deprecated.add(id);
|
|
49252
|
+
const options = Array.isArray(record2.reasoning_options) ? record2.reasoning_options : [];
|
|
49253
|
+
const effort = options.find(
|
|
49254
|
+
(option2) => option2?.type === "effort"
|
|
49255
|
+
);
|
|
49256
|
+
const values = Array.isArray(effort?.values) ? effort.values.filter((value2) => typeof value2 === "string") : [];
|
|
49257
|
+
if (values.length > 0) variants[id] = values;
|
|
49258
|
+
const cost = record2.cost;
|
|
49259
|
+
if (typeof cost?.input === "number" && typeof cost?.output === "number") {
|
|
49260
|
+
billing[id] = cost.input === 0 && cost.output === 0 ? "free" : "paid";
|
|
49261
|
+
}
|
|
49262
|
+
}
|
|
49263
|
+
}
|
|
49264
|
+
return Object.keys(variants).length > 0 || Object.keys(billing).length > 0 ? { variants, billing, deprecated } : null;
|
|
49265
|
+
}
|
|
49266
|
+
function hydrateOpenCodeMetadata(discovery, cache2) {
|
|
49267
|
+
const ids = /* @__PURE__ */ new Set([...discovery.models, ...discovery.catalogModels ?? []]);
|
|
49268
|
+
const modelVariants = { ...discovery.modelVariants };
|
|
49269
|
+
const modelBilling = { ...discovery.modelBilling };
|
|
49270
|
+
for (const id of ids) {
|
|
49271
|
+
if (!Object.hasOwn(modelVariants, id) && cache2.variants[id]) {
|
|
49272
|
+
modelVariants[id] = cache2.variants[id];
|
|
49273
|
+
}
|
|
49274
|
+
if (!Object.hasOwn(modelBilling, id) && cache2.billing[id]) {
|
|
49275
|
+
modelBilling[id] = cache2.billing[id];
|
|
49276
|
+
}
|
|
49277
|
+
}
|
|
49278
|
+
return {
|
|
49279
|
+
...discovery,
|
|
49280
|
+
...Object.keys(modelVariants).length > 0 ? { modelVariants } : {},
|
|
49281
|
+
...Object.keys(modelBilling).length > 0 ? { modelBilling } : {}
|
|
49282
|
+
};
|
|
49283
|
+
}
|
|
49353
49284
|
async function discoverOpenCodeModels(executable, env) {
|
|
49285
|
+
const credential = readOpenCodeZenCredential(env);
|
|
49286
|
+
const [rawScan, entitled] = await Promise.all([
|
|
49287
|
+
scanOpenCodeModels(executable, env),
|
|
49288
|
+
fetchZenEntitledModelIds(credential)
|
|
49289
|
+
]);
|
|
49290
|
+
const configured = readConfiguredOpenCodeProviders(env);
|
|
49291
|
+
const inConfigured = (id) => {
|
|
49292
|
+
const slash = id.indexOf("/");
|
|
49293
|
+
return slash > 0 && configured.has(id.slice(0, slash));
|
|
49294
|
+
};
|
|
49295
|
+
const scanned = {
|
|
49296
|
+
...rawScan,
|
|
49297
|
+
models: rawScan.models.filter(inConfigured),
|
|
49298
|
+
...rawScan.catalogModels ? { catalogModels: rawScan.catalogModels.filter(inConfigured) } : {}
|
|
49299
|
+
};
|
|
49300
|
+
const filtered = entitled ? applyZenEntitlement(scanned, entitled) : scanned;
|
|
49301
|
+
const cache2 = readOpenCodeCatalogueCache(env);
|
|
49302
|
+
const hydrated = cache2 ? hydrateOpenCodeMetadata(filtered, cache2) : filtered;
|
|
49303
|
+
const keyEntitled = credential && entitled ? entitled : null;
|
|
49304
|
+
const withoutDeprecated = cache2 ? hydrated.models.filter(
|
|
49305
|
+
(id) => !cache2.deprecated.has(id) || keyEntitled !== null && id.startsWith(OPENCODE_ZEN_ID_PREFIX) && keyEntitled.has(id.slice(OPENCODE_ZEN_ID_PREFIX.length))
|
|
49306
|
+
) : hydrated.models;
|
|
49307
|
+
return {
|
|
49308
|
+
...hydrated,
|
|
49309
|
+
models: credential ? withoutDeprecated : filterZenToFreeModels(withoutDeprecated, hydrated.modelBilling)
|
|
49310
|
+
};
|
|
49311
|
+
}
|
|
49312
|
+
function filterZenToFreeModels(models, billing) {
|
|
49313
|
+
return models.filter((id) => {
|
|
49314
|
+
if (!id.startsWith("opencode/") && !id.startsWith("opencode-go/")) return true;
|
|
49315
|
+
return (billing?.[id] ?? OPENCODE_ZEN_STATIC_BILLING.get(id)) === "free";
|
|
49316
|
+
});
|
|
49317
|
+
}
|
|
49318
|
+
async function scanOpenCodeModels(executable, env) {
|
|
49354
49319
|
const verbose = await runCliProbeAsync(
|
|
49355
49320
|
executable,
|
|
49356
49321
|
withModelProbeEnv(env),
|
|
@@ -49613,6 +49578,7 @@ function discoverCapabilities() {
|
|
|
49613
49578
|
available,
|
|
49614
49579
|
...version2 ? { version: version2 } : {},
|
|
49615
49580
|
models: modelDiscovery?.models ?? [],
|
|
49581
|
+
...modelDiscovery?.catalogModels ? { catalogModels: modelDiscovery.catalogModels } : {},
|
|
49616
49582
|
...modelDiscovery?.modelVariants ? { modelVariants: modelDiscovery.modelVariants } : {},
|
|
49617
49583
|
...modelDiscovery?.modelBilling ? { modelBilling: modelDiscovery.modelBilling } : {},
|
|
49618
49584
|
lastCheckedAt: now,
|
|
@@ -49860,8 +49826,8 @@ function scheduleRuntimeModelScan(getBaseMetadata, options) {
|
|
|
49860
49826
|
var import_node_crypto16 = require("crypto");
|
|
49861
49827
|
var import_node_fs20 = require("fs");
|
|
49862
49828
|
var import_node_http = __toESM(require("http"), 1);
|
|
49863
|
-
var
|
|
49864
|
-
var
|
|
49829
|
+
var import_node_os11 = require("os");
|
|
49830
|
+
var import_node_path23 = require("path");
|
|
49865
49831
|
|
|
49866
49832
|
// ../../node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.node.js
|
|
49867
49833
|
var XMLHttpRequestModule = __toESM(require_XMLHttpRequest(), 1);
|
|
@@ -53421,8 +53387,8 @@ Object.assign(lookup, {
|
|
|
53421
53387
|
var import_node_child_process7 = require("child_process");
|
|
53422
53388
|
var import_node_crypto5 = require("crypto");
|
|
53423
53389
|
var import_node_fs13 = require("fs");
|
|
53424
|
-
var
|
|
53425
|
-
var
|
|
53390
|
+
var import_node_os7 = require("os");
|
|
53391
|
+
var import_node_path12 = require("path");
|
|
53426
53392
|
var import_node_url = require("url");
|
|
53427
53393
|
var BINDING_SWITCH_GIT_METHODS = [
|
|
53428
53394
|
"git.status",
|
|
@@ -53474,8 +53440,8 @@ async function waitForCheckpointTestBarrier() {
|
|
|
53474
53440
|
const barrierDir = process.env.NODE_ENV === "test" ? process.env.ALAN_TEST_GIT_CHECKPOINT_BARRIER_DIR : void 0;
|
|
53475
53441
|
if (!barrierDir) return;
|
|
53476
53442
|
(0, import_node_fs13.mkdirSync)(barrierDir, { recursive: true });
|
|
53477
|
-
const readyPath = (0,
|
|
53478
|
-
const releasePath = (0,
|
|
53443
|
+
const readyPath = (0, import_node_path12.join)(barrierDir, "ready");
|
|
53444
|
+
const releasePath = (0, import_node_path12.join)(barrierDir, "release");
|
|
53479
53445
|
(0, import_node_fs13.writeFileSync)(readyPath, "ready\n");
|
|
53480
53446
|
const deadline = Date.now() + 5e3;
|
|
53481
53447
|
while (!(0, import_node_fs13.existsSync)(releasePath)) {
|
|
@@ -53492,8 +53458,8 @@ async function waitForCheckpointFinalizeTestBarrier() {
|
|
|
53492
53458
|
const barrierDir = process.env.NODE_ENV === "test" ? process.env.ALAN_TEST_GIT_CHECKPOINT_FINALIZE_BARRIER_DIR : void 0;
|
|
53493
53459
|
if (!barrierDir) return;
|
|
53494
53460
|
(0, import_node_fs13.mkdirSync)(barrierDir, { recursive: true });
|
|
53495
|
-
const readyPath = (0,
|
|
53496
|
-
const releasePath = (0,
|
|
53461
|
+
const readyPath = (0, import_node_path12.join)(barrierDir, "ready");
|
|
53462
|
+
const releasePath = (0, import_node_path12.join)(barrierDir, "release");
|
|
53497
53463
|
(0, import_node_fs13.writeFileSync)(readyPath, "ready\n");
|
|
53498
53464
|
const deadline = Date.now() + 5e3;
|
|
53499
53465
|
while (!(0, import_node_fs13.existsSync)(releasePath)) {
|
|
@@ -53634,7 +53600,7 @@ function acquireCheckpointRepositoryLocks(repoRoot) {
|
|
|
53634
53600
|
"checkpoint_lock_unavailable"
|
|
53635
53601
|
);
|
|
53636
53602
|
const locks = {
|
|
53637
|
-
headLockPath: (0,
|
|
53603
|
+
headLockPath: (0, import_node_path12.join)(gitDir, "HEAD.lock"),
|
|
53638
53604
|
headLockHeld: false,
|
|
53639
53605
|
indexLockPath: `${indexPath}.lock`,
|
|
53640
53606
|
indexLockHeld: false,
|
|
@@ -53676,8 +53642,8 @@ function assertCheckpointHead(repoRoot, expectedRef, expectedHeadSha) {
|
|
|
53676
53642
|
}
|
|
53677
53643
|
}
|
|
53678
53644
|
function createCheckpointIndexBaseline(repoRoot, checkpointSha) {
|
|
53679
|
-
const tempDir = (0, import_node_fs13.mkdtempSync)((0,
|
|
53680
|
-
const indexPath = (0,
|
|
53645
|
+
const tempDir = (0, import_node_fs13.mkdtempSync)((0, import_node_path12.join)((0, import_node_os7.tmpdir)(), "alan-checkpoint-index-"));
|
|
53646
|
+
const indexPath = (0, import_node_path12.join)(tempDir, "index");
|
|
53681
53647
|
try {
|
|
53682
53648
|
runGitWithOptions(
|
|
53683
53649
|
repoRoot,
|
|
@@ -53738,7 +53704,7 @@ function commonRequest(params) {
|
|
|
53738
53704
|
return {
|
|
53739
53705
|
switchId: requiredString2(params, "switchId"),
|
|
53740
53706
|
repoKey: requiredString2(params, "repoKey"),
|
|
53741
|
-
repoPath: (0,
|
|
53707
|
+
repoPath: (0, import_node_path12.resolve)(requiredString2(params, "repoPath"))
|
|
53742
53708
|
};
|
|
53743
53709
|
}
|
|
53744
53710
|
function assertCommitSha(sha, key) {
|
|
@@ -53772,8 +53738,8 @@ function canonicalRemoteUrl(repoRoot, value2) {
|
|
|
53772
53738
|
}
|
|
53773
53739
|
const scpStyle = trimmed.match(/^([^/@:\s]+)@([^/:\s]+):(.+)$/);
|
|
53774
53740
|
const urlValue = scpStyle ? `ssh://${scpStyle[1]}@${scpStyle[2]}/${scpStyle[3]}` : trimmed;
|
|
53775
|
-
if ((0,
|
|
53776
|
-
const absolute = (0,
|
|
53741
|
+
if ((0, import_node_path12.isAbsolute)(urlValue) || urlValue.startsWith("./") || urlValue.startsWith("../")) {
|
|
53742
|
+
const absolute = (0, import_node_path12.isAbsolute)(urlValue) ? urlValue : (0, import_node_path12.resolve)(repoRoot, urlValue);
|
|
53777
53743
|
return `file://${canonicalPathWithMissingTail(absolute).replace(/\/+$/, "").replace(/\.git$/, "")}`;
|
|
53778
53744
|
}
|
|
53779
53745
|
let parsed;
|
|
@@ -53839,24 +53805,24 @@ function inspectedRemoteUrl(repoRoot, params) {
|
|
|
53839
53805
|
return urls[0];
|
|
53840
53806
|
}
|
|
53841
53807
|
function isPathContained2(childPath, parentPath) {
|
|
53842
|
-
const rel = (0,
|
|
53843
|
-
return rel === "" || !(0,
|
|
53808
|
+
const rel = (0, import_node_path12.relative)((0, import_node_path12.resolve)(parentPath), (0, import_node_path12.resolve)(childPath));
|
|
53809
|
+
return rel === "" || !(0, import_node_path12.isAbsolute)(rel) && rel !== ".." && !rel.startsWith(`..${import_node_path12.sep}`);
|
|
53844
53810
|
}
|
|
53845
53811
|
function canonicalPathWithMissingTail(path2) {
|
|
53846
53812
|
const missingSegments = [];
|
|
53847
|
-
let cursor = (0,
|
|
53813
|
+
let cursor = (0, import_node_path12.resolve)(path2);
|
|
53848
53814
|
while (!(0, import_node_fs13.existsSync)(cursor)) {
|
|
53849
|
-
const parent = (0,
|
|
53815
|
+
const parent = (0, import_node_path12.dirname)(cursor);
|
|
53850
53816
|
if (parent === cursor) {
|
|
53851
53817
|
throw new BindingSwitchGitError(
|
|
53852
53818
|
"path_canonicalization_failed",
|
|
53853
53819
|
"The selected path has no existing canonical ancestor"
|
|
53854
53820
|
);
|
|
53855
53821
|
}
|
|
53856
|
-
missingSegments.unshift((0,
|
|
53822
|
+
missingSegments.unshift((0, import_node_path12.basename)(cursor));
|
|
53857
53823
|
cursor = parent;
|
|
53858
53824
|
}
|
|
53859
|
-
return (0,
|
|
53825
|
+
return (0, import_node_path12.join)(import_node_fs13.realpathSync.native(cursor), ...missingSegments);
|
|
53860
53826
|
}
|
|
53861
53827
|
function assertCanonicalPathContained(childPath, parentPath, code, message) {
|
|
53862
53828
|
if (!isPathContained2(
|
|
@@ -53867,7 +53833,7 @@ function assertCanonicalPathContained(childPath, parentPath, code, message) {
|
|
|
53867
53833
|
}
|
|
53868
53834
|
}
|
|
53869
53835
|
function alanWorktreeRoot(projectRoot) {
|
|
53870
|
-
return (0,
|
|
53836
|
+
return (0, import_node_path12.join)((0, import_node_path12.dirname)(projectRoot), `${(0, import_node_path12.basename)(projectRoot)}-alan-worktrees`);
|
|
53871
53837
|
}
|
|
53872
53838
|
function resolveRepositoryRoot(requestedPath) {
|
|
53873
53839
|
if (!(0, import_node_fs13.existsSync)(requestedPath)) {
|
|
@@ -53883,7 +53849,7 @@ function resolveRepositoryRoot(requestedPath) {
|
|
|
53883
53849
|
"The selected folder is not inside a Git repository"
|
|
53884
53850
|
);
|
|
53885
53851
|
}
|
|
53886
|
-
return import_node_fs13.realpathSync.native((0,
|
|
53852
|
+
return import_node_fs13.realpathSync.native((0, import_node_path12.resolve)(root.stdout.trim()));
|
|
53887
53853
|
}
|
|
53888
53854
|
function listWorktrees(repoRoot) {
|
|
53889
53855
|
return runGit(repoRoot, ["worktree", "list", "--porcelain"]).split("\n\n").flatMap((entry) => {
|
|
@@ -53902,7 +53868,7 @@ function resolveAuthorizedRepository(params, requireTrustedContext = false) {
|
|
|
53902
53868
|
const { repoPath } = commonRequest(params);
|
|
53903
53869
|
const repoRoot = resolveRepositoryRoot(repoPath);
|
|
53904
53870
|
const expectedRepoRoot = requireTrustedContext ? requiredString2(params, "expectedRepoRoot") : optionalString(params, "expectedRepoRoot");
|
|
53905
|
-
if (expectedRepoRoot && resolveRepositoryRoot((0,
|
|
53871
|
+
if (expectedRepoRoot && resolveRepositoryRoot((0, import_node_path12.resolve)(expectedRepoRoot)) !== repoRoot) {
|
|
53906
53872
|
throw new BindingSwitchGitError(
|
|
53907
53873
|
"repository_path_changed",
|
|
53908
53874
|
"The selected path now resolves to a different Git repository"
|
|
@@ -53910,7 +53876,7 @@ function resolveAuthorizedRepository(params, requireTrustedContext = false) {
|
|
|
53910
53876
|
}
|
|
53911
53877
|
const projectPath = requireTrustedContext ? requiredString2(params, "projectPath") : optionalString(params, "projectPath");
|
|
53912
53878
|
if (!projectPath) return repoRoot;
|
|
53913
|
-
const projectRoot = resolveRepositoryRoot((0,
|
|
53879
|
+
const projectRoot = resolveRepositoryRoot((0, import_node_path12.resolve)(projectPath));
|
|
53914
53880
|
const registrations = listWorktrees(projectRoot);
|
|
53915
53881
|
const registered = registrations.find(({ path: path2 }) => path2 === repoRoot);
|
|
53916
53882
|
if (!registered) {
|
|
@@ -53946,8 +53912,8 @@ function updateLengthPrefixed(hash2, value2) {
|
|
|
53946
53912
|
hash2.update("\0");
|
|
53947
53913
|
}
|
|
53948
53914
|
function proposedTreeSha(repoRoot, headSha) {
|
|
53949
|
-
const tempDir = (0, import_node_fs13.mkdtempSync)((0,
|
|
53950
|
-
const indexPath = (0,
|
|
53915
|
+
const tempDir = (0, import_node_fs13.mkdtempSync)((0, import_node_path12.join)((0, import_node_os7.tmpdir)(), "alan-switch-index-"));
|
|
53916
|
+
const indexPath = (0, import_node_path12.join)(tempDir, "index");
|
|
53951
53917
|
const options = { env: { GIT_INDEX_FILE: indexPath } };
|
|
53952
53918
|
try {
|
|
53953
53919
|
if (headSha) {
|
|
@@ -54409,12 +54375,12 @@ async function prepareWorktree(params) {
|
|
|
54409
54375
|
"Worktree preparation requires the Project's main checkout"
|
|
54410
54376
|
);
|
|
54411
54377
|
}
|
|
54412
|
-
const worktreePath = (0,
|
|
54378
|
+
const worktreePath = (0, import_node_path12.resolve)(requiredString2(params, "worktreePath"));
|
|
54413
54379
|
const managedRoot = alanWorktreeRoot(projectRoot);
|
|
54414
54380
|
const pathError = "The destination worktree path is outside the Alan-managed worktree directory";
|
|
54415
|
-
const intendedManagedRoot = (0,
|
|
54416
|
-
import_node_fs13.realpathSync.native((0,
|
|
54417
|
-
(0,
|
|
54381
|
+
const intendedManagedRoot = (0, import_node_path12.join)(
|
|
54382
|
+
import_node_fs13.realpathSync.native((0, import_node_path12.dirname)(managedRoot)),
|
|
54383
|
+
(0, import_node_path12.basename)(managedRoot)
|
|
54418
54384
|
);
|
|
54419
54385
|
if (canonicalPathWithMissingTail(managedRoot) !== intendedManagedRoot) {
|
|
54420
54386
|
throw new BindingSwitchGitError("worktree_path_not_authorized", pathError);
|
|
@@ -54474,7 +54440,7 @@ async function prepareWorktree(params) {
|
|
|
54474
54440
|
);
|
|
54475
54441
|
}
|
|
54476
54442
|
}
|
|
54477
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
54443
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.dirname)(worktreePath), { recursive: true });
|
|
54478
54444
|
if (branchExists) {
|
|
54479
54445
|
runGit(repoRoot, ["worktree", "add", worktreePath, branch], "worktree_prepare_failed");
|
|
54480
54446
|
const currentHead = runGit(worktreePath, ["rev-parse", "HEAD"]);
|
|
@@ -54553,11 +54519,11 @@ async function executeBindingSwitchGitRpc(method, params) {
|
|
|
54553
54519
|
|
|
54554
54520
|
// src/daemon-execute.ts
|
|
54555
54521
|
var import_node_fs15 = require("fs");
|
|
54556
|
-
var
|
|
54522
|
+
var import_node_path14 = require("path");
|
|
54557
54523
|
|
|
54558
54524
|
// src/cli-ensure-install.ts
|
|
54559
54525
|
var import_node_child_process8 = require("child_process");
|
|
54560
|
-
var
|
|
54526
|
+
var import_node_os8 = require("os");
|
|
54561
54527
|
var CLI_RUNTIME_VERSIONS_ENV = "ALAN_CLI_RUNTIME_VERSIONS";
|
|
54562
54528
|
var INSTALLABLE_PROVIDER_PACKAGES = {
|
|
54563
54529
|
claude_cli: { npmPackage: "@anthropic-ai/claude-code", command: "claude", label: "Claude Code" },
|
|
@@ -54585,7 +54551,7 @@ function versionPolicy(npmPackage) {
|
|
|
54585
54551
|
}
|
|
54586
54552
|
function runNpmInstall(installSpec, env, timeoutMs) {
|
|
54587
54553
|
return new Promise((resolve15) => {
|
|
54588
|
-
const isWin = (0,
|
|
54554
|
+
const isWin = (0, import_node_os8.platform)() === "win32";
|
|
54589
54555
|
let child;
|
|
54590
54556
|
try {
|
|
54591
54557
|
child = (0, import_node_child_process8.spawn)("npm", ["install", "-g", installSpec], {
|
|
@@ -54655,13 +54621,13 @@ function ensureProviderCliInstalled(backendKind, options) {
|
|
|
54655
54621
|
}
|
|
54656
54622
|
|
|
54657
54623
|
// src/core-agent.ts
|
|
54658
|
-
var
|
|
54624
|
+
var import_node_os10 = require("os");
|
|
54659
54625
|
|
|
54660
54626
|
// src/mcp-registration.ts
|
|
54661
54627
|
var import_node_crypto6 = require("crypto");
|
|
54662
54628
|
var import_node_fs14 = require("fs");
|
|
54663
|
-
var
|
|
54664
|
-
var
|
|
54629
|
+
var import_node_os9 = require("os");
|
|
54630
|
+
var import_node_path13 = require("path");
|
|
54665
54631
|
|
|
54666
54632
|
// ../../node_modules/smol-toml/dist/error.js
|
|
54667
54633
|
function getLineColFromPtr(string4, ptr) {
|
|
@@ -55602,7 +55568,7 @@ var inspectAlanMcpThroughProviderCli = async (backendKind, expectedUrl, home) =>
|
|
|
55602
55568
|
return result;
|
|
55603
55569
|
};
|
|
55604
55570
|
async function waitForConfigLock(lockPath) {
|
|
55605
|
-
(0, import_node_fs14.mkdirSync)((0,
|
|
55571
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path13.dirname)(lockPath), { recursive: true });
|
|
55606
55572
|
const startedAt = Date.now();
|
|
55607
55573
|
while (true) {
|
|
55608
55574
|
try {
|
|
@@ -55683,8 +55649,8 @@ function atomicWriteManagedConfig(path2, content) {
|
|
|
55683
55649
|
(0, import_node_fs14.rmSync)(pendingPath, { force: true });
|
|
55684
55650
|
}
|
|
55685
55651
|
}
|
|
55686
|
-
async function configureAntigravityApiKeyMode(home = (0,
|
|
55687
|
-
const path2 = (0,
|
|
55652
|
+
async function configureAntigravityApiKeyMode(home = (0, import_node_os9.homedir)()) {
|
|
55653
|
+
const path2 = (0, import_node_path13.join)(home, ".gemini", "antigravity-cli", "settings.json");
|
|
55688
55654
|
const releaseLock = await waitForConfigLock(`${path2}.alan-lock`);
|
|
55689
55655
|
try {
|
|
55690
55656
|
const existingContent = (0, import_node_fs14.existsSync)(path2) ? (0, import_node_fs14.readFileSync)(path2, "utf8") : "";
|
|
@@ -55697,13 +55663,13 @@ async function configureAntigravityApiKeyMode(home = (0, import_node_os8.homedir
|
|
|
55697
55663
|
releaseLock();
|
|
55698
55664
|
}
|
|
55699
55665
|
}
|
|
55700
|
-
async function ensureAlanMcpRegistered(backendKind, registration, home = (0,
|
|
55666
|
+
async function ensureAlanMcpRegistered(backendKind, registration, home = (0, import_node_os9.homedir)(), inspectCli = inspectAlanMcpThroughProviderCli) {
|
|
55701
55667
|
try {
|
|
55702
55668
|
const mcpServers = buildAlanMcpServers(registration);
|
|
55703
55669
|
const files = alanMcpConfigFilesForBackend(backendKind, mcpServers, home);
|
|
55704
55670
|
const paths = [];
|
|
55705
55671
|
for (const file2 of files) {
|
|
55706
|
-
(0, import_node_fs14.mkdirSync)((0,
|
|
55672
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path13.dirname)(file2.path), { recursive: true });
|
|
55707
55673
|
const releaseLock = await waitForConfigLock(`${file2.path}.alan-lock`);
|
|
55708
55674
|
try {
|
|
55709
55675
|
const current = (0, import_node_fs14.existsSync)(file2.path) ? (0, import_node_fs14.readFileSync)(file2.path, "utf8") : null;
|
|
@@ -55768,7 +55734,7 @@ async function ensureAlanMcpRegistered(backendKind, registration, home = (0, imp
|
|
|
55768
55734
|
return { ok: false, paths: [], error: err instanceof Error ? err.message : String(err) };
|
|
55769
55735
|
}
|
|
55770
55736
|
}
|
|
55771
|
-
async function restoreStaticAlanMcp(backendKind, apiUrl, home = (0,
|
|
55737
|
+
async function restoreStaticAlanMcp(backendKind, apiUrl, home = (0, import_node_os9.homedir)()) {
|
|
55772
55738
|
let url3;
|
|
55773
55739
|
try {
|
|
55774
55740
|
url3 = new URL("/mcp", apiUrl).toString();
|
|
@@ -55784,7 +55750,7 @@ async function restoreStaticAlanMcp(backendKind, apiUrl, home = (0, import_node_
|
|
|
55784
55750
|
verification: { method: "file" }
|
|
55785
55751
|
}));
|
|
55786
55752
|
}
|
|
55787
|
-
async function verifyAlanMcpRegistered(backendKind, home = (0,
|
|
55753
|
+
async function verifyAlanMcpRegistered(backendKind, home = (0, import_node_os9.homedir)(), inspectCli = inspectAlanMcpThroughProviderCli) {
|
|
55788
55754
|
const files = alanMcpConfigFilesForBackend(backendKind, {}, home);
|
|
55789
55755
|
const missing = files.map((f) => f.path).filter((p) => !(0, import_node_fs14.existsSync)(p));
|
|
55790
55756
|
const presentEntries = files.map((file2) => ({
|
|
@@ -56096,7 +56062,7 @@ var CoreAgent = class _CoreAgent extends BaseMachineAgent {
|
|
|
56096
56062
|
if (backendKind === "antigravity_cli" && augmented.GEMINI_API_KEY?.trim()) {
|
|
56097
56063
|
await configureAntigravityApiKeyMode(augmented.HOME ?? augmented.USERPROFILE);
|
|
56098
56064
|
}
|
|
56099
|
-
if ((0,
|
|
56065
|
+
if ((0, import_node_os10.platform)() !== "win32") {
|
|
56100
56066
|
const home = augmented.HOME ?? "/home/user";
|
|
56101
56067
|
const extraPaths = [`${home}/.local/node/bin`, `${home}/.local/bin`];
|
|
56102
56068
|
const separator = ":";
|
|
@@ -60269,9 +60235,9 @@ function buildMcpParamHeaders(declarations, args) {
|
|
|
60269
60235
|
for (const decl of declarations) {
|
|
60270
60236
|
const raw = valueAtPath(args, decl.path);
|
|
60271
60237
|
if (raw === void 0 || raw === null) continue;
|
|
60272
|
-
const
|
|
60273
|
-
if (
|
|
60274
|
-
out[`${MCP_PARAM_HEADER_PREFIX}${decl.headerName}`] = encodeMcpParamValue(
|
|
60238
|
+
const stringValue2 = mcpParamPrimitiveToString(raw);
|
|
60239
|
+
if (stringValue2 === void 0) continue;
|
|
60240
|
+
out[`${MCP_PARAM_HEADER_PREFIX}${decl.headerName}`] = encodeMcpParamValue(stringValue2);
|
|
60275
60241
|
}
|
|
60276
60242
|
return out;
|
|
60277
60243
|
}
|
|
@@ -73145,24 +73111,24 @@ async function handleAgentExecute(ctx, payload) {
|
|
|
73145
73111
|
let workspaceReadiness = inspectWorkspaceReadiness(workspaceRequired ? cwd : void 0);
|
|
73146
73112
|
const expectedRepoUrls = [
|
|
73147
73113
|
...(payload.repoLocalPaths ?? []).filter(
|
|
73148
|
-
(repo) => explicitWorkspacePath ? (0,
|
|
73114
|
+
(repo) => explicitWorkspacePath ? (0, import_node_path14.resolve)(repo.localPath) === (0, import_node_path14.resolve)(explicitWorkspacePath) : false
|
|
73149
73115
|
).map((repo) => repo.repoUrl),
|
|
73150
73116
|
...payload.localRepoUrls ?? []
|
|
73151
73117
|
];
|
|
73152
73118
|
if (workspaceReadiness.code === "workspace_missing" && explicitWorkspacePath && !payload.worktreeInfo) {
|
|
73153
|
-
const previousPath = (0,
|
|
73119
|
+
const previousPath = (0, import_node_path14.resolve)(explicitWorkspacePath);
|
|
73154
73120
|
const remembered = workspaceRelocations.get(previousPath);
|
|
73155
73121
|
const rememberedPath = remembered?.canonicalPath;
|
|
73156
73122
|
const relocated = rememberedPath && workspaceMatchesExpectedRepositories({
|
|
73157
73123
|
workspacePath: rememberedPath,
|
|
73158
73124
|
expectedRepoUrls
|
|
73159
|
-
}) ? (0,
|
|
73125
|
+
}) ? (0, import_node_path14.resolve)(rememberedPath) : discoverRelocatedWorkspace({
|
|
73160
73126
|
missingPath: explicitWorkspacePath,
|
|
73161
73127
|
approvedWorkspacePaths: payload.approvedWorkspacePaths,
|
|
73162
73128
|
expectedRepoUrls
|
|
73163
73129
|
});
|
|
73164
73130
|
if (relocated) {
|
|
73165
|
-
if (!remembered || (0,
|
|
73131
|
+
if (!remembered || (0, import_node_path14.resolve)(remembered.canonicalPath) !== relocated) {
|
|
73166
73132
|
workspaceRelocations.set(previousPath, {
|
|
73167
73133
|
conversationId: payload.conversationId,
|
|
73168
73134
|
runId: payload.runId,
|
|
@@ -73946,7 +73912,7 @@ function transcriptGraceExpired(observedAt, now, graceMs) {
|
|
|
73946
73912
|
// src/native-hook-inbox.ts
|
|
73947
73913
|
var import_node_crypto8 = require("crypto");
|
|
73948
73914
|
var import_node_fs16 = require("fs");
|
|
73949
|
-
var
|
|
73915
|
+
var import_node_path15 = require("path");
|
|
73950
73916
|
var INBOX_FILE_VERSION = 1;
|
|
73951
73917
|
var DEFAULT_MAX_BYTES = 64 * 1024 * 1024;
|
|
73952
73918
|
var DEFAULT_MAX_ENTRIES = 1e4;
|
|
@@ -73993,8 +73959,8 @@ var EncryptedNativeHookInbox = class {
|
|
|
73993
73959
|
};
|
|
73994
73960
|
const monotonic = process.hrtime.bigint().toString().padStart(20, "0");
|
|
73995
73961
|
const prefix = `${String(Date.now()).padStart(13, "0")}-${monotonic}-${envelope.eventId}`;
|
|
73996
|
-
const temporaryPath = (0,
|
|
73997
|
-
const finalPath = (0,
|
|
73962
|
+
const temporaryPath = (0, import_node_path15.join)(this.path, `.${prefix}-${(0, import_node_crypto8.randomUUID)()}.tmp`);
|
|
73963
|
+
const finalPath = (0, import_node_path15.join)(this.path, `${prefix}.event`);
|
|
73998
73964
|
(0, import_node_fs16.writeFileSync)(temporaryPath, JSON.stringify(file2), { mode: 384, flag: "wx" });
|
|
73999
73965
|
(0, import_node_fs16.chmodSync)(temporaryPath, 384);
|
|
74000
73966
|
(0, import_node_fs16.renameSync)(temporaryPath, finalPath);
|
|
@@ -74012,9 +73978,9 @@ var EncryptedNativeHookInbox = class {
|
|
|
74012
73978
|
const result = { attempted: 0, acknowledged: 0, deferred: 0 };
|
|
74013
73979
|
const names = encryptedEntryNames(this.path).filter((name) => name.endsWith(".event")).slice(0, Math.max(0, limit));
|
|
74014
73980
|
for (const name of names) {
|
|
74015
|
-
const sourcePath = (0,
|
|
73981
|
+
const sourcePath = (0, import_node_path15.join)(this.path, name);
|
|
74016
73982
|
const claimedName = `${name.slice(0, -".event".length)}.processing-${(0, import_node_crypto8.randomUUID)()}`;
|
|
74017
|
-
const claimedPath = (0,
|
|
73983
|
+
const claimedPath = (0, import_node_path15.join)(this.path, claimedName);
|
|
74018
73984
|
try {
|
|
74019
73985
|
(0, import_node_fs16.renameSync)(sourcePath, claimedPath);
|
|
74020
73986
|
} catch {
|
|
@@ -74061,14 +74027,14 @@ var EncryptedNativeHookInbox = class {
|
|
|
74061
74027
|
if (name.endsWith(".quarantine")) continue;
|
|
74062
74028
|
const marker = name.indexOf(".processing-");
|
|
74063
74029
|
if (marker === -1) continue;
|
|
74064
|
-
const claimedPath = (0,
|
|
74065
|
-
const eventPath = (0,
|
|
74030
|
+
const claimedPath = (0, import_node_path15.join)(this.path, name);
|
|
74031
|
+
const eventPath = (0, import_node_path15.join)(this.path, `${name.slice(0, marker)}.event`);
|
|
74066
74032
|
if ((0, import_node_fs16.existsSync)(eventPath)) (0, import_node_fs16.rmSync)(claimedPath, { force: true });
|
|
74067
74033
|
else (0, import_node_fs16.renameSync)(claimedPath, eventPath);
|
|
74068
74034
|
}
|
|
74069
74035
|
}
|
|
74070
74036
|
enforceBounds() {
|
|
74071
|
-
const entries = encryptedEntryNames(this.path).filter((name) => name.endsWith(".event")).map((name) => ({ name, bytes: (0, import_node_fs16.statSync)((0,
|
|
74037
|
+
const entries = encryptedEntryNames(this.path).filter((name) => name.endsWith(".event")).map((name) => ({ name, bytes: (0, import_node_fs16.statSync)((0, import_node_path15.join)(this.path, name)).size }));
|
|
74072
74038
|
const totalBytes = entries.reduce((sum, entry) => sum + entry.bytes, 0);
|
|
74073
74039
|
if (entries.length > this.maxEntries || totalBytes > this.maxBytes) {
|
|
74074
74040
|
throw new Error(
|
|
@@ -74078,13 +74044,13 @@ var EncryptedNativeHookInbox = class {
|
|
|
74078
74044
|
}
|
|
74079
74045
|
};
|
|
74080
74046
|
function nativeHookInboxPath(configPath) {
|
|
74081
|
-
return (0,
|
|
74047
|
+
return (0, import_node_path15.join)((0, import_node_path15.dirname)(configPath), "native-hook-inbox");
|
|
74082
74048
|
}
|
|
74083
74049
|
|
|
74084
74050
|
// src/native-transcript-cursor.ts
|
|
74085
74051
|
var import_node_crypto9 = require("crypto");
|
|
74086
74052
|
var import_node_fs17 = require("fs");
|
|
74087
|
-
var
|
|
74053
|
+
var import_node_path16 = require("path");
|
|
74088
74054
|
var CURSOR_FILE_VERSION = 1;
|
|
74089
74055
|
function nativeTranscriptCursorKey(input2) {
|
|
74090
74056
|
return (0, import_node_crypto9.createHash)("sha256").update(`${input2.provider}\0${input2.externalSessionId}\0${input2.transcriptPath}`).digest("base64url");
|
|
@@ -74115,7 +74081,7 @@ var NativeTranscriptCursorStore = class {
|
|
|
74115
74081
|
return parsed.entries;
|
|
74116
74082
|
}
|
|
74117
74083
|
persist() {
|
|
74118
|
-
(0, import_node_fs17.mkdirSync)((0,
|
|
74084
|
+
(0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(this.path), { recursive: true, mode: 448 });
|
|
74119
74085
|
const pendingPath = `${this.path}.pending-${process.pid}-${(0, import_node_crypto9.randomBytes)(6).toString("hex")}`;
|
|
74120
74086
|
try {
|
|
74121
74087
|
(0, import_node_fs17.writeFileSync)(
|
|
@@ -74228,7 +74194,7 @@ var NativeTranscriptStreamer = class {
|
|
|
74228
74194
|
continue;
|
|
74229
74195
|
}
|
|
74230
74196
|
const parsed = parseJsonObject3(raw);
|
|
74231
|
-
const events = parsed ?
|
|
74197
|
+
const events = parsed ? providerRecordToAgentEvents(hook.provider, parsed) : [];
|
|
74232
74198
|
for (let index = 0; index < events.length; index += 1) {
|
|
74233
74199
|
const deliveredEvent = events[index];
|
|
74234
74200
|
const sourceCursor = `${start.generation}:${recordEndOffset}:${index}`;
|
|
@@ -74288,12 +74254,62 @@ function parseJsonObject3(value2) {
|
|
|
74288
74254
|
return null;
|
|
74289
74255
|
}
|
|
74290
74256
|
}
|
|
74291
|
-
function
|
|
74257
|
+
function providerRecordToAgentEvents(provider, record2) {
|
|
74258
|
+
if (provider === "codex") return codexRecordToAgentEvents(record2);
|
|
74259
|
+
if (provider === "copilot") return copilotRecordToAgentEvents(record2);
|
|
74260
|
+
return claudeCompatibleRecordToAgentEvents(record2);
|
|
74261
|
+
}
|
|
74262
|
+
function copilotRecordToAgentEvents(record2) {
|
|
74263
|
+
if (typeof record2.type !== "string" || !isRecord2(record2.data)) return [];
|
|
74264
|
+
const timestamp = timestampOf(record2) ? Date.parse(timestampOf(record2)) : Date.now();
|
|
74265
|
+
const ts = Number.isFinite(timestamp) ? timestamp : Date.now();
|
|
74266
|
+
const data = record2.data;
|
|
74267
|
+
if (record2.type === "assistant.message") {
|
|
74268
|
+
const events = [];
|
|
74269
|
+
if (typeof data.reasoningText === "string" && data.reasoningText.length > 0) {
|
|
74270
|
+
events.push({ type: "thinking", text: data.reasoningText, ts });
|
|
74271
|
+
}
|
|
74272
|
+
if (typeof data.content === "string" && data.content.length > 0) {
|
|
74273
|
+
events.push({ type: "text", text: data.content, ts });
|
|
74274
|
+
}
|
|
74275
|
+
if (Array.isArray(data.toolRequests)) {
|
|
74276
|
+
for (const request of data.toolRequests) {
|
|
74277
|
+
if (!isRecord2(request)) continue;
|
|
74278
|
+
const id = stringValue(request.id, request.toolCallId, request.tool_call_id);
|
|
74279
|
+
const name = stringValue(request.name, request.toolName, request.tool_name);
|
|
74280
|
+
if (id && name) {
|
|
74281
|
+
events.push({
|
|
74282
|
+
type: "tool_use",
|
|
74283
|
+
id,
|
|
74284
|
+
name,
|
|
74285
|
+
input: request.arguments ?? request.input,
|
|
74286
|
+
ts
|
|
74287
|
+
});
|
|
74288
|
+
}
|
|
74289
|
+
}
|
|
74290
|
+
}
|
|
74291
|
+
return events;
|
|
74292
|
+
}
|
|
74293
|
+
if (record2.type === "tool.execution_complete" || record2.type === "tool.execution_end") {
|
|
74294
|
+
const id = stringValue(data.toolCallId, data.tool_call_id, data.id);
|
|
74295
|
+
if (!id) return [];
|
|
74296
|
+
return [
|
|
74297
|
+
{
|
|
74298
|
+
type: "tool_result",
|
|
74299
|
+
id,
|
|
74300
|
+
content: extractText2(data.result ?? data.output ?? data.content),
|
|
74301
|
+
ts
|
|
74302
|
+
}
|
|
74303
|
+
];
|
|
74304
|
+
}
|
|
74305
|
+
return [];
|
|
74306
|
+
}
|
|
74307
|
+
function claudeCompatibleRecordToAgentEvents(record2) {
|
|
74292
74308
|
const timestamp = timestampOf(record2) ? Date.parse(timestampOf(record2)) : Date.now();
|
|
74293
74309
|
const ts = Number.isFinite(timestamp) ? timestamp : Date.now();
|
|
74294
74310
|
const message = isRecord2(record2.message) ? record2.message : record2;
|
|
74295
74311
|
const content = message.content;
|
|
74296
|
-
const role = typeof message.role === "string" ? message.role : typeof record2.type === "string" ? record2.type : null;
|
|
74312
|
+
const role = typeof message.role === "string" ? message.role : typeof record2.role === "string" ? record2.role : typeof record2.type === "string" ? record2.type : null;
|
|
74297
74313
|
if (role === "user") {
|
|
74298
74314
|
if (!Array.isArray(content)) return [];
|
|
74299
74315
|
return content.flatMap((block) => {
|
|
@@ -74331,6 +74347,47 @@ function claudeRecordToAgentEvents(record2) {
|
|
|
74331
74347
|
return [{ type: "text", text: content, ts }];
|
|
74332
74348
|
return [];
|
|
74333
74349
|
}
|
|
74350
|
+
function codexRecordToAgentEvents(record2) {
|
|
74351
|
+
if (record2.type !== "response_item" || !isRecord2(record2.payload)) return [];
|
|
74352
|
+
const payload = record2.payload;
|
|
74353
|
+
const timestamp = timestampOf(record2) ? Date.parse(timestampOf(record2)) : Date.now();
|
|
74354
|
+
const ts = Number.isFinite(timestamp) ? timestamp : Date.now();
|
|
74355
|
+
if (payload.type === "message" && payload.role === "assistant") {
|
|
74356
|
+
if (!Array.isArray(payload.content)) return [];
|
|
74357
|
+
return payload.content.flatMap((block) => {
|
|
74358
|
+
if (!isRecord2(block) || block.type !== "output_text" || typeof block.text !== "string") {
|
|
74359
|
+
return [];
|
|
74360
|
+
}
|
|
74361
|
+
return block.text ? [{ type: "text", text: block.text, ts }] : [];
|
|
74362
|
+
});
|
|
74363
|
+
}
|
|
74364
|
+
if (payload.type === "reasoning") {
|
|
74365
|
+
const text = extractText2(payload.summary);
|
|
74366
|
+
return text ? [{ type: "thinking", text, ts }] : [];
|
|
74367
|
+
}
|
|
74368
|
+
if (payload.type === "custom_tool_call") {
|
|
74369
|
+
const id = stringValue(payload.call_id, payload.id);
|
|
74370
|
+
const name = stringValue(payload.name);
|
|
74371
|
+
if (!id || !name) return [];
|
|
74372
|
+
return [{ type: "tool_use", id, name, input: parseEmbeddedJson(payload.input), ts }];
|
|
74373
|
+
}
|
|
74374
|
+
if (payload.type === "custom_tool_call_output") {
|
|
74375
|
+
const id = stringValue(payload.call_id, payload.id);
|
|
74376
|
+
return id ? [{ type: "tool_result", id, content: extractText2(payload.output), ts }] : [];
|
|
74377
|
+
}
|
|
74378
|
+
return [];
|
|
74379
|
+
}
|
|
74380
|
+
function stringValue(...values) {
|
|
74381
|
+
return values.find((value2) => typeof value2 === "string" && value2.length > 0) ?? null;
|
|
74382
|
+
}
|
|
74383
|
+
function parseEmbeddedJson(value2) {
|
|
74384
|
+
if (typeof value2 !== "string") return value2;
|
|
74385
|
+
try {
|
|
74386
|
+
return JSON.parse(value2);
|
|
74387
|
+
} catch {
|
|
74388
|
+
return value2;
|
|
74389
|
+
}
|
|
74390
|
+
}
|
|
74334
74391
|
function extractText2(value2) {
|
|
74335
74392
|
if (typeof value2 === "string") return value2;
|
|
74336
74393
|
if (Array.isArray(value2)) return value2.map(extractText2).filter(Boolean).join("\n");
|
|
@@ -74430,7 +74487,7 @@ var ObservableMap = class extends Map {
|
|
|
74430
74487
|
|
|
74431
74488
|
// src/run-journal.ts
|
|
74432
74489
|
var import_node_fs19 = require("fs");
|
|
74433
|
-
var
|
|
74490
|
+
var import_node_path17 = require("path");
|
|
74434
74491
|
var JOURNAL_VERSION = 1;
|
|
74435
74492
|
var INTERRUPTED_ENTRY_TTL_MS = 24 * 60 * 6e4;
|
|
74436
74493
|
function isEntry(value2) {
|
|
@@ -74574,7 +74631,7 @@ var RuntimeRunJournal = class {
|
|
|
74574
74631
|
}
|
|
74575
74632
|
persist() {
|
|
74576
74633
|
const pendingPath = `${this.path}.pending`;
|
|
74577
|
-
(0, import_node_fs19.mkdirSync)((0,
|
|
74634
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path17.dirname)(this.path), { recursive: true });
|
|
74578
74635
|
try {
|
|
74579
74636
|
(0, import_node_fs19.writeFileSync)(
|
|
74580
74637
|
pendingPath,
|
|
@@ -74615,13 +74672,13 @@ var RunStartGate = class {
|
|
|
74615
74672
|
var import_node_buffer2 = require("buffer");
|
|
74616
74673
|
var import_node_crypto12 = require("crypto");
|
|
74617
74674
|
var import_promises2 = require("fs/promises");
|
|
74618
|
-
var
|
|
74675
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
74619
74676
|
|
|
74620
74677
|
// ../shared/dist/node/skill-package.js
|
|
74621
74678
|
var import_node_buffer = require("buffer");
|
|
74622
74679
|
var import_node_crypto11 = require("crypto");
|
|
74623
74680
|
var import_promises = require("fs/promises");
|
|
74624
|
-
var
|
|
74681
|
+
var import_node_path18 = require("path");
|
|
74625
74682
|
var import_yaml = __toESM(require_dist2(), 1);
|
|
74626
74683
|
|
|
74627
74684
|
// ../shared/dist/skills/domain.js
|
|
@@ -75045,7 +75102,7 @@ async function inspectSkillPackage(packageRoot, options = {}) {
|
|
|
75045
75102
|
}
|
|
75046
75103
|
const inspectedFiles = await Promise.all(files.map(readPackageFile));
|
|
75047
75104
|
inspectedFiles.sort(comparePackageFiles);
|
|
75048
|
-
const parsedMetadata = parseSkillMetadata(inspectedFiles.find((file2) => file2.manifest.path === "SKILL.md")?.bytes, options.expectedName === void 0 ? (0,
|
|
75105
|
+
const parsedMetadata = parseSkillMetadata(inspectedFiles.find((file2) => file2.manifest.path === "SKILL.md")?.bytes, options.expectedName === void 0 ? (0, import_node_path18.basename)(root) : options.expectedName);
|
|
75049
75106
|
const manifestFiles = inspectedFiles.map((file2) => file2.manifest);
|
|
75050
75107
|
const diagnostics = [
|
|
75051
75108
|
...parsedMetadata.conformance,
|
|
@@ -75069,7 +75126,7 @@ async function readSkillPackageFile(packageRoot, path2, expectedSha256) {
|
|
|
75069
75126
|
if (!normalizedPath || normalizedPath !== path2 || normalizedPath.includes("\\") || components.some((component) => !component || component === "." || component === "..")) {
|
|
75070
75127
|
throw new SkillPackageError("INVALID_PATH", `Invalid Skill package path: ${path2}`, path2);
|
|
75071
75128
|
}
|
|
75072
|
-
const absolutePath = await (0, import_promises.realpath)((0,
|
|
75129
|
+
const absolutePath = await (0, import_promises.realpath)((0, import_node_path18.resolve)(root, ...components)).catch(() => null);
|
|
75073
75130
|
if (!absolutePath || normalizeRelativePath(root, absolutePath) !== normalizedPath) {
|
|
75074
75131
|
throw new SkillPackageError("INVALID_PATH", `Skill package file was not found: ${path2}`, path2);
|
|
75075
75132
|
}
|
|
@@ -75090,7 +75147,7 @@ async function readSkillPackageFile(packageRoot, path2, expectedSha256) {
|
|
|
75090
75147
|
return { file: read.manifest, bytes: read.bytes };
|
|
75091
75148
|
}
|
|
75092
75149
|
async function requirePackageRoot(packageRoot) {
|
|
75093
|
-
const root = await (0, import_promises.realpath)((0,
|
|
75150
|
+
const root = await (0, import_promises.realpath)((0, import_node_path18.resolve)(packageRoot)).catch(() => null);
|
|
75094
75151
|
if (!root) {
|
|
75095
75152
|
throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package directory does not exist");
|
|
75096
75153
|
}
|
|
@@ -75116,7 +75173,7 @@ async function walkPackage(root, ignoredPaths) {
|
|
|
75116
75173
|
async function walkDirectory(directory) {
|
|
75117
75174
|
const entries = await (0, import_promises.readdir)(directory, { withFileTypes: true });
|
|
75118
75175
|
for (const entry of entries) {
|
|
75119
|
-
const absolutePath = (0,
|
|
75176
|
+
const absolutePath = (0, import_node_path18.resolve)(directory, entry.name);
|
|
75120
75177
|
const normalizedPath = normalizeRelativePath(root, absolutePath);
|
|
75121
75178
|
if (isIgnored(normalizedPath, entry.name, entry.isDirectory(), ignored))
|
|
75122
75179
|
continue;
|
|
@@ -75153,10 +75210,10 @@ function createIgnoreMatcher(path2) {
|
|
|
75153
75210
|
const expression = globToRegExp(pattern);
|
|
75154
75211
|
return (candidate) => expression.test(candidate) || expression.test(`${candidate}/`);
|
|
75155
75212
|
}
|
|
75156
|
-
function isIgnored(normalizedPath,
|
|
75157
|
-
if (isDirectory2 && ALWAYS_IGNORED_DIRECTORIES.has(
|
|
75213
|
+
function isIgnored(normalizedPath, basename7, isDirectory2, configured) {
|
|
75214
|
+
if (isDirectory2 && ALWAYS_IGNORED_DIRECTORIES.has(basename7))
|
|
75158
75215
|
return true;
|
|
75159
|
-
if (!isDirectory2 && ALWAYS_IGNORED_FILES.has(
|
|
75216
|
+
if (!isDirectory2 && ALWAYS_IGNORED_FILES.has(basename7))
|
|
75160
75217
|
return true;
|
|
75161
75218
|
return configured.some((matches) => matches(normalizedPath));
|
|
75162
75219
|
}
|
|
@@ -75183,12 +75240,12 @@ function globToRegExp(pattern) {
|
|
|
75183
75240
|
return new RegExp(`${source}(?:/.*)?$`);
|
|
75184
75241
|
}
|
|
75185
75242
|
function normalizeRelativePath(root, absolutePath) {
|
|
75186
|
-
const nativeRelativePath = (0,
|
|
75187
|
-
if (!nativeRelativePath || nativeRelativePath.startsWith(`..${
|
|
75243
|
+
const nativeRelativePath = (0, import_node_path18.relative)(root, absolutePath);
|
|
75244
|
+
if (!nativeRelativePath || nativeRelativePath.startsWith(`..${import_node_path18.sep}`) || nativeRelativePath === "..") {
|
|
75188
75245
|
throw new SkillPackageError("INVALID_PATH", "Skill package path escapes its root");
|
|
75189
75246
|
}
|
|
75190
|
-
const normalized = nativeRelativePath.split(
|
|
75191
|
-
if (normalized.includes("\0") || normalized.includes("\uFFFD") ||
|
|
75247
|
+
const normalized = nativeRelativePath.split(import_node_path18.sep).join("/").normalize("NFC");
|
|
75248
|
+
if (normalized.includes("\0") || normalized.includes("\uFFFD") || import_node_path18.posix.isAbsolute(normalized)) {
|
|
75192
75249
|
throw new SkillPackageError("INVALID_PATH", `Invalid Skill package path: ${normalized}`);
|
|
75193
75250
|
}
|
|
75194
75251
|
return normalized;
|
|
@@ -75223,7 +75280,7 @@ function requireSafeFile(path2, size, normalizedPaths) {
|
|
|
75223
75280
|
}
|
|
75224
75281
|
}
|
|
75225
75282
|
function isSecretPath(path2) {
|
|
75226
|
-
const name =
|
|
75283
|
+
const name = import_node_path18.posix.basename(path2).toLowerCase();
|
|
75227
75284
|
if (SECRET_BASENAMES.has(name) || name.startsWith(".env."))
|
|
75228
75285
|
return true;
|
|
75229
75286
|
return name.endsWith(".private-key.pem") || name.endsWith(".private-key.key");
|
|
@@ -75251,12 +75308,12 @@ function classifyFileKind(path2) {
|
|
|
75251
75308
|
return "reference";
|
|
75252
75309
|
if (path2.startsWith("assets/"))
|
|
75253
75310
|
return "asset";
|
|
75254
|
-
if (/^(?:licen[cs]e|copying|notice)(?:\.|$)/i.test(
|
|
75311
|
+
if (/^(?:licen[cs]e|copying|notice)(?:\.|$)/i.test(import_node_path18.posix.basename(path2)))
|
|
75255
75312
|
return "license";
|
|
75256
75313
|
return "other";
|
|
75257
75314
|
}
|
|
75258
75315
|
function classifyPreview(path2, bytes) {
|
|
75259
|
-
const extension =
|
|
75316
|
+
const extension = import_node_path18.posix.extname(path2).toLowerCase();
|
|
75260
75317
|
if (IMAGE_EXTENSIONS.has(extension))
|
|
75261
75318
|
return "image";
|
|
75262
75319
|
if (bytes.includes(0))
|
|
@@ -75360,7 +75417,7 @@ function normalizePackageReference(value2) {
|
|
|
75360
75417
|
const withoutSuffix = trimmed.split(/[?#]/, 1)[0];
|
|
75361
75418
|
if (!withoutSuffix)
|
|
75362
75419
|
return null;
|
|
75363
|
-
const normalized =
|
|
75420
|
+
const normalized = import_node_path18.posix.normalize(withoutSuffix).replace(/^\.\//, "").normalize("NFC");
|
|
75364
75421
|
if (normalized === ".." || normalized.startsWith("../"))
|
|
75365
75422
|
return null;
|
|
75366
75423
|
return normalized;
|
|
@@ -75597,9 +75654,9 @@ var LocalSkillSource = class {
|
|
|
75597
75654
|
*/
|
|
75598
75655
|
async scanRootAsPackage(resolvedRoot, ignoredPaths, mode) {
|
|
75599
75656
|
const directory = resolvedRoot.directory;
|
|
75600
|
-
if (!await pathExists((0,
|
|
75657
|
+
if (!await pathExists((0, import_node_path19.join)(directory, "SKILL.md"))) return null;
|
|
75601
75658
|
const canonicalRoot = await (0, import_promises2.realpath)(directory).catch(() => directory);
|
|
75602
|
-
const name =
|
|
75659
|
+
const name = import_node_path19.default.basename(canonicalRoot);
|
|
75603
75660
|
try {
|
|
75604
75661
|
const fingerprint = await fingerprintPackage(canonicalRoot);
|
|
75605
75662
|
const ignoreSignature = JSON.stringify(ignoredPaths);
|
|
@@ -75669,7 +75726,7 @@ var LocalSkillSource = class {
|
|
|
75669
75726
|
);
|
|
75670
75727
|
for (const entry of entries) {
|
|
75671
75728
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
75672
|
-
const candidatePath = (0,
|
|
75729
|
+
const candidatePath = (0, import_node_path19.join)(resolvedRoot.directory, entry.name);
|
|
75673
75730
|
const canonicalPath = await (0, import_promises2.realpath)(candidatePath).catch(() => null);
|
|
75674
75731
|
if (!canonicalPath) {
|
|
75675
75732
|
diagnostics.push({
|
|
@@ -75735,7 +75792,7 @@ async function fingerprintPackage(root) {
|
|
|
75735
75792
|
entries.sort((left, right) => import_node_buffer2.Buffer.compare(import_node_buffer2.Buffer.from(left.name), import_node_buffer2.Buffer.from(right.name)));
|
|
75736
75793
|
for (const entry of entries) {
|
|
75737
75794
|
const path2 = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
|
|
75738
|
-
const absolutePath = (0,
|
|
75795
|
+
const absolutePath = (0, import_node_path19.join)(directory, entry.name);
|
|
75739
75796
|
const metadata = await (0, import_promises2.lstat)(absolutePath);
|
|
75740
75797
|
hash2.update(path2.normalize("NFC")).update("\0").update(
|
|
75741
75798
|
entry.isDirectory() ? "d" : entry.isFile() ? "f" : entry.isSymbolicLink() ? "l" : "o"
|
|
@@ -75760,12 +75817,12 @@ async function canonicalDirectories(directories) {
|
|
|
75760
75817
|
return [...new Set(canonical)];
|
|
75761
75818
|
}
|
|
75762
75819
|
function isWithinDirectory(parent, candidate) {
|
|
75763
|
-
const path2 = (0,
|
|
75764
|
-
return path2 !== ".." && !path2.startsWith(`..${
|
|
75820
|
+
const path2 = (0, import_node_path19.relative)(parent, candidate);
|
|
75821
|
+
return path2 !== ".." && !path2.startsWith(`..${import_node_path19.sep}`) && !(0, import_node_path19.isAbsolute)(path2);
|
|
75765
75822
|
}
|
|
75766
|
-
async function loadSkillSourceConfig(
|
|
75767
|
-
const configDirectory = (0,
|
|
75768
|
-
const configPath = (0,
|
|
75823
|
+
async function loadSkillSourceConfig(homeDirectory2) {
|
|
75824
|
+
const configDirectory = (0, import_node_path19.join)(homeDirectory2, ".alan");
|
|
75825
|
+
const configPath = (0, import_node_path19.join)(configDirectory, "config.toml");
|
|
75769
75826
|
await (0, import_promises2.mkdir)(configDirectory, { recursive: true, mode: 448 });
|
|
75770
75827
|
let created = false;
|
|
75771
75828
|
try {
|
|
@@ -75780,18 +75837,18 @@ async function loadSkillSourceConfig(homeDirectory) {
|
|
|
75780
75837
|
}
|
|
75781
75838
|
const content = await (0, import_promises2.readFile)(configPath, "utf8");
|
|
75782
75839
|
try {
|
|
75783
|
-
return { state: "ready", config: parseSkillSourceConfig(content,
|
|
75840
|
+
return { state: "ready", config: parseSkillSourceConfig(content, homeDirectory2), created };
|
|
75784
75841
|
} catch (error61) {
|
|
75785
75842
|
return {
|
|
75786
75843
|
state: "invalid",
|
|
75787
|
-
config: parseSkillSourceConfig(DEFAULT_SKILL_CONFIG,
|
|
75844
|
+
config: parseSkillSourceConfig(DEFAULT_SKILL_CONFIG, homeDirectory2),
|
|
75788
75845
|
created: false,
|
|
75789
75846
|
diagnostic: error61 instanceof Error ? error61.message : String(error61)
|
|
75790
75847
|
};
|
|
75791
75848
|
}
|
|
75792
75849
|
}
|
|
75793
|
-
async function resolveSkillScanInput(
|
|
75794
|
-
const loaded = await loadSkillSourceConfig(
|
|
75850
|
+
async function resolveSkillScanInput(homeDirectory2, declared) {
|
|
75851
|
+
const loaded = await loadSkillSourceConfig(homeDirectory2);
|
|
75795
75852
|
if (loaded.state === "invalid") {
|
|
75796
75853
|
throw Object.assign(new Error(`Invalid Skill source configuration: ${loaded.diagnostic}`), {
|
|
75797
75854
|
code: "SKILL_SOURCE_CONFIG_INVALID"
|
|
@@ -75799,7 +75856,7 @@ async function resolveSkillScanInput(homeDirectory, declared) {
|
|
|
75799
75856
|
}
|
|
75800
75857
|
const { config: config2 } = loaded;
|
|
75801
75858
|
if (!config2.enabled) return { ...declared, roots: [], ignoredPaths: config2.ignoredPaths };
|
|
75802
|
-
const draftsPath = (0,
|
|
75859
|
+
const draftsPath = (0, import_node_path19.resolve)((0, import_node_path19.join)(homeDirectory2, ".alan", "skill-sources"));
|
|
75803
75860
|
const enabledProviders = new Set(declared.enabledProviderKinds ?? []);
|
|
75804
75861
|
const configured = [];
|
|
75805
75862
|
for (const source of config2.sources) {
|
|
@@ -75807,7 +75864,7 @@ async function resolveSkillScanInput(homeDirectory, declared) {
|
|
|
75807
75864
|
continue;
|
|
75808
75865
|
}
|
|
75809
75866
|
configured.push(
|
|
75810
|
-
(0,
|
|
75867
|
+
(0, import_node_path19.resolve)(source.path) === draftsPath ? { kind: "drafts", path: source.path, label: "Alan drafts" } : {
|
|
75811
75868
|
kind: "configured",
|
|
75812
75869
|
declarationId: source.declarationId,
|
|
75813
75870
|
path: source.path,
|
|
@@ -75823,7 +75880,7 @@ async function resolveSkillScanInput(homeDirectory, declared) {
|
|
|
75823
75880
|
ignoredPaths: [.../* @__PURE__ */ new Set([...config2.ignoredPaths, ...declared.ignoredPaths ?? []])]
|
|
75824
75881
|
};
|
|
75825
75882
|
}
|
|
75826
|
-
function parseSkillSourceConfig(content,
|
|
75883
|
+
function parseSkillSourceConfig(content, homeDirectory2) {
|
|
75827
75884
|
const parsed = parse5(content);
|
|
75828
75885
|
if (!isRecord4(parsed) || parsed.version !== 1 || !isRecord4(parsed.skills)) {
|
|
75829
75886
|
throw new Error("~/.alan/config.toml must contain version = 1 and a [skills] table");
|
|
@@ -75846,7 +75903,7 @@ function parseSkillSourceConfig(content, homeDirectory) {
|
|
|
75846
75903
|
`skills.sources entry ${index + 1} must contain string path and label values`
|
|
75847
75904
|
);
|
|
75848
75905
|
}
|
|
75849
|
-
const sourcePath = resolveSkillSourcePath(value2.path,
|
|
75906
|
+
const sourcePath = resolveSkillSourcePath(value2.path, homeDirectory2);
|
|
75850
75907
|
const label = value2.label.trim();
|
|
75851
75908
|
if (!label) throw new Error(`skills.sources entry ${index + 1} has an empty label`);
|
|
75852
75909
|
const declarationId = value2.id === void 0 ? stableSourceDeclarationId(sourcePath) : requiredSourceId(value2.id, `skills.sources[${index}].id`);
|
|
@@ -75854,7 +75911,7 @@ function parseSkillSourceConfig(content, homeDirectory) {
|
|
|
75854
75911
|
value2.providers,
|
|
75855
75912
|
`skills.sources[${index}].providers`
|
|
75856
75913
|
);
|
|
75857
|
-
const relativeDirectory =
|
|
75914
|
+
const relativeDirectory = import_node_path19.default.relative(homeDirectory2, sourcePath);
|
|
75858
75915
|
const inferredProviders = providerKindsForUserDirectory(relativeDirectory);
|
|
75859
75916
|
const declaredProviders = value2.providers === void 0 ? inferredProviders : [...new Set(explicitProviders.map((provider) => provider.trim()).filter(Boolean))];
|
|
75860
75917
|
const stale = staleCodexDeclaration(relativeDirectory, label, declaredProviders);
|
|
@@ -75884,14 +75941,14 @@ function requiredSourceId(value2, field) {
|
|
|
75884
75941
|
}
|
|
75885
75942
|
return value2;
|
|
75886
75943
|
}
|
|
75887
|
-
function resolveSkillSourcePath(sourcePath,
|
|
75944
|
+
function resolveSkillSourcePath(sourcePath, homeDirectory2, pathApi = import_node_path19.default) {
|
|
75888
75945
|
const trimmed = sourcePath.trim();
|
|
75889
|
-
if (trimmed === "~") return pathApi.resolve(
|
|
75946
|
+
if (trimmed === "~") return pathApi.resolve(homeDirectory2);
|
|
75890
75947
|
if (trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
75891
75948
|
const components = trimmed.slice(2).split(/[\\/]+/).filter(Boolean);
|
|
75892
|
-
return pathApi.resolve(pathApi.join(
|
|
75949
|
+
return pathApi.resolve(pathApi.join(homeDirectory2, ...components));
|
|
75893
75950
|
}
|
|
75894
|
-
return pathApi.isAbsolute(trimmed) ? pathApi.resolve(trimmed) : pathApi.resolve(
|
|
75951
|
+
return pathApi.isAbsolute(trimmed) ? pathApi.resolve(trimmed) : pathApi.resolve(homeDirectory2, trimmed);
|
|
75895
75952
|
}
|
|
75896
75953
|
function optionalBoolean(value2, fallback, field) {
|
|
75897
75954
|
if (value2 === void 0) return fallback;
|
|
@@ -75919,7 +75976,7 @@ function resolveScanRoots(roots, enabledProviderKinds) {
|
|
|
75919
75976
|
).entries()) {
|
|
75920
75977
|
resolved.push({
|
|
75921
75978
|
root,
|
|
75922
|
-
directory: (0,
|
|
75979
|
+
directory: (0, import_node_path19.join)(root.path, relativeDirectory),
|
|
75923
75980
|
order: `1:${root.repositoryId}:${String(index).padStart(2, "0")}`
|
|
75924
75981
|
});
|
|
75925
75982
|
}
|
|
@@ -75978,7 +76035,7 @@ async function pathExists(candidate) {
|
|
|
75978
76035
|
}
|
|
75979
76036
|
async function hasManagedMarker(directory) {
|
|
75980
76037
|
try {
|
|
75981
|
-
await (0, import_promises2.access)((0,
|
|
76038
|
+
await (0, import_promises2.access)((0, import_node_path19.join)(directory, ".alan-managed.json"));
|
|
75982
76039
|
return true;
|
|
75983
76040
|
} catch {
|
|
75984
76041
|
return false;
|
|
@@ -76147,12 +76204,12 @@ var RuntimeSkillCoordinator = class {
|
|
|
76147
76204
|
var import_node_buffer5 = require("buffer");
|
|
76148
76205
|
var import_node_crypto15 = require("crypto");
|
|
76149
76206
|
var import_promises5 = require("fs/promises");
|
|
76150
|
-
var
|
|
76207
|
+
var import_node_path22 = require("path");
|
|
76151
76208
|
|
|
76152
76209
|
// src/skills/managed-skill-store.ts
|
|
76153
76210
|
var import_node_crypto13 = require("crypto");
|
|
76154
76211
|
var import_promises3 = require("fs/promises");
|
|
76155
|
-
var
|
|
76212
|
+
var import_node_path20 = require("path");
|
|
76156
76213
|
var EMPTY_STATE = {
|
|
76157
76214
|
version: 1,
|
|
76158
76215
|
sources: {},
|
|
@@ -76171,7 +76228,7 @@ var ManagedSkillStore = class _ManagedSkillStore {
|
|
|
76171
76228
|
static async open(baseDirectory) {
|
|
76172
76229
|
await (0, import_promises3.mkdir)(baseDirectory, { recursive: true, mode: 448 });
|
|
76173
76230
|
try {
|
|
76174
|
-
const parsed = JSON.parse(await (0, import_promises3.readFile)((0,
|
|
76231
|
+
const parsed = JSON.parse(await (0, import_promises3.readFile)((0, import_node_path20.join)(baseDirectory, "state.json"), "utf8"));
|
|
76175
76232
|
return new _ManagedSkillStore(baseDirectory, parseState(parsed), "verified");
|
|
76176
76233
|
} catch (error61) {
|
|
76177
76234
|
if (isMissingPath2(error61)) {
|
|
@@ -76270,8 +76327,8 @@ var ManagedSkillStore = class _ManagedSkillStore {
|
|
|
76270
76327
|
this.canRemoveManagedFiles = true;
|
|
76271
76328
|
}
|
|
76272
76329
|
async persist() {
|
|
76273
|
-
const statePath = (0,
|
|
76274
|
-
const pendingPath = (0,
|
|
76330
|
+
const statePath = (0, import_node_path20.join)(this.baseDirectory, "state.json");
|
|
76331
|
+
const pendingPath = (0, import_node_path20.join)(
|
|
76275
76332
|
this.baseDirectory,
|
|
76276
76333
|
`.state.json.pending-${process.pid}-${(0, import_node_crypto13.randomBytes)(6).toString("hex")}`
|
|
76277
76334
|
);
|
|
@@ -76356,7 +76413,7 @@ function isMissingPath2(error61) {
|
|
|
76356
76413
|
var import_node_buffer3 = require("buffer");
|
|
76357
76414
|
var import_node_crypto14 = require("crypto");
|
|
76358
76415
|
var import_promises4 = require("fs/promises");
|
|
76359
|
-
var
|
|
76416
|
+
var import_node_path21 = require("path");
|
|
76360
76417
|
var import_node_stream = require("stream");
|
|
76361
76418
|
var import_node_zlib = require("zlib");
|
|
76362
76419
|
var import_tar_stream = __toESM(require_tar_stream(), 1);
|
|
@@ -76365,7 +76422,7 @@ async function createSkillBundle(packageRoot) {
|
|
|
76365
76422
|
const archive = (0, import_tar_stream.pack)();
|
|
76366
76423
|
const tarPromise = collectStream(archive);
|
|
76367
76424
|
for (const file2 of before.files) {
|
|
76368
|
-
const bytes2 = await (0, import_promises4.readFile)((0,
|
|
76425
|
+
const bytes2 = await (0, import_promises4.readFile)((0, import_node_path21.join)(packageRoot, ...file2.path.split("/")));
|
|
76369
76426
|
await addArchiveEntry(archive, {
|
|
76370
76427
|
name: file2.path,
|
|
76371
76428
|
type: "file",
|
|
@@ -76480,13 +76537,13 @@ async function extractEntry(header, stream, destination, limits) {
|
|
|
76480
76537
|
if (bytes.byteLength !== declaredSize) {
|
|
76481
76538
|
throw new Error(`Skill archive file size is invalid: ${path2}`);
|
|
76482
76539
|
}
|
|
76483
|
-
const outputPath = (0,
|
|
76484
|
-
await (0, import_promises4.mkdir)((0,
|
|
76540
|
+
const outputPath = (0, import_node_path21.join)(destination, ...path2.split("/"));
|
|
76541
|
+
await (0, import_promises4.mkdir)((0, import_node_path21.dirname)(outputPath), { recursive: true, mode: 448 });
|
|
76485
76542
|
await (0, import_promises4.writeFile)(outputPath, bytes, { mode: (header.mode ?? 420) & 73 ? 493 : 420 });
|
|
76486
76543
|
}
|
|
76487
76544
|
function requireSafeArchivePath(value2) {
|
|
76488
76545
|
const normalized = value2.replaceAll("\\", "/").normalize("NFC");
|
|
76489
|
-
if (!normalized || normalized.startsWith("/") || normalized.includes("\0") ||
|
|
76546
|
+
if (!normalized || normalized.startsWith("/") || normalized.includes("\0") || import_node_path21.posix.normalize(normalized) !== normalized || normalized === ".." || normalized.startsWith("../")) {
|
|
76490
76547
|
throw new Error(`Skill archive contains an unsafe path: ${value2}`);
|
|
76491
76548
|
}
|
|
76492
76549
|
return normalized;
|
|
@@ -76565,14 +76622,14 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76565
76622
|
}
|
|
76566
76623
|
reconcileTail = Promise.resolve();
|
|
76567
76624
|
static async open(options) {
|
|
76568
|
-
const skillsStateDirectory = (0,
|
|
76569
|
-
const managedSkillsDirectory = (0,
|
|
76625
|
+
const skillsStateDirectory = (0, import_node_path22.join)(options.homeDirectory, ".alan", "skills");
|
|
76626
|
+
const managedSkillsDirectory = (0, import_node_path22.join)(options.homeDirectory, ".agents", "skills");
|
|
76570
76627
|
const store = await ManagedSkillStore.open(skillsStateDirectory);
|
|
76571
76628
|
return new _RuntimeSkillManager(
|
|
76572
76629
|
skillsStateDirectory,
|
|
76573
76630
|
managedSkillsDirectory,
|
|
76574
|
-
(0,
|
|
76575
|
-
(0,
|
|
76631
|
+
(0, import_node_path22.join)(options.homeDirectory, ".claude", "skills"),
|
|
76632
|
+
(0, import_node_path22.join)(options.homeDirectory, ".alan", "sync-manifest.json"),
|
|
76576
76633
|
store,
|
|
76577
76634
|
options.downloadBundle ?? downloadBundleWithFetch,
|
|
76578
76635
|
options.localSource ?? new LocalSkillSource(),
|
|
@@ -76731,7 +76788,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76731
76788
|
if (!runtimeDirectory) {
|
|
76732
76789
|
throw new Error("Selected Skill version is not installed on this runtime");
|
|
76733
76790
|
}
|
|
76734
|
-
const packageDirectory = (0,
|
|
76791
|
+
const packageDirectory = (0, import_node_path22.join)(this.managedSkillsDirectory, runtimeDirectory);
|
|
76735
76792
|
const marker = await readMarker(packageDirectory);
|
|
76736
76793
|
if (!marker || marker.skillId !== invocation.skillId || marker.versionId !== invocation.versionId) {
|
|
76737
76794
|
throw new Error("Selected Skill projection is missing or no longer owned by Alan");
|
|
@@ -76745,11 +76802,11 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76745
76802
|
async reconcileUnlocked(manifest) {
|
|
76746
76803
|
const desired = desiredSkillManifestSchema.parse(manifest);
|
|
76747
76804
|
await (0, import_promises5.mkdir)(this.managedSkillsDirectory, { recursive: true, mode: 448 });
|
|
76748
|
-
await (0, import_promises5.mkdir)((0,
|
|
76805
|
+
await (0, import_promises5.mkdir)((0, import_node_path22.join)(this.skillsStateDirectory, "cache", "sha256"), {
|
|
76749
76806
|
recursive: true,
|
|
76750
76807
|
mode: 448
|
|
76751
76808
|
});
|
|
76752
|
-
await (0, import_promises5.mkdir)((0,
|
|
76809
|
+
await (0, import_promises5.mkdir)((0, import_node_path22.join)(this.skillsStateDirectory, "tmp"), { recursive: true, mode: 448 });
|
|
76753
76810
|
const results = [];
|
|
76754
76811
|
const nextProjections = {};
|
|
76755
76812
|
for (const entry of desired.skills) {
|
|
@@ -76800,7 +76857,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76800
76857
|
};
|
|
76801
76858
|
}
|
|
76802
76859
|
async reuseCurrentProjection(entry) {
|
|
76803
|
-
const destination = (0,
|
|
76860
|
+
const destination = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.runtimeDirectory);
|
|
76804
76861
|
const marker = await readMarker(destination);
|
|
76805
76862
|
if (marker?.skillId !== entry.skillId || marker.versionId !== entry.versionId || marker.contentHash !== entry.contentHash || !await packageMatches(destination, entry.contentHash)) {
|
|
76806
76863
|
return null;
|
|
@@ -76809,19 +76866,19 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76809
76866
|
return entry.contentHash;
|
|
76810
76867
|
}
|
|
76811
76868
|
async adoptLegacyProjection(entry) {
|
|
76812
|
-
const destination = (0,
|
|
76869
|
+
const destination = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.runtimeDirectory);
|
|
76813
76870
|
if (await pathExists2(destination)) return;
|
|
76814
76871
|
const manifest = await readLegacyManifest(this.legacyManifestPath);
|
|
76815
76872
|
const legacy = manifest?.skills[entry.slug];
|
|
76816
76873
|
if (!legacy) return;
|
|
76817
|
-
const source = (0,
|
|
76874
|
+
const source = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.slug);
|
|
76818
76875
|
if (!await legacyFileMatches(source, legacy.hash) || !await packageMatches(source, entry.contentHash)) {
|
|
76819
76876
|
return;
|
|
76820
76877
|
}
|
|
76821
76878
|
await (0, import_promises5.rename)(source, destination);
|
|
76822
76879
|
try {
|
|
76823
76880
|
await (0, import_promises5.writeFile)(
|
|
76824
|
-
(0,
|
|
76881
|
+
(0, import_node_path22.join)(destination, ".alan-managed.json"),
|
|
76825
76882
|
`${JSON.stringify(markerFor(entry), null, 2)}
|
|
76826
76883
|
`,
|
|
76827
76884
|
{ encoding: "utf8", flag: "wx", mode: 384 }
|
|
@@ -76830,19 +76887,19 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76830
76887
|
await (0, import_promises5.rename)(destination, source).catch(() => void 0);
|
|
76831
76888
|
throw error61;
|
|
76832
76889
|
}
|
|
76833
|
-
await removeExactLegacySkill((0,
|
|
76890
|
+
await removeExactLegacySkill((0, import_node_path22.join)(this.compatibilitySkillsDirectory, entry.slug), legacy.hash);
|
|
76834
76891
|
}
|
|
76835
76892
|
async retireLegacySyncManifest() {
|
|
76836
76893
|
const manifest = await readLegacyManifest(this.legacyManifestPath);
|
|
76837
76894
|
if (!manifest) return;
|
|
76838
76895
|
for (const [command, entry] of Object.entries(manifest.skills)) {
|
|
76839
|
-
await removeExactLegacySkill((0,
|
|
76840
|
-
await removeExactLegacySkill((0,
|
|
76896
|
+
await removeExactLegacySkill((0, import_node_path22.join)(this.managedSkillsDirectory, command), entry.hash);
|
|
76897
|
+
await removeExactLegacySkill((0, import_node_path22.join)(this.compatibilitySkillsDirectory, command), entry.hash);
|
|
76841
76898
|
}
|
|
76842
76899
|
await (0, import_promises5.rm)(this.legacyManifestPath, { force: true });
|
|
76843
76900
|
}
|
|
76844
76901
|
async ensureCached(entry) {
|
|
76845
|
-
const cacheDirectory = (0,
|
|
76902
|
+
const cacheDirectory = (0, import_node_path22.join)(
|
|
76846
76903
|
this.skillsStateDirectory,
|
|
76847
76904
|
"cache",
|
|
76848
76905
|
"sha256",
|
|
@@ -76856,7 +76913,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76856
76913
|
`Downloaded Skill bundle length ${bytes.byteLength} does not match ${entry.compressedBytes}`
|
|
76857
76914
|
);
|
|
76858
76915
|
}
|
|
76859
|
-
const pendingDirectory = (0,
|
|
76916
|
+
const pendingDirectory = (0, import_node_path22.join)(
|
|
76860
76917
|
this.skillsStateDirectory,
|
|
76861
76918
|
"tmp",
|
|
76862
76919
|
`cache-${process.pid}-${(0, import_node_crypto15.randomBytes)(8).toString("hex")}`
|
|
@@ -76877,22 +76934,22 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76877
76934
|
return cacheDirectory;
|
|
76878
76935
|
}
|
|
76879
76936
|
async project(entry, cacheDirectory) {
|
|
76880
|
-
const destination = (0,
|
|
76937
|
+
const destination = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.runtimeDirectory);
|
|
76881
76938
|
const existing = await readMarker(destination);
|
|
76882
76939
|
if (existing?.skillId === entry.skillId && existing.versionId === entry.versionId && existing.contentHash === entry.contentHash && await packageMatches(destination, entry.contentHash)) {
|
|
76883
76940
|
await this.ensureCompatibilityProjection(entry, destination);
|
|
76884
76941
|
return entry.contentHash;
|
|
76885
76942
|
}
|
|
76886
76943
|
const suffix = `${process.pid}-${(0, import_node_crypto15.randomBytes)(8).toString("hex")}`;
|
|
76887
|
-
const pending = (0,
|
|
76888
|
-
const backup = (0,
|
|
76944
|
+
const pending = (0, import_node_path22.join)(this.managedSkillsDirectory, `.pending-${suffix}`);
|
|
76945
|
+
const backup = (0, import_node_path22.join)(this.managedSkillsDirectory, `.backup-${suffix}`);
|
|
76889
76946
|
let movedExisting = false;
|
|
76890
76947
|
let installedPending = false;
|
|
76891
76948
|
let completed = false;
|
|
76892
76949
|
try {
|
|
76893
76950
|
await (0, import_promises5.cp)(cacheDirectory, pending, { recursive: true, errorOnExist: true, force: false });
|
|
76894
76951
|
await (0, import_promises5.writeFile)(
|
|
76895
|
-
(0,
|
|
76952
|
+
(0, import_node_path22.join)(pending, ".alan-managed.json"),
|
|
76896
76953
|
`${JSON.stringify(markerFor(entry), null, 2)}
|
|
76897
76954
|
`,
|
|
76898
76955
|
{ encoding: "utf8", flag: "wx", mode: 384 }
|
|
@@ -76933,7 +76990,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76933
76990
|
}
|
|
76934
76991
|
}
|
|
76935
76992
|
async requireReplaceable(entry) {
|
|
76936
|
-
const destination = (0,
|
|
76993
|
+
const destination = (0, import_node_path22.join)(this.managedSkillsDirectory, entry.runtimeDirectory);
|
|
76937
76994
|
if (!await pathExists2(destination)) return;
|
|
76938
76995
|
const marker = await readMarker(destination);
|
|
76939
76996
|
if (!marker) throw unmanagedPathConflict(entry.runtimeDirectory);
|
|
@@ -76950,8 +77007,8 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76950
77007
|
if (!this.store.inspect().canRemoveManagedFiles) return failures;
|
|
76951
77008
|
for (const [runtimeDirectory, recorded] of Object.entries(this.store.projections())) {
|
|
76952
77009
|
if (desired[runtimeDirectory]) continue;
|
|
76953
|
-
const destination = (0,
|
|
76954
|
-
const compatibility = (0,
|
|
77010
|
+
const destination = (0, import_node_path22.join)(this.managedSkillsDirectory, runtimeDirectory);
|
|
77011
|
+
const compatibility = (0, import_node_path22.join)(this.compatibilitySkillsDirectory, runtimeDirectory);
|
|
76955
77012
|
const marker = await readMarker(destination);
|
|
76956
77013
|
if (!await pathExists2(destination)) continue;
|
|
76957
77014
|
if (marker && markerMatchesProjection(marker, recorded)) {
|
|
@@ -76982,7 +77039,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76982
77039
|
}
|
|
76983
77040
|
async ensureCompatibilityProjection(entry, canonicalDirectory) {
|
|
76984
77041
|
await (0, import_promises5.mkdir)(this.compatibilitySkillsDirectory, { recursive: true, mode: 448 });
|
|
76985
|
-
const destination = (0,
|
|
77042
|
+
const destination = (0, import_node_path22.join)(this.compatibilitySkillsDirectory, entry.runtimeDirectory);
|
|
76986
77043
|
if (await pathExists2(destination)) {
|
|
76987
77044
|
if (await compatibilityProjectionMatches(destination, canonicalDirectory, entry)) return;
|
|
76988
77045
|
throw unmanagedCompatibilityConflict(entry.runtimeDirectory);
|
|
@@ -76997,7 +77054,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
76997
77054
|
try {
|
|
76998
77055
|
await (0, import_promises5.cp)(canonicalDirectory, pending, { recursive: true, errorOnExist: true, force: false });
|
|
76999
77056
|
await (0, import_promises5.writeFile)(
|
|
77000
|
-
(0,
|
|
77057
|
+
(0, import_node_path22.join)(pending, ".alan-compatibility.json"),
|
|
77001
77058
|
`${JSON.stringify({ ...markerFor(entry), canonicalDirectory }, null, 2)}
|
|
77002
77059
|
`,
|
|
77003
77060
|
{ encoding: "utf8", flag: "wx", mode: 384 }
|
|
@@ -77022,14 +77079,14 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
|
|
|
77022
77079
|
}
|
|
77023
77080
|
async withMachineLock(work) {
|
|
77024
77081
|
await (0, import_promises5.mkdir)(this.skillsStateDirectory, { recursive: true, mode: 448 });
|
|
77025
|
-
const lockDirectory = (0,
|
|
77082
|
+
const lockDirectory = (0, import_node_path22.join)(this.skillsStateDirectory, "manager.lock");
|
|
77026
77083
|
const deadline = Date.now() + 3e4;
|
|
77027
77084
|
while (true) {
|
|
77028
77085
|
try {
|
|
77029
77086
|
await (0, import_promises5.mkdir)(lockDirectory, { mode: 448 });
|
|
77030
77087
|
try {
|
|
77031
77088
|
await (0, import_promises5.writeFile)(
|
|
77032
|
-
(0,
|
|
77089
|
+
(0, import_node_path22.join)(lockDirectory, "owner.json"),
|
|
77033
77090
|
`${JSON.stringify({ pid: process.pid, acquiredAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
77034
77091
|
`,
|
|
77035
77092
|
{ encoding: "utf8", flag: "wx", mode: 384 }
|
|
@@ -77079,7 +77136,7 @@ async function packageMatches(directory, expectedHash) {
|
|
|
77079
77136
|
async function readMarker(directory) {
|
|
77080
77137
|
try {
|
|
77081
77138
|
const value2 = JSON.parse(
|
|
77082
|
-
await (0, import_promises5.readFile)((0,
|
|
77139
|
+
await (0, import_promises5.readFile)((0, import_node_path22.join)(directory, ".alan-managed.json"), "utf8")
|
|
77083
77140
|
);
|
|
77084
77141
|
if (typeof value2 !== "object" || value2 === null || !("protocolVersion" in value2) || value2.protocolVersion !== SKILLS_PROTOCOL_VERSION || !("skillId" in value2) || typeof value2.skillId !== "string" || !("versionId" in value2) || typeof value2.versionId !== "string" || !("contentHash" in value2) || typeof value2.contentHash !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value2.contentHash)) {
|
|
77085
77142
|
return null;
|
|
@@ -77093,7 +77150,7 @@ async function compatibilityProjectionMatches(destination, canonicalDirectory, e
|
|
|
77093
77150
|
const metadata = await (0, import_promises5.lstat)(destination);
|
|
77094
77151
|
if (metadata.isSymbolicLink()) {
|
|
77095
77152
|
const target = await (0, import_promises5.readlink)(destination);
|
|
77096
|
-
return (0,
|
|
77153
|
+
return (0, import_node_path22.resolve)((0, import_node_path22.dirname)(destination), target) === (0, import_node_path22.resolve)(canonicalDirectory);
|
|
77097
77154
|
}
|
|
77098
77155
|
if (!metadata.isDirectory()) return false;
|
|
77099
77156
|
const marker = await readCompatibilityMarker(destination);
|
|
@@ -77104,7 +77161,7 @@ async function removeCompatibilityProjection(destination, canonicalDirectory, pr
|
|
|
77104
77161
|
const metadata = await (0, import_promises5.lstat)(destination);
|
|
77105
77162
|
if (metadata.isSymbolicLink()) {
|
|
77106
77163
|
const target = await (0, import_promises5.readlink)(destination);
|
|
77107
|
-
if ((0,
|
|
77164
|
+
if ((0, import_node_path22.resolve)((0, import_node_path22.dirname)(destination), target) !== (0, import_node_path22.resolve)(canonicalDirectory)) return false;
|
|
77108
77165
|
await (0, import_promises5.rm)(destination, { force: true });
|
|
77109
77166
|
return true;
|
|
77110
77167
|
}
|
|
@@ -77116,7 +77173,7 @@ async function removeCompatibilityProjection(destination, canonicalDirectory, pr
|
|
|
77116
77173
|
async function readCompatibilityMarker(directory) {
|
|
77117
77174
|
try {
|
|
77118
77175
|
const value2 = JSON.parse(
|
|
77119
|
-
await (0, import_promises5.readFile)((0,
|
|
77176
|
+
await (0, import_promises5.readFile)((0, import_node_path22.join)(directory, ".alan-compatibility.json"), "utf8")
|
|
77120
77177
|
);
|
|
77121
77178
|
if (value2.protocolVersion !== SKILLS_PROTOCOL_VERSION || typeof value2.skillId !== "string" || typeof value2.versionId !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value2.contentHash) || typeof value2.canonicalDirectory !== "string") {
|
|
77122
77179
|
return null;
|
|
@@ -77156,7 +77213,7 @@ async function legacyFileMatches(directory, expectedHash) {
|
|
|
77156
77213
|
try {
|
|
77157
77214
|
const metadata = await (0, import_promises5.lstat)(directory);
|
|
77158
77215
|
if (!metadata.isDirectory() || metadata.isSymbolicLink()) return false;
|
|
77159
|
-
const content = await (0, import_promises5.readFile)((0,
|
|
77216
|
+
const content = await (0, import_promises5.readFile)((0, import_node_path22.join)(directory, "SKILL.md"));
|
|
77160
77217
|
return (0, import_node_crypto15.createHash)("sha256").update(content).digest("hex").slice(0, 16) === expectedHash;
|
|
77161
77218
|
} catch {
|
|
77162
77219
|
return false;
|
|
@@ -77164,7 +77221,7 @@ async function legacyFileMatches(directory, expectedHash) {
|
|
|
77164
77221
|
}
|
|
77165
77222
|
async function removeExactLegacySkill(directory, expectedHash) {
|
|
77166
77223
|
if (!await legacyFileMatches(directory, expectedHash)) return;
|
|
77167
|
-
await (0, import_promises5.rm)((0,
|
|
77224
|
+
await (0, import_promises5.rm)((0, import_node_path22.join)(directory, "SKILL.md"), { force: true });
|
|
77168
77225
|
const remaining = await (0, import_promises5.readdir)(directory);
|
|
77169
77226
|
if (remaining.length === 0) await (0, import_promises5.rm)(directory, { recursive: true, force: true });
|
|
77170
77227
|
}
|
|
@@ -77324,13 +77381,13 @@ async function startDaemon(args) {
|
|
|
77324
77381
|
getRuntimeToken: () => runtimeToken
|
|
77325
77382
|
});
|
|
77326
77383
|
const runtimeSkillManager = await RuntimeSkillManager.open({
|
|
77327
|
-
homeDirectory: (0,
|
|
77384
|
+
homeDirectory: (0, import_node_os11.homedir)(),
|
|
77328
77385
|
controlClient: skillControl
|
|
77329
77386
|
});
|
|
77330
77387
|
const runtimeSkillCoordinator = new RuntimeSkillCoordinator(
|
|
77331
77388
|
runtimeSkillManager,
|
|
77332
77389
|
skillControl,
|
|
77333
|
-
(input2) => resolveSkillScanInput((0,
|
|
77390
|
+
(input2) => resolveSkillScanInput((0, import_node_os11.homedir)(), input2)
|
|
77334
77391
|
);
|
|
77335
77392
|
const runSkillSync = (reason) => {
|
|
77336
77393
|
const operation = reason === "startup" ? runtimeSkillCoordinator.runStartup() : reason === "interval" ? runtimeSkillCoordinator.runIncremental() : reason === "refresh" ? runtimeSkillCoordinator.runAudit() : runtimeSkillCoordinator.run();
|
|
@@ -77404,10 +77461,10 @@ async function startDaemon(args) {
|
|
|
77404
77461
|
installationId
|
|
77405
77462
|
});
|
|
77406
77463
|
const recentLogs = [];
|
|
77407
|
-
const daemonLogPath = (0,
|
|
77464
|
+
const daemonLogPath = (0, import_node_path23.join)((0, import_node_path23.dirname)(configPath), "logs", "daemon.log");
|
|
77408
77465
|
const persistDaemonLog = (line) => {
|
|
77409
77466
|
try {
|
|
77410
|
-
(0, import_node_fs20.mkdirSync)((0,
|
|
77467
|
+
(0, import_node_fs20.mkdirSync)((0, import_node_path23.dirname)(daemonLogPath), { recursive: true });
|
|
77411
77468
|
try {
|
|
77412
77469
|
if ((0, import_node_fs20.statSync)(daemonLogPath).size > 5 * 1024 * 1024) {
|
|
77413
77470
|
(0, import_node_fs20.renameSync)(daemonLogPath, `${daemonLogPath}.1`);
|
|
@@ -77539,7 +77596,7 @@ async function startDaemon(args) {
|
|
|
77539
77596
|
};
|
|
77540
77597
|
for (const relocation of stored.workspaceRelocations ?? []) {
|
|
77541
77598
|
if (relocation?.conversationId && relocation.runId && relocation.previousPath && relocation.canonicalPath) {
|
|
77542
|
-
workspaceRelocations.set((0,
|
|
77599
|
+
workspaceRelocations.set((0, import_node_path23.resolve)(relocation.previousPath), relocation);
|
|
77543
77600
|
}
|
|
77544
77601
|
}
|
|
77545
77602
|
if (stored.localApiPort !== localApiPort || stored.localApiToken !== localApiToken || stored.localServiceId !== localServiceId || stored.localServiceSecret !== localServiceSecret || stored.eventSpoolKey !== eventSpoolKey || stored.daemonEpoch !== daemonEpoch || stored.installationId !== installationId) {
|
|
@@ -78247,7 +78304,7 @@ async function setupDaemon(args) {
|
|
|
78247
78304
|
const teamId = argValue(args, "--team") ?? process.env.ALAN_TEAM_ID;
|
|
78248
78305
|
const setupToken = argValue(args, "--setup-token") ?? process.env.ALAN_RUNTIME_SETUP_TOKEN;
|
|
78249
78306
|
const token = argValue(args, "--token") ?? process.env.ALAN_SETUP_TOKEN;
|
|
78250
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
78307
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os12.hostname)();
|
|
78251
78308
|
const scope = argValue(args, "--scope") ?? process.env.ALAN_RUNTIME_SCOPE ?? (setupToken ? "team" : "user");
|
|
78252
78309
|
const installationId = argValue(args, "--installation-id") ?? previousConfig.installationId ?? (0, import_node_crypto17.randomUUID)();
|
|
78253
78310
|
if (scope !== "team" && scope !== "user") {
|
|
@@ -78270,7 +78327,7 @@ async function setupDaemon(args) {
|
|
|
78270
78327
|
...teamId ? { teamId } : {},
|
|
78271
78328
|
...setupToken ? { setupToken, registrationAttemptId } : {},
|
|
78272
78329
|
displayName,
|
|
78273
|
-
hostname: (0,
|
|
78330
|
+
hostname: (0, import_node_os12.hostname)(),
|
|
78274
78331
|
runtimeKind: "machine",
|
|
78275
78332
|
managementKind: "user_managed",
|
|
78276
78333
|
hostKind: "daemon",
|
|
@@ -78354,7 +78411,7 @@ async function loginWithDeviceCode(args) {
|
|
|
78354
78411
|
}
|
|
78355
78412
|
const previousConfig = readConfigForRegistration();
|
|
78356
78413
|
const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
|
|
78357
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
78414
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os12.hostname)();
|
|
78358
78415
|
const maxPolls = Number.parseInt(argValue(args, "--max-polls") ?? "300", 10);
|
|
78359
78416
|
const resumed = readPendingDeviceAuthorization(apiUrl);
|
|
78360
78417
|
const installationId = resumed?.installationId ?? previousConfig.installationId ?? (0, import_node_crypto17.randomUUID)();
|
|
@@ -78366,7 +78423,7 @@ async function loginWithDeviceCode(args) {
|
|
|
78366
78423
|
headers: { "content-type": "application/json" },
|
|
78367
78424
|
body: JSON.stringify({
|
|
78368
78425
|
displayName,
|
|
78369
|
-
hostname: (0,
|
|
78426
|
+
hostname: (0, import_node_os12.hostname)(),
|
|
78370
78427
|
capabilities: discoverCapabilities(),
|
|
78371
78428
|
metadata: {
|
|
78372
78429
|
...await collectRuntimeMetadataWithProviderLimits(),
|
|
@@ -78790,25 +78847,18 @@ async function printDoctor(args = []) {
|
|
|
78790
78847
|
// src/mcp-config-adapters.ts
|
|
78791
78848
|
var import_node_crypto18 = require("crypto");
|
|
78792
78849
|
var import_node_fs21 = require("fs");
|
|
78793
|
-
var
|
|
78794
|
-
var
|
|
78850
|
+
var import_node_os13 = require("os");
|
|
78851
|
+
var import_node_path24 = require("path");
|
|
78795
78852
|
var log = {
|
|
78796
78853
|
info: (...args) => console.info("[mcp-config-adapters]", ...args),
|
|
78797
78854
|
warn: (...args) => console.warn("[mcp-config-adapters]", ...args),
|
|
78798
78855
|
debug: () => {
|
|
78799
78856
|
}
|
|
78800
78857
|
};
|
|
78801
|
-
var
|
|
78802
|
-
|
|
78803
|
-
|
|
78804
|
-
|
|
78805
|
-
cursor: (0, import_node_path23.join)(HOME, ".cursor", "mcp.json"),
|
|
78806
|
-
antigravity: (0, import_node_path23.join)(HOME, ".gemini", "config", "mcp_config.json"),
|
|
78807
|
-
kimi: (0, import_node_path23.join)(HOME, ".kimi", "mcp.json"),
|
|
78808
|
-
opencode: (0, import_node_path23.join)(HOME, ".config", "opencode", "opencode.json"),
|
|
78809
|
-
factory: (0, import_node_path23.join)(HOME, ".factory", "mcp.json"),
|
|
78810
|
-
amp: (0, import_node_path23.join)(HOME, ".config", "amp", "settings.json")
|
|
78811
|
-
};
|
|
78858
|
+
var homeDirectoryOverride;
|
|
78859
|
+
function homeDirectory() {
|
|
78860
|
+
return homeDirectoryOverride ?? (0, import_node_os13.homedir)();
|
|
78861
|
+
}
|
|
78812
78862
|
var MalformedToolConfigError = class extends Error {
|
|
78813
78863
|
};
|
|
78814
78864
|
function parseJsonSafe2(content) {
|
|
@@ -78826,7 +78876,7 @@ function readFileOr(path2) {
|
|
|
78826
78876
|
return (0, import_node_fs21.existsSync)(path2) ? (0, import_node_fs21.readFileSync)(path2, "utf-8") : null;
|
|
78827
78877
|
}
|
|
78828
78878
|
function acquireConfigLock2(path2) {
|
|
78829
|
-
(0, import_node_fs21.mkdirSync)((0,
|
|
78879
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path24.dirname)(path2), { recursive: true });
|
|
78830
78880
|
const lockPath = `${path2}.alan-lock`;
|
|
78831
78881
|
const startedAt = Date.now();
|
|
78832
78882
|
while (true) {
|
|
@@ -78852,7 +78902,7 @@ function acquireConfigLock2(path2) {
|
|
|
78852
78902
|
}
|
|
78853
78903
|
}
|
|
78854
78904
|
function writeFileSafe2(path2, content) {
|
|
78855
|
-
(0, import_node_fs21.mkdirSync)((0,
|
|
78905
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path24.dirname)(path2), { recursive: true });
|
|
78856
78906
|
const pendingPath = `${path2}.alan-pending-${process.pid}-${(0, import_node_crypto18.randomBytes)(6).toString("hex")}`;
|
|
78857
78907
|
try {
|
|
78858
78908
|
(0, import_node_fs21.writeFileSync)(pendingPath, content, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
@@ -78869,9 +78919,12 @@ function saveMalformedBackup2(path2, content) {
|
|
|
78869
78919
|
}
|
|
78870
78920
|
var claudeAdapter = {
|
|
78871
78921
|
cli: "Claude Code",
|
|
78872
|
-
configPath
|
|
78873
|
-
|
|
78874
|
-
|
|
78922
|
+
get configPath() {
|
|
78923
|
+
return (0, import_node_path24.join)(homeDirectory(), ".claude.json");
|
|
78924
|
+
},
|
|
78925
|
+
get guardDir() {
|
|
78926
|
+
return homeDirectory();
|
|
78927
|
+
},
|
|
78875
78928
|
merge(existing, servers) {
|
|
78876
78929
|
const config2 = parseJsonSafe2(existing);
|
|
78877
78930
|
const mcpServers = config2.mcpServers ?? {};
|
|
@@ -78899,8 +78952,12 @@ var claudeAdapter = {
|
|
|
78899
78952
|
};
|
|
78900
78953
|
var codexAdapter = {
|
|
78901
78954
|
cli: "Codex",
|
|
78902
|
-
configPath
|
|
78903
|
-
|
|
78955
|
+
get configPath() {
|
|
78956
|
+
return (0, import_node_path24.join)(homeDirectory(), ".codex", "config.toml");
|
|
78957
|
+
},
|
|
78958
|
+
get guardDir() {
|
|
78959
|
+
return (0, import_node_path24.join)(homeDirectory(), ".codex");
|
|
78960
|
+
},
|
|
78904
78961
|
merge(existing, servers) {
|
|
78905
78962
|
let config2 = {};
|
|
78906
78963
|
if (existing) {
|
|
@@ -78941,8 +78998,12 @@ var codexAdapter = {
|
|
|
78941
78998
|
};
|
|
78942
78999
|
var cursorAdapter = {
|
|
78943
79000
|
cli: "Cursor",
|
|
78944
|
-
configPath
|
|
78945
|
-
|
|
79001
|
+
get configPath() {
|
|
79002
|
+
return (0, import_node_path24.join)(homeDirectory(), ".cursor", "mcp.json");
|
|
79003
|
+
},
|
|
79004
|
+
get guardDir() {
|
|
79005
|
+
return (0, import_node_path24.join)(homeDirectory(), ".cursor");
|
|
79006
|
+
},
|
|
78946
79007
|
merge(existing, servers) {
|
|
78947
79008
|
const config2 = parseJsonSafe2(existing);
|
|
78948
79009
|
const mcpServers = config2.mcpServers ?? {};
|
|
@@ -78971,8 +79032,12 @@ var cursorAdapter = {
|
|
|
78971
79032
|
function createAntigravityAdapter() {
|
|
78972
79033
|
return {
|
|
78973
79034
|
cli: "Antigravity CLI",
|
|
78974
|
-
configPath
|
|
78975
|
-
|
|
79035
|
+
get configPath() {
|
|
79036
|
+
return (0, import_node_path24.join)(homeDirectory(), ".gemini", "config", "mcp_config.json");
|
|
79037
|
+
},
|
|
79038
|
+
get guardDir() {
|
|
79039
|
+
return (0, import_node_path24.join)(homeDirectory(), ".gemini", "config");
|
|
79040
|
+
},
|
|
78976
79041
|
merge(existing, servers) {
|
|
78977
79042
|
const config2 = parseJsonSafe2(existing);
|
|
78978
79043
|
const mcpServers = config2.mcpServers ?? {};
|
|
@@ -79002,8 +79067,12 @@ function createAntigravityAdapter() {
|
|
|
79002
79067
|
var antigravityAdapter = createAntigravityAdapter();
|
|
79003
79068
|
var kimiAdapter = {
|
|
79004
79069
|
cli: "Kimi CLI",
|
|
79005
|
-
configPath
|
|
79006
|
-
|
|
79070
|
+
get configPath() {
|
|
79071
|
+
return (0, import_node_path24.join)(homeDirectory(), ".kimi", "mcp.json");
|
|
79072
|
+
},
|
|
79073
|
+
get guardDir() {
|
|
79074
|
+
return (0, import_node_path24.join)(homeDirectory(), ".kimi");
|
|
79075
|
+
},
|
|
79007
79076
|
merge(existing, servers) {
|
|
79008
79077
|
const config2 = parseJsonSafe2(existing);
|
|
79009
79078
|
const mcpServers = config2.mcpServers ?? {};
|
|
@@ -79031,8 +79100,12 @@ var kimiAdapter = {
|
|
|
79031
79100
|
};
|
|
79032
79101
|
var opencodeAdapter = {
|
|
79033
79102
|
cli: "OpenCode",
|
|
79034
|
-
configPath
|
|
79035
|
-
|
|
79103
|
+
get configPath() {
|
|
79104
|
+
return (0, import_node_path24.join)(homeDirectory(), ".config", "opencode", "opencode.json");
|
|
79105
|
+
},
|
|
79106
|
+
get guardDir() {
|
|
79107
|
+
return (0, import_node_path24.join)(homeDirectory(), ".config", "opencode");
|
|
79108
|
+
},
|
|
79036
79109
|
merge(existing, servers) {
|
|
79037
79110
|
const config2 = parseJsonSafe2(existing);
|
|
79038
79111
|
const mcp = config2.mcp ?? {};
|
|
@@ -79060,8 +79133,12 @@ var opencodeAdapter = {
|
|
|
79060
79133
|
};
|
|
79061
79134
|
var factoryAdapter = {
|
|
79062
79135
|
cli: "Factory Droid",
|
|
79063
|
-
configPath
|
|
79064
|
-
|
|
79136
|
+
get configPath() {
|
|
79137
|
+
return (0, import_node_path24.join)(homeDirectory(), ".factory", "mcp.json");
|
|
79138
|
+
},
|
|
79139
|
+
get guardDir() {
|
|
79140
|
+
return (0, import_node_path24.join)(homeDirectory(), ".factory");
|
|
79141
|
+
},
|
|
79065
79142
|
merge(existing, servers) {
|
|
79066
79143
|
const config2 = parseJsonSafe2(existing);
|
|
79067
79144
|
const mcpServers = config2.mcpServers ?? {};
|
|
@@ -79096,8 +79173,12 @@ var factoryAdapter = {
|
|
|
79096
79173
|
};
|
|
79097
79174
|
var ampAdapter = {
|
|
79098
79175
|
cli: "Amp",
|
|
79099
|
-
configPath
|
|
79100
|
-
|
|
79176
|
+
get configPath() {
|
|
79177
|
+
return (0, import_node_path24.join)(homeDirectory(), ".config", "amp", "settings.json");
|
|
79178
|
+
},
|
|
79179
|
+
get guardDir() {
|
|
79180
|
+
return (0, import_node_path24.join)(homeDirectory(), ".config", "amp");
|
|
79181
|
+
},
|
|
79101
79182
|
merge(existing, servers) {
|
|
79102
79183
|
const config2 = parseJsonSafe2(existing);
|
|
79103
79184
|
const mcpServers = config2["amp.mcpServers"] ?? {};
|
|
@@ -79203,6 +79284,77 @@ function normalizeAlanRuntimeEntry(actual, expected) {
|
|
|
79203
79284
|
function matchesAlanManagedEntry(actual, expected) {
|
|
79204
79285
|
return entriesMatch(actual, expected) || entriesMatch(normalizeAlanRuntimeEntry(actual, expected), expected);
|
|
79205
79286
|
}
|
|
79287
|
+
var LOCAL_ALAN_MCP_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "0.0.0.0"]);
|
|
79288
|
+
var LEGACY_LOCAL_ALAN_MCP_PORTS = /* @__PURE__ */ new Set(["8400"]);
|
|
79289
|
+
var ALAN_MCP_HOST_SUFFIXES = [".tryalan.ai"];
|
|
79290
|
+
function normalizeMcpPathname(pathname) {
|
|
79291
|
+
const trimmed = pathname.replace(/\/+$/, "");
|
|
79292
|
+
return trimmed.length > 0 ? trimmed : "/";
|
|
79293
|
+
}
|
|
79294
|
+
function urlsShareAlanMcpEndpoint(left, right) {
|
|
79295
|
+
try {
|
|
79296
|
+
const a = new URL(left);
|
|
79297
|
+
const b = new URL(right);
|
|
79298
|
+
return a.origin === b.origin && normalizeMcpPathname(a.pathname) === normalizeMcpPathname(b.pathname);
|
|
79299
|
+
} catch {
|
|
79300
|
+
return left === right;
|
|
79301
|
+
}
|
|
79302
|
+
}
|
|
79303
|
+
function configuredAlanMcpUrlsFromEnv() {
|
|
79304
|
+
const urls = [];
|
|
79305
|
+
for (const raw of [
|
|
79306
|
+
process.env.ALAN_MCP_DESKTOP_URL,
|
|
79307
|
+
process.env.ALAN_MCP_PUBLIC_URL,
|
|
79308
|
+
process.env.ALAN_LOCAL_API_URL
|
|
79309
|
+
]) {
|
|
79310
|
+
const value2 = raw?.trim();
|
|
79311
|
+
if (!value2) continue;
|
|
79312
|
+
try {
|
|
79313
|
+
const parsed = new URL(value2);
|
|
79314
|
+
if (normalizeMcpPathname(parsed.pathname) === "/mcp") {
|
|
79315
|
+
urls.push(parsed.toString());
|
|
79316
|
+
continue;
|
|
79317
|
+
}
|
|
79318
|
+
parsed.pathname = "/mcp";
|
|
79319
|
+
urls.push(parsed.toString());
|
|
79320
|
+
} catch {
|
|
79321
|
+
urls.push(value2.endsWith("/mcp") ? value2 : `${value2.replace(/\/$/, "")}/mcp`);
|
|
79322
|
+
}
|
|
79323
|
+
}
|
|
79324
|
+
return urls;
|
|
79325
|
+
}
|
|
79326
|
+
function extractHttpUrlFromEntry(entry) {
|
|
79327
|
+
if (!entry || typeof entry !== "object") return void 0;
|
|
79328
|
+
const record2 = entry;
|
|
79329
|
+
for (const key of ["url", "serverUrl"]) {
|
|
79330
|
+
const value2 = record2[key];
|
|
79331
|
+
if (typeof value2 === "string" && value2.length > 0) return value2;
|
|
79332
|
+
}
|
|
79333
|
+
for (const value2 of Object.values(record2)) {
|
|
79334
|
+
if (!value2 || typeof value2 !== "object") continue;
|
|
79335
|
+
const nested = extractHttpUrlFromEntry(value2);
|
|
79336
|
+
if (nested) return nested;
|
|
79337
|
+
}
|
|
79338
|
+
return void 0;
|
|
79339
|
+
}
|
|
79340
|
+
function isAlanSelfRegistrationEntry(entry) {
|
|
79341
|
+
const url3 = extractHttpUrlFromEntry(entry);
|
|
79342
|
+
if (!url3) return false;
|
|
79343
|
+
try {
|
|
79344
|
+
const parsed = new URL(url3);
|
|
79345
|
+
if (normalizeMcpPathname(parsed.pathname) !== "/mcp") return false;
|
|
79346
|
+
const host = parsed.hostname.toLowerCase();
|
|
79347
|
+
if (LOCAL_ALAN_MCP_HOSTS.has(host) && LEGACY_LOCAL_ALAN_MCP_PORTS.has(parsed.port)) {
|
|
79348
|
+
return true;
|
|
79349
|
+
}
|
|
79350
|
+
if (ALAN_MCP_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix))) return true;
|
|
79351
|
+
return configuredAlanMcpUrlsFromEnv().some(
|
|
79352
|
+
(configured) => urlsShareAlanMcpEndpoint(configured, url3)
|
|
79353
|
+
);
|
|
79354
|
+
} catch {
|
|
79355
|
+
return false;
|
|
79356
|
+
}
|
|
79357
|
+
}
|
|
79206
79358
|
function hasAlanManagedSignature(entry) {
|
|
79207
79359
|
if (!entry || typeof entry !== "object") return false;
|
|
79208
79360
|
for (const [key, value2] of Object.entries(entry)) {
|
|
@@ -79223,6 +79375,9 @@ function expectedServerEntry(adapter, server) {
|
|
|
79223
79375
|
function isManagedServerList(entries) {
|
|
79224
79376
|
return entries.length === 0 || typeof entries[0] !== "string";
|
|
79225
79377
|
}
|
|
79378
|
+
function isAlanOwnedMcpEntry(entry, desiredEntry, previousEntry) {
|
|
79379
|
+
return hasAlanManagedSignature(entry) || isAlanSelfRegistrationEntry(entry) || matchesAlanManagedEntry(entry, desiredEntry) || previousEntry !== void 0 && matchesAlanManagedEntry(entry, previousEntry);
|
|
79380
|
+
}
|
|
79226
79381
|
function syncMcpToAllClis(servers, oldManagedServers = []) {
|
|
79227
79382
|
const written = [];
|
|
79228
79383
|
const failures = [];
|
|
@@ -79237,6 +79392,7 @@ function syncMcpToAllClis(servers, oldManagedServers = []) {
|
|
|
79237
79392
|
try {
|
|
79238
79393
|
const existing = readFileOr(adapter.configPath);
|
|
79239
79394
|
const previousServers = isManagedServerList(oldManagedServers) ? oldManagedServers : [];
|
|
79395
|
+
const previousNames = isManagedServerList(oldManagedServers) ? oldManagedServers.map((server) => server.name) : oldManagedServers;
|
|
79240
79396
|
const previousByName = new Map(previousServers.map((server) => [server.name, server]));
|
|
79241
79397
|
if (existing) {
|
|
79242
79398
|
for (const server of servers) {
|
|
@@ -79245,21 +79401,20 @@ function syncMcpToAllClis(servers, oldManagedServers = []) {
|
|
|
79245
79401
|
const desiredEntry = expectedServerEntry(adapter, server);
|
|
79246
79402
|
const previous = previousByName.get(server.name);
|
|
79247
79403
|
const previousEntry = previous ? expectedServerEntry(adapter, previous) : void 0;
|
|
79248
|
-
if (!
|
|
79404
|
+
if (!isAlanOwnedMcpEntry(currentEntry, desiredEntry, previousEntry)) {
|
|
79249
79405
|
throw new Error(`an unowned entry already uses the name ${server.name}`);
|
|
79250
79406
|
}
|
|
79251
79407
|
}
|
|
79252
79408
|
}
|
|
79253
79409
|
const currentNames = new Set(servers.map((s) => s.name));
|
|
79254
|
-
const toRemove =
|
|
79410
|
+
const toRemove = previousNames.filter((name) => !currentNames.has(name));
|
|
79255
79411
|
let content;
|
|
79256
79412
|
if (toRemove.length > 0) {
|
|
79257
|
-
const ownedNames = existing ? toRemove.filter(
|
|
79258
|
-
(
|
|
79259
|
-
|
|
79260
|
-
|
|
79261
|
-
|
|
79262
|
-
).map((server) => server.name) : [];
|
|
79413
|
+
const ownedNames = existing ? toRemove.filter((name) => {
|
|
79414
|
+
const entry = serverEntry(adapter, existing, name);
|
|
79415
|
+
const previous = previousByName.get(name);
|
|
79416
|
+
return hasAlanManagedSignature(entry) || isAlanSelfRegistrationEntry(entry) || previous !== void 0 && matchesAlanManagedEntry(entry, expectedServerEntry(adapter, previous));
|
|
79417
|
+
}) : [];
|
|
79263
79418
|
const cleaned = adapter.remove(existing, ownedNames);
|
|
79264
79419
|
content = adapter.merge(cleaned, servers);
|
|
79265
79420
|
} else {
|
|
@@ -79344,7 +79499,9 @@ function inspectAlanMcpPresence(expectedServers = [], candidateNames = DEFAULT_A
|
|
|
79344
79499
|
if (entry === void 0) continue;
|
|
79345
79500
|
const expected = expectedByName.get(name);
|
|
79346
79501
|
const matchesExpected = expected ? matchesAlanManagedEntry(entry, expectedServerEntry(adapter, expected)) : false;
|
|
79347
|
-
if (!hasAlanManagedSignature(entry) && !matchesExpected)
|
|
79502
|
+
if (!hasAlanManagedSignature(entry) && !matchesExpected && !isAlanSelfRegistrationEntry(entry)) {
|
|
79503
|
+
continue;
|
|
79504
|
+
}
|
|
79348
79505
|
foundOnCli = true;
|
|
79349
79506
|
serverNamesFound.add(name);
|
|
79350
79507
|
}
|
|
@@ -79392,7 +79549,8 @@ var McpSyncService = class {
|
|
|
79392
79549
|
managedServerNames;
|
|
79393
79550
|
legacyServerNames;
|
|
79394
79551
|
getStatus() {
|
|
79395
|
-
const
|
|
79552
|
+
const candidateNames = [.../* @__PURE__ */ new Set([...this.managedServerNames, ...this.legacyServerNames])];
|
|
79553
|
+
const presence = inspectAlanMcpPresence([], candidateNames);
|
|
79396
79554
|
return {
|
|
79397
79555
|
configured: presence.configured,
|
|
79398
79556
|
lastSyncAt: null,
|
|
@@ -79444,8 +79602,12 @@ var McpSyncService = class {
|
|
|
79444
79602
|
|
|
79445
79603
|
// src/native-hook-config.ts
|
|
79446
79604
|
var import_node_fs22 = require("fs");
|
|
79447
|
-
var
|
|
79448
|
-
var
|
|
79605
|
+
var import_node_os14 = require("os");
|
|
79606
|
+
var import_node_path25 = require("path");
|
|
79607
|
+
var ALAN_HOOK_MARKER = "# alan-native-session-hook";
|
|
79608
|
+
var ALAN_KIMI_HOOKS_START = "# alan-native-session-hooks:start";
|
|
79609
|
+
var ALAN_KIMI_HOOKS_END = "# alan-native-session-hooks:end";
|
|
79610
|
+
var ALAN_OPENCODE_PLUGIN_MARKER = "// alan-native-session-plugin";
|
|
79449
79611
|
var CLAUDE_HOOK_EVENTS = [
|
|
79450
79612
|
"SessionStart",
|
|
79451
79613
|
"UserPromptSubmit",
|
|
@@ -79455,15 +79617,59 @@ var CLAUDE_HOOK_EVENTS = [
|
|
|
79455
79617
|
"SubagentStop",
|
|
79456
79618
|
"SessionEnd"
|
|
79457
79619
|
];
|
|
79458
|
-
var
|
|
79620
|
+
var CODEX_HOOK_EVENTS = [
|
|
79621
|
+
"SessionStart",
|
|
79622
|
+
"UserPromptSubmit",
|
|
79623
|
+
"PostToolUse",
|
|
79624
|
+
"Stop",
|
|
79625
|
+
"SubagentStart",
|
|
79626
|
+
"SubagentStop",
|
|
79627
|
+
"SessionEnd"
|
|
79628
|
+
];
|
|
79629
|
+
var COPILOT_HOOK_EVENTS = [
|
|
79630
|
+
"SessionStart",
|
|
79631
|
+
"UserPromptSubmit",
|
|
79632
|
+
"PostToolUse",
|
|
79633
|
+
"Stop",
|
|
79634
|
+
"SubagentStop",
|
|
79635
|
+
"SessionEnd"
|
|
79636
|
+
];
|
|
79637
|
+
var CURSOR_HOOK_EVENTS = [
|
|
79638
|
+
"sessionStart",
|
|
79639
|
+
"beforeSubmitPrompt",
|
|
79640
|
+
"afterAgentResponse",
|
|
79641
|
+
"stop",
|
|
79642
|
+
"sessionEnd"
|
|
79643
|
+
];
|
|
79644
|
+
var KIMI_HOOK_EVENTS = [
|
|
79645
|
+
"SessionStart",
|
|
79646
|
+
"UserPromptSubmit",
|
|
79647
|
+
"PostToolUse",
|
|
79648
|
+
"Stop",
|
|
79649
|
+
"Interrupt",
|
|
79650
|
+
"SubagentStart",
|
|
79651
|
+
"SubagentStop",
|
|
79652
|
+
"SessionEnd"
|
|
79653
|
+
];
|
|
79654
|
+
var GROK_HOOK_EVENTS = [
|
|
79655
|
+
"SessionStart",
|
|
79656
|
+
"UserPromptSubmit",
|
|
79657
|
+
"PostToolUse",
|
|
79658
|
+
"Stop",
|
|
79659
|
+
"StopFailure",
|
|
79660
|
+
"StopCancelled",
|
|
79661
|
+
"SubagentStart",
|
|
79662
|
+
"SubagentStop",
|
|
79663
|
+
"SessionEnd"
|
|
79664
|
+
];
|
|
79459
79665
|
function shellQuote(value2) {
|
|
79460
79666
|
return `'${value2.replaceAll("'", `'\\''`)}'`;
|
|
79461
79667
|
}
|
|
79462
79668
|
function powershellQuote(value2) {
|
|
79463
79669
|
return `'${value2.replaceAll("'", "''")}'`;
|
|
79464
79670
|
}
|
|
79465
|
-
function
|
|
79466
|
-
|
|
79671
|
+
function hookArgs(input2) {
|
|
79672
|
+
return [
|
|
79467
79673
|
input2.cliEntry,
|
|
79468
79674
|
"hook",
|
|
79469
79675
|
"--config-path",
|
|
@@ -79474,21 +79680,23 @@ function nativeHookCommand(input2) {
|
|
|
79474
79680
|
input2.event,
|
|
79475
79681
|
ALAN_HOOK_MARKER
|
|
79476
79682
|
];
|
|
79477
|
-
|
|
79478
|
-
|
|
79683
|
+
}
|
|
79684
|
+
function checkedEnvironment(environment) {
|
|
79685
|
+
const entries = Object.entries(environment ?? {});
|
|
79686
|
+
for (const [key] of entries) {
|
|
79479
79687
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
79480
79688
|
throw new Error(`Invalid native hook environment variable: ${key}`);
|
|
79481
79689
|
}
|
|
79482
79690
|
}
|
|
79691
|
+
return entries;
|
|
79692
|
+
}
|
|
79693
|
+
function nativeHookCommand(input2) {
|
|
79694
|
+
const args = hookArgs(input2);
|
|
79695
|
+
const environment = checkedEnvironment(input2.environment);
|
|
79483
79696
|
if (environment.length === 0) {
|
|
79484
|
-
return {
|
|
79485
|
-
type: "command",
|
|
79486
|
-
command: input2.nodeExecutable,
|
|
79487
|
-
args,
|
|
79488
|
-
timeout: 5
|
|
79489
|
-
};
|
|
79697
|
+
return { type: "command", command: input2.nodeExecutable, args, timeout: 5 };
|
|
79490
79698
|
}
|
|
79491
|
-
if ((input2.platform ?? (0,
|
|
79699
|
+
if ((input2.platform ?? (0, import_node_os14.platform)()) === "win32") {
|
|
79492
79700
|
const environmentPrefix2 = environment.map(([key, value2]) => `$env:${key}=${powershellQuote(value2)}`).join("; ");
|
|
79493
79701
|
const command2 = [input2.nodeExecutable, ...args].map(powershellQuote).join(" ");
|
|
79494
79702
|
return {
|
|
@@ -79507,7 +79715,40 @@ function nativeHookCommand(input2) {
|
|
|
79507
79715
|
timeout: 5
|
|
79508
79716
|
};
|
|
79509
79717
|
}
|
|
79510
|
-
function
|
|
79718
|
+
function nativeShellCommand(runtime, provider, event, platform6 = runtime.platform) {
|
|
79719
|
+
const args = hookArgs({
|
|
79720
|
+
configPath: runtime.configPath,
|
|
79721
|
+
cliEntry: runtime.cliEntry,
|
|
79722
|
+
provider,
|
|
79723
|
+
event
|
|
79724
|
+
});
|
|
79725
|
+
const environment = checkedEnvironment(runtime.environment);
|
|
79726
|
+
if (platform6 === "win32") {
|
|
79727
|
+
const prefix2 = environment.map(([key, value2]) => `$env:${key}=${powershellQuote(value2)}`).join("; ");
|
|
79728
|
+
const command2 = `& ${[runtime.nodeExecutable, ...args].map(powershellQuote).join(" ")}`;
|
|
79729
|
+
return prefix2 ? `${prefix2}; ${command2}` : command2;
|
|
79730
|
+
}
|
|
79731
|
+
const prefix = environment.map(([key, value2]) => `${key}=${shellQuote(value2)}`).join(" ");
|
|
79732
|
+
const command = [runtime.nodeExecutable, ...args].map(shellQuote).join(" ");
|
|
79733
|
+
return prefix ? `${prefix} ${command}` : command;
|
|
79734
|
+
}
|
|
79735
|
+
function resolveRuntime(input2 = {}) {
|
|
79736
|
+
const cliEntry = input2.cliEntry ?? process.argv[1];
|
|
79737
|
+
const configPath = input2.configPath ?? process.env.ALAN_AGENT_CONFIG_PATH;
|
|
79738
|
+
if (!cliEntry) throw new Error("Cannot resolve the alan-agent CLI entrypoint");
|
|
79739
|
+
if (!configPath?.trim()) {
|
|
79740
|
+
throw new Error("Cannot install native hooks without an exact Alan agent config path");
|
|
79741
|
+
}
|
|
79742
|
+
return {
|
|
79743
|
+
configPath,
|
|
79744
|
+
homeDir: input2.homeDir ?? (0, import_node_os14.homedir)(),
|
|
79745
|
+
nodeExecutable: input2.nodeExecutable ?? process.execPath,
|
|
79746
|
+
cliEntry,
|
|
79747
|
+
environment: input2.environment,
|
|
79748
|
+
platform: input2.platform ?? (0, import_node_os14.platform)()
|
|
79749
|
+
};
|
|
79750
|
+
}
|
|
79751
|
+
function readSettings(path2, providerLabel) {
|
|
79511
79752
|
if (!(0, import_node_fs22.existsSync)(path2)) return {};
|
|
79512
79753
|
try {
|
|
79513
79754
|
const value2 = JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
|
|
@@ -79519,78 +79760,363 @@ function readSettings(path2) {
|
|
|
79519
79760
|
const backup = `${path2}.malformed-${Date.now()}.bak`;
|
|
79520
79761
|
(0, import_node_fs22.copyFileSync)(path2, backup);
|
|
79521
79762
|
throw new Error(
|
|
79522
|
-
|
|
79763
|
+
`${providerLabel} settings were malformed and copied to ${backup}: ${error61 instanceof Error ? error61.message : String(error61)}`
|
|
79523
79764
|
);
|
|
79524
79765
|
}
|
|
79525
79766
|
}
|
|
79526
|
-
function
|
|
79767
|
+
function withoutAlanEntries(value2) {
|
|
79527
79768
|
if (!Array.isArray(value2)) return [];
|
|
79528
|
-
return value2.filter((
|
|
79769
|
+
return value2.filter((entry) => !JSON.stringify(entry).includes(ALAN_HOOK_MARKER));
|
|
79529
79770
|
}
|
|
79530
79771
|
function writeSettings(path2, settings) {
|
|
79531
|
-
|
|
79772
|
+
const serialized = `${JSON.stringify(settings, null, 2)}
|
|
79773
|
+
`;
|
|
79774
|
+
if ((0, import_node_fs22.existsSync)(path2) && (0, import_node_fs22.readFileSync)(path2, "utf8") === serialized) return false;
|
|
79775
|
+
(0, import_node_fs22.mkdirSync)((0, import_node_path25.dirname)(path2), { recursive: true, mode: 448 });
|
|
79532
79776
|
const temporary = `${path2}.${process.pid}.tmp`;
|
|
79533
|
-
(0, import_node_fs22.writeFileSync)(temporary,
|
|
79534
|
-
`, { mode: 384 });
|
|
79777
|
+
(0, import_node_fs22.writeFileSync)(temporary, serialized, { mode: 384 });
|
|
79535
79778
|
(0, import_node_fs22.renameSync)(temporary, path2);
|
|
79779
|
+
return true;
|
|
79536
79780
|
}
|
|
79537
|
-
function
|
|
79538
|
-
|
|
79539
|
-
|
|
79540
|
-
const
|
|
79541
|
-
|
|
79542
|
-
|
|
79543
|
-
|
|
79544
|
-
|
|
79545
|
-
|
|
79781
|
+
function writeTextFile(path2, content) {
|
|
79782
|
+
if ((0, import_node_fs22.existsSync)(path2) && (0, import_node_fs22.readFileSync)(path2, "utf8") === content) return false;
|
|
79783
|
+
(0, import_node_fs22.mkdirSync)((0, import_node_path25.dirname)(path2), { recursive: true, mode: 448 });
|
|
79784
|
+
const temporary = `${path2}.${process.pid}.tmp`;
|
|
79785
|
+
(0, import_node_fs22.writeFileSync)(temporary, content, { mode: 384 });
|
|
79786
|
+
(0, import_node_fs22.renameSync)(temporary, path2);
|
|
79787
|
+
return true;
|
|
79788
|
+
}
|
|
79789
|
+
function withoutMarkedSection(content, start, end) {
|
|
79790
|
+
const startIndex = content.indexOf(start);
|
|
79791
|
+
const endIndex = content.indexOf(end);
|
|
79792
|
+
if (startIndex < 0 && endIndex < 0) return content;
|
|
79793
|
+
if (startIndex < 0 || endIndex < startIndex) {
|
|
79794
|
+
throw new Error(`Malformed Alan-owned configuration section: ${start}`);
|
|
79546
79795
|
}
|
|
79547
|
-
const
|
|
79796
|
+
const afterEnd = endIndex + end.length;
|
|
79797
|
+
return `${content.slice(0, startIndex).trimEnd()}
|
|
79798
|
+
${content.slice(afterEnd).trimStart()}`.trim();
|
|
79799
|
+
}
|
|
79800
|
+
function reconcileNestedCommandHooks(input2) {
|
|
79801
|
+
const settings = readSettings(input2.path, input2.providerLabel);
|
|
79548
79802
|
const currentHooks = settings.hooks && typeof settings.hooks === "object" && !Array.isArray(settings.hooks) ? settings.hooks : {};
|
|
79549
79803
|
const hooks = { ...currentHooks };
|
|
79550
|
-
for (const event of
|
|
79804
|
+
for (const event of input2.events) {
|
|
79805
|
+
hooks[event] = [...withoutAlanEntries(currentHooks[event]), { hooks: [input2.command(event)] }];
|
|
79806
|
+
}
|
|
79807
|
+
return writeSettings(input2.path, { ...settings, hooks });
|
|
79808
|
+
}
|
|
79809
|
+
function removeNestedCommandHooks(path2, providerLabel) {
|
|
79810
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
79811
|
+
const settings = readSettings(path2, providerLabel);
|
|
79812
|
+
if (!settings.hooks || typeof settings.hooks !== "object" || Array.isArray(settings.hooks)) {
|
|
79813
|
+
return false;
|
|
79814
|
+
}
|
|
79815
|
+
const hooks = {};
|
|
79816
|
+
let removed = false;
|
|
79817
|
+
for (const [event, groups] of Object.entries(settings.hooks)) {
|
|
79818
|
+
const retained = withoutAlanEntries(groups);
|
|
79819
|
+
if (Array.isArray(groups) && retained.length !== groups.length) removed = true;
|
|
79820
|
+
if (retained.length > 0) hooks[event] = retained;
|
|
79821
|
+
}
|
|
79822
|
+
return removed ? writeSettings(path2, { ...settings, hooks }) : false;
|
|
79823
|
+
}
|
|
79824
|
+
function reconcileClaudeNativeHooks(input2 = {}) {
|
|
79825
|
+
const runtime = resolveRuntime(input2);
|
|
79826
|
+
return reconcileNestedCommandHooks({
|
|
79827
|
+
path: (0, import_node_path25.join)(runtime.homeDir, ".claude", "settings.json"),
|
|
79828
|
+
providerLabel: "Claude",
|
|
79829
|
+
events: CLAUDE_HOOK_EVENTS,
|
|
79830
|
+
command: (event) => ({
|
|
79831
|
+
...nativeHookCommand({
|
|
79832
|
+
...runtime,
|
|
79833
|
+
provider: "claude_cli",
|
|
79834
|
+
event
|
|
79835
|
+
})
|
|
79836
|
+
})
|
|
79837
|
+
});
|
|
79838
|
+
}
|
|
79839
|
+
function removeClaudeNativeHooks(homeDir = (0, import_node_os14.homedir)()) {
|
|
79840
|
+
return removeNestedCommandHooks((0, import_node_path25.join)(homeDir, ".claude", "settings.json"), "Claude");
|
|
79841
|
+
}
|
|
79842
|
+
function reconcileCodexNativeHooks(input2 = {}) {
|
|
79843
|
+
const runtime = resolveRuntime(input2);
|
|
79844
|
+
return reconcileNestedCommandHooks({
|
|
79845
|
+
path: (0, import_node_path25.join)(runtime.homeDir, ".codex", "hooks.json"),
|
|
79846
|
+
providerLabel: "Codex",
|
|
79847
|
+
events: CODEX_HOOK_EVENTS,
|
|
79848
|
+
command: (event) => ({
|
|
79849
|
+
type: "command",
|
|
79850
|
+
command: nativeShellCommand(runtime, "codex_app_server", event, "darwin"),
|
|
79851
|
+
commandWindows: nativeShellCommand(runtime, "codex_app_server", event, "win32"),
|
|
79852
|
+
timeout: event === "SessionEnd" ? 3 : 5
|
|
79853
|
+
})
|
|
79854
|
+
});
|
|
79855
|
+
}
|
|
79856
|
+
function removeCodexNativeHooks(homeDir = (0, import_node_os14.homedir)()) {
|
|
79857
|
+
return removeNestedCommandHooks((0, import_node_path25.join)(homeDir, ".codex", "hooks.json"), "Codex");
|
|
79858
|
+
}
|
|
79859
|
+
function reconcileCopilotNativeHooks(input2 = {}) {
|
|
79860
|
+
const runtime = resolveRuntime(input2);
|
|
79861
|
+
const path2 = (0, import_node_path25.join)(runtime.homeDir, ".copilot", "hooks", "alan-native-session.json");
|
|
79862
|
+
if ((0, import_node_fs22.existsSync)(path2) && !(0, import_node_fs22.readFileSync)(path2, "utf8").includes(ALAN_HOOK_MARKER)) {
|
|
79863
|
+
throw new Error(`Refusing to overwrite non-Alan Copilot hook configuration at ${path2}`);
|
|
79864
|
+
}
|
|
79865
|
+
const hooks = Object.fromEntries(
|
|
79866
|
+
COPILOT_HOOK_EVENTS.map((event) => [
|
|
79867
|
+
event,
|
|
79868
|
+
[
|
|
79869
|
+
{
|
|
79870
|
+
type: "command",
|
|
79871
|
+
bash: nativeShellCommand(runtime, "copilot_cli", event, "darwin"),
|
|
79872
|
+
powershell: nativeShellCommand(runtime, "copilot_cli", event, "win32"),
|
|
79873
|
+
timeoutSec: event === "SessionEnd" ? 3 : 5
|
|
79874
|
+
}
|
|
79875
|
+
]
|
|
79876
|
+
])
|
|
79877
|
+
);
|
|
79878
|
+
return writeSettings(path2, { version: 1, hooks });
|
|
79879
|
+
}
|
|
79880
|
+
function removeCopilotNativeHooks(homeDir = (0, import_node_os14.homedir)()) {
|
|
79881
|
+
const path2 = (0, import_node_path25.join)(homeDir, ".copilot", "hooks", "alan-native-session.json");
|
|
79882
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
79883
|
+
if (!(0, import_node_fs22.readFileSync)(path2, "utf8").includes(ALAN_HOOK_MARKER)) return false;
|
|
79884
|
+
(0, import_node_fs22.rmSync)(path2);
|
|
79885
|
+
return true;
|
|
79886
|
+
}
|
|
79887
|
+
function reconcileCursorNativeHooks(input2 = {}) {
|
|
79888
|
+
const runtime = resolveRuntime(input2);
|
|
79889
|
+
const path2 = (0, import_node_path25.join)(runtime.homeDir, ".cursor", "hooks.json");
|
|
79890
|
+
const settings = readSettings(path2, "Cursor");
|
|
79891
|
+
const currentHooks = settings.hooks && typeof settings.hooks === "object" && !Array.isArray(settings.hooks) ? settings.hooks : {};
|
|
79892
|
+
const hooks = { ...currentHooks };
|
|
79893
|
+
for (const event of CURSOR_HOOK_EVENTS) {
|
|
79551
79894
|
hooks[event] = [
|
|
79552
|
-
...
|
|
79895
|
+
...withoutAlanEntries(currentHooks[event]),
|
|
79553
79896
|
{
|
|
79554
|
-
|
|
79555
|
-
|
|
79556
|
-
|
|
79557
|
-
nodeExecutable,
|
|
79558
|
-
cliEntry,
|
|
79559
|
-
environment: input2?.environment,
|
|
79560
|
-
platform: input2?.platform,
|
|
79561
|
-
provider: "claude_cli",
|
|
79562
|
-
event
|
|
79563
|
-
})
|
|
79564
|
-
]
|
|
79897
|
+
type: "command",
|
|
79898
|
+
command: nativeShellCommand(runtime, "cursor_agent_cli", event),
|
|
79899
|
+
timeout: 5
|
|
79565
79900
|
}
|
|
79566
79901
|
];
|
|
79567
79902
|
}
|
|
79568
|
-
|
|
79569
|
-
const previous = (0, import_node_fs22.existsSync)(settingsPath) ? (0, import_node_fs22.readFileSync)(settingsPath, "utf8") : null;
|
|
79570
|
-
const serialized = `${JSON.stringify(next, null, 2)}
|
|
79571
|
-
`;
|
|
79572
|
-
if (previous === serialized) return false;
|
|
79573
|
-
writeSettings(settingsPath, next);
|
|
79574
|
-
return true;
|
|
79903
|
+
return writeSettings(path2, { ...settings, version: settings.version ?? 1, hooks });
|
|
79575
79904
|
}
|
|
79576
|
-
function
|
|
79577
|
-
const
|
|
79578
|
-
if (!(0, import_node_fs22.existsSync)(
|
|
79579
|
-
const settings = readSettings(
|
|
79905
|
+
function removeCursorNativeHooks(homeDir = (0, import_node_os14.homedir)()) {
|
|
79906
|
+
const path2 = (0, import_node_path25.join)(homeDir, ".cursor", "hooks.json");
|
|
79907
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
79908
|
+
const settings = readSettings(path2, "Cursor");
|
|
79580
79909
|
if (!settings.hooks || typeof settings.hooks !== "object" || Array.isArray(settings.hooks)) {
|
|
79581
79910
|
return false;
|
|
79582
79911
|
}
|
|
79583
79912
|
const hooks = {};
|
|
79584
79913
|
let removed = false;
|
|
79585
|
-
for (const [event,
|
|
79586
|
-
const retained =
|
|
79587
|
-
if (Array.isArray(
|
|
79914
|
+
for (const [event, entries] of Object.entries(settings.hooks)) {
|
|
79915
|
+
const retained = withoutAlanEntries(entries);
|
|
79916
|
+
if (Array.isArray(entries) && retained.length !== entries.length) removed = true;
|
|
79588
79917
|
if (retained.length > 0) hooks[event] = retained;
|
|
79589
79918
|
}
|
|
79590
|
-
|
|
79591
|
-
|
|
79919
|
+
return removed ? writeSettings(path2, { ...settings, hooks }) : false;
|
|
79920
|
+
}
|
|
79921
|
+
function kimiHookSection(runtime) {
|
|
79922
|
+
const hooks = KIMI_HOOK_EVENTS.map(
|
|
79923
|
+
(event) => [
|
|
79924
|
+
"[[hooks]]",
|
|
79925
|
+
`event = ${JSON.stringify(event)}`,
|
|
79926
|
+
`command = ${JSON.stringify(nativeShellCommand(runtime, "kimi_cli", event))}`,
|
|
79927
|
+
`timeout = ${event === "SessionEnd" ? 3 : 5}`
|
|
79928
|
+
].join("\n")
|
|
79929
|
+
).join("\n\n");
|
|
79930
|
+
return `${ALAN_KIMI_HOOKS_START}
|
|
79931
|
+
${hooks}
|
|
79932
|
+
${ALAN_KIMI_HOOKS_END}`;
|
|
79933
|
+
}
|
|
79934
|
+
function reconcileKimiNativeHooks(input2 = {}) {
|
|
79935
|
+
const runtime = resolveRuntime(input2);
|
|
79936
|
+
const path2 = (0, import_node_path25.join)(runtime.homeDir, ".kimi-code", "config.toml");
|
|
79937
|
+
const current = (0, import_node_fs22.existsSync)(path2) ? (0, import_node_fs22.readFileSync)(path2, "utf8") : "";
|
|
79938
|
+
const userContent = withoutMarkedSection(current, ALAN_KIMI_HOOKS_START, ALAN_KIMI_HOOKS_END);
|
|
79939
|
+
const content = `${userContent.trimEnd()}${userContent.trim() ? "\n\n" : ""}${kimiHookSection(runtime)}
|
|
79940
|
+
`;
|
|
79941
|
+
return writeTextFile(path2, content);
|
|
79942
|
+
}
|
|
79943
|
+
function removeKimiNativeHooks(homeDir = (0, import_node_os14.homedir)()) {
|
|
79944
|
+
const path2 = (0, import_node_path25.join)(homeDir, ".kimi-code", "config.toml");
|
|
79945
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
79946
|
+
const current = (0, import_node_fs22.readFileSync)(path2, "utf8");
|
|
79947
|
+
const content = withoutMarkedSection(current, ALAN_KIMI_HOOKS_START, ALAN_KIMI_HOOKS_END);
|
|
79948
|
+
if (content === current) return false;
|
|
79949
|
+
return writeTextFile(path2, content ? `${content.trimEnd()}
|
|
79950
|
+
` : "");
|
|
79951
|
+
}
|
|
79952
|
+
function reconcileGrokNativeHooks(input2 = {}) {
|
|
79953
|
+
const runtime = resolveRuntime(input2);
|
|
79954
|
+
const path2 = (0, import_node_path25.join)(runtime.homeDir, ".grok", "hooks", "alan-native-session.json");
|
|
79955
|
+
if ((0, import_node_fs22.existsSync)(path2) && !(0, import_node_fs22.readFileSync)(path2, "utf8").includes(ALAN_HOOK_MARKER)) {
|
|
79956
|
+
throw new Error(`Refusing to overwrite non-Alan Grok hook configuration at ${path2}`);
|
|
79957
|
+
}
|
|
79958
|
+
return reconcileNestedCommandHooks({
|
|
79959
|
+
path: path2,
|
|
79960
|
+
providerLabel: "Grok",
|
|
79961
|
+
events: GROK_HOOK_EVENTS,
|
|
79962
|
+
command: (event) => ({
|
|
79963
|
+
type: "command",
|
|
79964
|
+
command: nativeShellCommand(runtime, "grok_cli", event),
|
|
79965
|
+
timeout: event === "SessionEnd" ? 3 : 5
|
|
79966
|
+
})
|
|
79967
|
+
});
|
|
79968
|
+
}
|
|
79969
|
+
function removeGrokNativeHooks(homeDir = (0, import_node_os14.homedir)()) {
|
|
79970
|
+
const path2 = (0, import_node_path25.join)(homeDir, ".grok", "hooks", "alan-native-session.json");
|
|
79971
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
79972
|
+
if (!(0, import_node_fs22.readFileSync)(path2, "utf8").includes(ALAN_HOOK_MARKER)) return false;
|
|
79973
|
+
(0, import_node_fs22.rmSync)(path2);
|
|
79974
|
+
return true;
|
|
79975
|
+
}
|
|
79976
|
+
function opencodePluginSource(runtime) {
|
|
79977
|
+
const command = [
|
|
79978
|
+
runtime.nodeExecutable,
|
|
79979
|
+
runtime.cliEntry,
|
|
79980
|
+
"hook",
|
|
79981
|
+
"--config-path",
|
|
79982
|
+
runtime.configPath,
|
|
79983
|
+
"--provider",
|
|
79984
|
+
"opencode_cli"
|
|
79985
|
+
];
|
|
79986
|
+
const environment = runtime.environment ?? {};
|
|
79987
|
+
return `${ALAN_OPENCODE_PLUGIN_MARKER}
|
|
79988
|
+
const command = ${JSON.stringify(command)}
|
|
79989
|
+
const environment = ${JSON.stringify(environment)}
|
|
79990
|
+
|
|
79991
|
+
export const AlanNativeSessionPlugin = async ({ directory }) => {
|
|
79992
|
+
const textByPart = new Map()
|
|
79993
|
+
const userPartIdsBySession = new Map()
|
|
79994
|
+
const send = async (event, payload) => {
|
|
79995
|
+
const proc = Bun.spawn({
|
|
79996
|
+
cmd: [...command, "--event", event, ${JSON.stringify(ALAN_HOOK_MARKER)}],
|
|
79997
|
+
env: { ...process.env, ...environment },
|
|
79998
|
+
stdin: "pipe",
|
|
79999
|
+
stdout: "ignore",
|
|
80000
|
+
stderr: "ignore",
|
|
80001
|
+
})
|
|
80002
|
+
proc.stdin.write(JSON.stringify({ ...payload, cwd: payload.cwd ?? directory }))
|
|
80003
|
+
proc.stdin.end()
|
|
80004
|
+
await proc.exited
|
|
80005
|
+
}
|
|
80006
|
+
|
|
80007
|
+
return {
|
|
80008
|
+
"chat.message": async (input, output) => {
|
|
80009
|
+
userPartIdsBySession.set(
|
|
80010
|
+
input.sessionID,
|
|
80011
|
+
new Set(output.parts.map((part) => part.id).filter(Boolean)),
|
|
80012
|
+
)
|
|
80013
|
+
const prompt = output.parts
|
|
80014
|
+
.filter((part) => part.type === "text")
|
|
80015
|
+
.map((part) => part.text)
|
|
80016
|
+
.join("\\n")
|
|
80017
|
+
await send("user_prompt", { session_id: input.sessionID, prompt })
|
|
80018
|
+
},
|
|
80019
|
+
event: async ({ event }) => {
|
|
80020
|
+
if (event.type === "session.created") {
|
|
80021
|
+
await send("session_start", { session_id: event.properties.info.id })
|
|
80022
|
+
return
|
|
80023
|
+
}
|
|
80024
|
+
if (event.type === "session.idle") {
|
|
80025
|
+
await send("stop", { session_id: event.properties.sessionID })
|
|
80026
|
+
return
|
|
80027
|
+
}
|
|
80028
|
+
if (event.type === "session.deleted") {
|
|
80029
|
+
userPartIdsBySession.delete(event.properties.info.id)
|
|
80030
|
+
await send("session_end", { session_id: event.properties.info.id })
|
|
80031
|
+
return
|
|
80032
|
+
}
|
|
80033
|
+
if (event.type === "session.error" && event.properties.sessionID) {
|
|
80034
|
+
await send("stop", {
|
|
80035
|
+
session_id: event.properties.sessionID,
|
|
80036
|
+
error: event.properties.error,
|
|
80037
|
+
})
|
|
80038
|
+
return
|
|
80039
|
+
}
|
|
80040
|
+
if (event.type !== "message.part.updated") return
|
|
80041
|
+
const part = event.properties.part
|
|
80042
|
+
if (part.type !== "text" && part.type !== "reasoning") return
|
|
80043
|
+
if (userPartIdsBySession.get(part.sessionID)?.has(part.id)) return
|
|
80044
|
+
const previous = textByPart.get(part.id) ?? ""
|
|
80045
|
+
const complete = typeof part.text === "string" ? part.text : ""
|
|
80046
|
+
const text = event.properties.delta ?? (complete.startsWith(previous) ? complete.slice(previous.length) : complete)
|
|
80047
|
+
textByPart.set(part.id, complete)
|
|
80048
|
+
if (!text) return
|
|
80049
|
+
await send("transcript_update", {
|
|
80050
|
+
session_id: part.sessionID,
|
|
80051
|
+
source_cursor: part.id + ":" + complete.length,
|
|
80052
|
+
...(part.type === "reasoning" ? { thinking: text } : { transcript_delta: text }),
|
|
80053
|
+
})
|
|
80054
|
+
},
|
|
80055
|
+
}
|
|
80056
|
+
}
|
|
80057
|
+
`;
|
|
80058
|
+
}
|
|
80059
|
+
function reconcileOpencodeNativePlugin(input2 = {}) {
|
|
80060
|
+
const runtime = resolveRuntime(input2);
|
|
80061
|
+
const path2 = (0, import_node_path25.join)(runtime.homeDir, ".config", "opencode", "plugins", "alan-native-session.js");
|
|
80062
|
+
if ((0, import_node_fs22.existsSync)(path2) && !(0, import_node_fs22.readFileSync)(path2, "utf8").includes(ALAN_OPENCODE_PLUGIN_MARKER)) {
|
|
80063
|
+
throw new Error(`Refusing to overwrite non-Alan OpenCode plugin at ${path2}`);
|
|
80064
|
+
}
|
|
80065
|
+
const source = opencodePluginSource(runtime);
|
|
80066
|
+
if ((0, import_node_fs22.existsSync)(path2) && (0, import_node_fs22.readFileSync)(path2, "utf8") === source) return false;
|
|
80067
|
+
(0, import_node_fs22.mkdirSync)((0, import_node_path25.dirname)(path2), { recursive: true, mode: 448 });
|
|
80068
|
+
const temporary = `${path2}.${process.pid}.tmp`;
|
|
80069
|
+
(0, import_node_fs22.writeFileSync)(temporary, source, { mode: 384 });
|
|
80070
|
+
(0, import_node_fs22.renameSync)(temporary, path2);
|
|
79592
80071
|
return true;
|
|
79593
80072
|
}
|
|
80073
|
+
function removeOpencodeNativePlugin(homeDir = (0, import_node_os14.homedir)()) {
|
|
80074
|
+
const path2 = (0, import_node_path25.join)(homeDir, ".config", "opencode", "plugins", "alan-native-session.js");
|
|
80075
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
80076
|
+
if (!(0, import_node_fs22.readFileSync)(path2, "utf8").includes(ALAN_OPENCODE_PLUGIN_MARKER)) return false;
|
|
80077
|
+
(0, import_node_fs22.rmSync)(path2);
|
|
80078
|
+
return true;
|
|
80079
|
+
}
|
|
80080
|
+
function configFileContainsMarker(path2, marker) {
|
|
80081
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return false;
|
|
80082
|
+
try {
|
|
80083
|
+
return (0, import_node_fs22.readFileSync)(path2, "utf8").includes(marker);
|
|
80084
|
+
} catch {
|
|
80085
|
+
return false;
|
|
80086
|
+
}
|
|
80087
|
+
}
|
|
80088
|
+
function inspectNativeHooksConfigured(providerKind, homeDir = (0, import_node_os14.homedir)()) {
|
|
80089
|
+
switch (providerKind) {
|
|
80090
|
+
case "claude_cli":
|
|
80091
|
+
return configFileContainsMarker((0, import_node_path25.join)(homeDir, ".claude", "settings.json"), ALAN_HOOK_MARKER);
|
|
80092
|
+
case "codex_app_server":
|
|
80093
|
+
return configFileContainsMarker((0, import_node_path25.join)(homeDir, ".codex", "hooks.json"), ALAN_HOOK_MARKER);
|
|
80094
|
+
case "copilot_cli":
|
|
80095
|
+
return configFileContainsMarker(
|
|
80096
|
+
(0, import_node_path25.join)(homeDir, ".copilot", "hooks", "alan-native-session.json"),
|
|
80097
|
+
ALAN_HOOK_MARKER
|
|
80098
|
+
);
|
|
80099
|
+
case "cursor_agent_cli":
|
|
80100
|
+
return configFileContainsMarker((0, import_node_path25.join)(homeDir, ".cursor", "hooks.json"), ALAN_HOOK_MARKER);
|
|
80101
|
+
case "kimi_cli":
|
|
80102
|
+
return configFileContainsMarker(
|
|
80103
|
+
(0, import_node_path25.join)(homeDir, ".kimi-code", "config.toml"),
|
|
80104
|
+
ALAN_KIMI_HOOKS_START
|
|
80105
|
+
);
|
|
80106
|
+
case "grok_cli":
|
|
80107
|
+
return configFileContainsMarker(
|
|
80108
|
+
(0, import_node_path25.join)(homeDir, ".grok", "hooks", "alan-native-session.json"),
|
|
80109
|
+
ALAN_HOOK_MARKER
|
|
80110
|
+
);
|
|
80111
|
+
case "opencode_cli":
|
|
80112
|
+
return configFileContainsMarker(
|
|
80113
|
+
(0, import_node_path25.join)(homeDir, ".config", "opencode", "plugins", "alan-native-session.js"),
|
|
80114
|
+
ALAN_OPENCODE_PLUGIN_MARKER
|
|
80115
|
+
);
|
|
80116
|
+
default:
|
|
80117
|
+
return false;
|
|
80118
|
+
}
|
|
80119
|
+
}
|
|
79594
80120
|
|
|
79595
80121
|
// src/integration-cli.ts
|
|
79596
80122
|
function alanMcpServers(apiUrl) {
|
|
@@ -79601,12 +80127,41 @@ function alanMcpServers(apiUrl) {
|
|
|
79601
80127
|
}
|
|
79602
80128
|
};
|
|
79603
80129
|
}
|
|
80130
|
+
function reconcileInstalledNativeHooks(options) {
|
|
80131
|
+
const environment = getDaemonCliEnvironment();
|
|
80132
|
+
const nativeRuntime = {
|
|
80133
|
+
configPath: options.configPath ?? getConfigPath(),
|
|
80134
|
+
nodeExecutable: options.nativeHookRuntime?.executable,
|
|
80135
|
+
cliEntry: options.nativeHookRuntime?.cliEntry,
|
|
80136
|
+
environment: options.nativeHookRuntime?.environment
|
|
80137
|
+
};
|
|
80138
|
+
return [
|
|
80139
|
+
resolveCliExecutable("claude", environment) ? reconcileClaudeNativeHooks(nativeRuntime) : false,
|
|
80140
|
+
resolveCliExecutable("codex", environment) ? reconcileCodexNativeHooks(nativeRuntime) : false,
|
|
80141
|
+
resolveCliExecutable("copilot", environment) ? reconcileCopilotNativeHooks(nativeRuntime) : false,
|
|
80142
|
+
resolveCliExecutable("cursor-agent", environment) ? reconcileCursorNativeHooks(nativeRuntime) : false,
|
|
80143
|
+
resolveCliExecutable("kimi-cli", environment) ? reconcileKimiNativeHooks(nativeRuntime) : false,
|
|
80144
|
+
resolveCliExecutable("grok", environment) ? reconcileGrokNativeHooks(nativeRuntime) : false,
|
|
80145
|
+
resolveCliExecutable("opencode", environment) ? reconcileOpencodeNativePlugin(nativeRuntime) : false
|
|
80146
|
+
].some(Boolean);
|
|
80147
|
+
}
|
|
80148
|
+
function removeNativeHooksOnly() {
|
|
80149
|
+
removeClaudeNativeHooks();
|
|
80150
|
+
removeCodexNativeHooks();
|
|
80151
|
+
removeCopilotNativeHooks();
|
|
80152
|
+
removeCursorNativeHooks();
|
|
80153
|
+
removeKimiNativeHooks();
|
|
80154
|
+
removeGrokNativeHooks();
|
|
80155
|
+
removeOpencodeNativePlugin();
|
|
80156
|
+
}
|
|
79604
80157
|
function runMcpIntegrationCommand(args, options = {}) {
|
|
79605
80158
|
bindConfigPath(args);
|
|
79606
80159
|
const action = args[0] ?? "status";
|
|
79607
80160
|
const config2 = readConfig();
|
|
79608
80161
|
const endpoints = resolveEndpoints(args.slice(1), config2);
|
|
79609
80162
|
const service = new McpSyncService({ enabled: true });
|
|
80163
|
+
const reconcileMcp = options.reconcileMcp ?? true;
|
|
80164
|
+
const reconcileHooks = options.reconcileHooks ?? true;
|
|
79610
80165
|
if (action === "status") {
|
|
79611
80166
|
process.stdout.write(`${JSON.stringify(service.getStatus(), null, 2)}
|
|
79612
80167
|
`);
|
|
@@ -79618,23 +80173,26 @@ function runMcpIntegrationCommand(args, options = {}) {
|
|
|
79618
80173
|
"Alan is not configured. Run `alan-agent login` or `alan-agent setup` first."
|
|
79619
80174
|
);
|
|
79620
80175
|
}
|
|
79621
|
-
|
|
79622
|
-
if (
|
|
79623
|
-
|
|
79624
|
-
|
|
79625
|
-
|
|
79626
|
-
|
|
79627
|
-
|
|
79628
|
-
}) : false;
|
|
80176
|
+
let mcpServersUpdated = false;
|
|
80177
|
+
if (reconcileMcp) {
|
|
80178
|
+
const result = service.syncServers(alanMcpServers(endpoints.apiUrl), endpoints.apiUrl);
|
|
80179
|
+
if (result.errors.length > 0) throw new Error(result.errors.join("; "));
|
|
80180
|
+
mcpServersUpdated = result.mcpServersUpdated;
|
|
80181
|
+
}
|
|
80182
|
+
const hooksUpdated = reconcileHooks ? reconcileInstalledNativeHooks(options) : false;
|
|
79629
80183
|
process.stdout.write(
|
|
79630
|
-
`${
|
|
80184
|
+
`${mcpServersUpdated || hooksUpdated ? "Alan CLI integrations updated" : "Alan CLI integrations already current"}.
|
|
79631
80185
|
`
|
|
79632
80186
|
);
|
|
79633
80187
|
return;
|
|
79634
80188
|
}
|
|
79635
80189
|
if (action === "uninstall") {
|
|
79636
|
-
|
|
79637
|
-
|
|
80190
|
+
if (reconcileMcp) {
|
|
80191
|
+
service.cleanup(toManagedMcpServers(alanMcpServers(endpoints.apiUrl)));
|
|
80192
|
+
}
|
|
80193
|
+
if (reconcileHooks) {
|
|
80194
|
+
removeNativeHooksOnly();
|
|
80195
|
+
}
|
|
79638
80196
|
process.stdout.write("Removed Alan-owned MCP configuration.\n");
|
|
79639
80197
|
return;
|
|
79640
80198
|
}
|
|
@@ -79716,7 +80274,8 @@ function omitUndefined(record2) {
|
|
|
79716
80274
|
// src/native-hook-command.ts
|
|
79717
80275
|
var import_node_crypto19 = require("crypto");
|
|
79718
80276
|
var import_node_fs23 = require("fs");
|
|
79719
|
-
var
|
|
80277
|
+
var import_node_os15 = require("os");
|
|
80278
|
+
var import_node_path26 = require("path");
|
|
79720
80279
|
|
|
79721
80280
|
// src/native-session.ts
|
|
79722
80281
|
var NATIVE_SESSION_PROVIDER_CAPABILITIES = [
|
|
@@ -79748,28 +80307,64 @@ var NATIVE_SESSION_PROVIDER_CAPABILITIES = [
|
|
|
79748
80307
|
command: "codex",
|
|
79749
80308
|
capabilities: {
|
|
79750
80309
|
mcp: true,
|
|
79751
|
-
lifecycleHooks:
|
|
79752
|
-
transcriptDelta:
|
|
79753
|
-
subagents:
|
|
79754
|
-
sessionEnd:
|
|
79755
|
-
state: "
|
|
79756
|
-
reason: "Codex exposes a turn-complete notification, not full lifecycle hooks."
|
|
80310
|
+
lifecycleHooks: true,
|
|
80311
|
+
transcriptDelta: true,
|
|
80312
|
+
subagents: true,
|
|
80313
|
+
sessionEnd: true,
|
|
80314
|
+
state: "supported"
|
|
79757
80315
|
},
|
|
79758
|
-
supportedHookEvents: [
|
|
80316
|
+
supportedHookEvents: [
|
|
80317
|
+
"SessionStart",
|
|
80318
|
+
"UserPromptSubmit",
|
|
80319
|
+
"PostToolUse",
|
|
80320
|
+
"Stop",
|
|
80321
|
+
"SubagentStart",
|
|
80322
|
+
"SubagentStop",
|
|
80323
|
+
"SessionEnd"
|
|
80324
|
+
]
|
|
79759
80325
|
},
|
|
79760
80326
|
{
|
|
79761
80327
|
providerKind: "copilot_cli",
|
|
79762
80328
|
provider: "copilot",
|
|
79763
80329
|
command: "copilot",
|
|
79764
|
-
capabilities:
|
|
79765
|
-
|
|
80330
|
+
capabilities: {
|
|
80331
|
+
mcp: true,
|
|
80332
|
+
lifecycleHooks: true,
|
|
80333
|
+
transcriptDelta: true,
|
|
80334
|
+
subagents: false,
|
|
80335
|
+
sessionEnd: true,
|
|
80336
|
+
state: "supported",
|
|
80337
|
+
reason: "Copilot exposes stable subagent identity only on SubagentStop, so paired subagent lifecycle is not projected."
|
|
80338
|
+
},
|
|
80339
|
+
supportedHookEvents: [
|
|
80340
|
+
"SessionStart",
|
|
80341
|
+
"UserPromptSubmit",
|
|
80342
|
+
"PostToolUse",
|
|
80343
|
+
"Stop",
|
|
80344
|
+
"SubagentStop",
|
|
80345
|
+
"SessionEnd"
|
|
80346
|
+
]
|
|
79766
80347
|
},
|
|
79767
80348
|
{
|
|
79768
80349
|
providerKind: "cursor_agent_cli",
|
|
79769
80350
|
provider: "cursor",
|
|
79770
80351
|
command: "cursor-agent",
|
|
79771
|
-
capabilities:
|
|
79772
|
-
|
|
80352
|
+
capabilities: {
|
|
80353
|
+
mcp: true,
|
|
80354
|
+
lifecycleHooks: true,
|
|
80355
|
+
transcriptDelta: true,
|
|
80356
|
+
subagents: false,
|
|
80357
|
+
sessionEnd: true,
|
|
80358
|
+
state: "supported",
|
|
80359
|
+
reason: "Cursor's subagent stop hook does not expose the stable subagent id from subagent start."
|
|
80360
|
+
},
|
|
80361
|
+
supportedHookEvents: [
|
|
80362
|
+
"sessionStart",
|
|
80363
|
+
"beforeSubmitPrompt",
|
|
80364
|
+
"afterAgentResponse",
|
|
80365
|
+
"stop",
|
|
80366
|
+
"sessionEnd"
|
|
80367
|
+
]
|
|
79773
80368
|
},
|
|
79774
80369
|
{
|
|
79775
80370
|
providerKind: "antigravity_cli",
|
|
@@ -79782,22 +80377,70 @@ var NATIVE_SESSION_PROVIDER_CAPABILITIES = [
|
|
|
79782
80377
|
providerKind: "kimi_cli",
|
|
79783
80378
|
provider: "kimi",
|
|
79784
80379
|
command: "kimi-cli",
|
|
79785
|
-
capabilities:
|
|
79786
|
-
|
|
80380
|
+
capabilities: {
|
|
80381
|
+
mcp: true,
|
|
80382
|
+
lifecycleHooks: true,
|
|
80383
|
+
transcriptDelta: true,
|
|
80384
|
+
subagents: false,
|
|
80385
|
+
sessionEnd: true,
|
|
80386
|
+
state: "supported",
|
|
80387
|
+
reason: "Kimi hooks identify subagents by name but do not expose a stable child session id."
|
|
80388
|
+
},
|
|
80389
|
+
supportedHookEvents: [
|
|
80390
|
+
"SessionStart",
|
|
80391
|
+
"UserPromptSubmit",
|
|
80392
|
+
"PostToolUse",
|
|
80393
|
+
"Stop",
|
|
80394
|
+
"Interrupt",
|
|
80395
|
+
"SubagentStart",
|
|
80396
|
+
"SubagentStop",
|
|
80397
|
+
"SessionEnd"
|
|
80398
|
+
]
|
|
79787
80399
|
},
|
|
79788
80400
|
{
|
|
79789
80401
|
providerKind: "grok_cli",
|
|
79790
80402
|
provider: "grok",
|
|
79791
80403
|
command: "grok",
|
|
79792
|
-
capabilities:
|
|
79793
|
-
|
|
80404
|
+
capabilities: {
|
|
80405
|
+
mcp: true,
|
|
80406
|
+
lifecycleHooks: true,
|
|
80407
|
+
transcriptDelta: false,
|
|
80408
|
+
subagents: false,
|
|
80409
|
+
sessionEnd: true,
|
|
80410
|
+
state: "supported",
|
|
80411
|
+
reason: "Grok supplies the final assistant message on terminal hooks, but not incremental transcript deltas or stable child session ids."
|
|
80412
|
+
},
|
|
80413
|
+
supportedHookEvents: [
|
|
80414
|
+
"SessionStart",
|
|
80415
|
+
"UserPromptSubmit",
|
|
80416
|
+
"PostToolUse",
|
|
80417
|
+
"Stop",
|
|
80418
|
+
"StopFailure",
|
|
80419
|
+
"StopCancelled",
|
|
80420
|
+
"SubagentStart",
|
|
80421
|
+
"SubagentStop",
|
|
80422
|
+
"SessionEnd"
|
|
80423
|
+
]
|
|
79794
80424
|
},
|
|
79795
80425
|
{
|
|
79796
80426
|
providerKind: "opencode_cli",
|
|
79797
80427
|
provider: "opencode",
|
|
79798
80428
|
command: "opencode",
|
|
79799
|
-
capabilities:
|
|
79800
|
-
|
|
80429
|
+
capabilities: {
|
|
80430
|
+
mcp: true,
|
|
80431
|
+
lifecycleHooks: true,
|
|
80432
|
+
transcriptDelta: true,
|
|
80433
|
+
subagents: false,
|
|
80434
|
+
sessionEnd: true,
|
|
80435
|
+
state: "supported",
|
|
80436
|
+
reason: "OpenCode exposes root session and message events; subagent lifecycle is not distinct."
|
|
80437
|
+
},
|
|
80438
|
+
supportedHookEvents: [
|
|
80439
|
+
"session.created",
|
|
80440
|
+
"message.part.updated",
|
|
80441
|
+
"session.idle",
|
|
80442
|
+
"session.deleted"
|
|
80443
|
+
]
|
|
79801
80444
|
},
|
|
79802
80445
|
{
|
|
79803
80446
|
providerKind: "droid_cli",
|
|
@@ -79847,6 +80490,17 @@ function stringField4(payload, ...names) {
|
|
|
79847
80490
|
}
|
|
79848
80491
|
return void 0;
|
|
79849
80492
|
}
|
|
80493
|
+
function firstStringArrayField(payload, ...names) {
|
|
80494
|
+
for (const name of names) {
|
|
80495
|
+
const value2 = payload[name];
|
|
80496
|
+
if (!Array.isArray(value2)) continue;
|
|
80497
|
+
const first = value2.find(
|
|
80498
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
80499
|
+
);
|
|
80500
|
+
if (first) return first.trim();
|
|
80501
|
+
}
|
|
80502
|
+
return void 0;
|
|
80503
|
+
}
|
|
79850
80504
|
function nonNegativeIntegerField(payload, ...names) {
|
|
79851
80505
|
for (const name of names) {
|
|
79852
80506
|
const value2 = payload[name];
|
|
@@ -79854,19 +80508,77 @@ function nonNegativeIntegerField(payload, ...names) {
|
|
|
79854
80508
|
}
|
|
79855
80509
|
return void 0;
|
|
79856
80510
|
}
|
|
80511
|
+
function resolveCodexSessionIdFromTranscriptPath(transcriptPath) {
|
|
80512
|
+
const fileName = (0, import_node_path26.basename)(transcriptPath);
|
|
80513
|
+
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(
|
|
80514
|
+
fileName
|
|
80515
|
+
);
|
|
80516
|
+
return match?.[1];
|
|
80517
|
+
}
|
|
80518
|
+
function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path26.join)((0, import_node_os15.homedir)(), ".kimi-code")) {
|
|
80519
|
+
if ((0, import_node_path26.basename)(externalSessionId) !== externalSessionId) return void 0;
|
|
80520
|
+
const sessionsDir = (0, import_node_path26.join)(kimiHomeDir, "sessions");
|
|
80521
|
+
if (!(0, import_node_fs23.existsSync)(sessionsDir)) return void 0;
|
|
80522
|
+
for (const workspace of (0, import_node_fs23.readdirSync)(sessionsDir, { withFileTypes: true })) {
|
|
80523
|
+
if (!workspace.isDirectory()) continue;
|
|
80524
|
+
const transcriptPath = (0, import_node_path26.join)(
|
|
80525
|
+
sessionsDir,
|
|
80526
|
+
workspace.name,
|
|
80527
|
+
externalSessionId,
|
|
80528
|
+
"agents",
|
|
80529
|
+
"main",
|
|
80530
|
+
"wire.jsonl"
|
|
80531
|
+
);
|
|
80532
|
+
if ((0, import_node_fs23.existsSync)(transcriptPath)) return transcriptPath;
|
|
80533
|
+
}
|
|
80534
|
+
return void 0;
|
|
80535
|
+
}
|
|
80536
|
+
function enrichProviderPayload(provider, payload) {
|
|
80537
|
+
if (provider === "codex_app_server") {
|
|
80538
|
+
const externalSessionId2 = stringField4(
|
|
80539
|
+
payload,
|
|
80540
|
+
"session_id",
|
|
80541
|
+
"sessionId",
|
|
80542
|
+
"thread_id",
|
|
80543
|
+
"threadId"
|
|
80544
|
+
);
|
|
80545
|
+
if (externalSessionId2) return payload;
|
|
80546
|
+
const transcriptPath2 = stringField4(payload, "transcript_path", "transcriptPath");
|
|
80547
|
+
if (!transcriptPath2) return payload;
|
|
80548
|
+
const derivedSessionId = resolveCodexSessionIdFromTranscriptPath(transcriptPath2);
|
|
80549
|
+
return derivedSessionId ? { ...payload, session_id: derivedSessionId } : payload;
|
|
80550
|
+
}
|
|
80551
|
+
if (provider !== "kimi_cli") return payload;
|
|
80552
|
+
const externalSessionId = stringField4(payload, "session_id", "sessionId");
|
|
80553
|
+
if (!externalSessionId || stringField4(payload, "transcript_path", "transcriptPath")) {
|
|
80554
|
+
return payload;
|
|
80555
|
+
}
|
|
80556
|
+
const transcriptPath = resolveKimiTranscriptPath(externalSessionId);
|
|
80557
|
+
return transcriptPath ? { ...payload, transcript_path: transcriptPath } : payload;
|
|
80558
|
+
}
|
|
79857
80559
|
function parseNativeHookEnvelope(input2) {
|
|
79858
80560
|
if (!isNativeSessionProviderKind(input2.provider)) {
|
|
79859
80561
|
throw new Error(`unsupported native session provider: ${input2.provider}`);
|
|
79860
80562
|
}
|
|
79861
|
-
const
|
|
79862
|
-
const
|
|
79863
|
-
const
|
|
80563
|
+
const payload = enrichProviderPayload(input2.provider, input2.payload);
|
|
80564
|
+
const rawHookEvent = input2.hookEvent ?? stringField4(payload, "hook_event_name", "hookEvent", "hookEventName", "type") ?? "notification";
|
|
80565
|
+
const eventType = normalizeHookEvent(rawHookEvent);
|
|
80566
|
+
const cwd = stringField4(payload, "cwd", "working_directory", "workingDirectory") ?? firstStringArrayField(payload, "workspace_roots", "workspaceRoots");
|
|
80567
|
+
const transcriptPath = eventType === "subagent_start" || eventType === "subagent_end" ? stringField4(
|
|
80568
|
+
payload,
|
|
80569
|
+
"agent_transcript_path",
|
|
80570
|
+
"agentTranscriptPath",
|
|
80571
|
+
"transcript_path",
|
|
80572
|
+
"transcriptPath"
|
|
80573
|
+
) : stringField4(payload, "transcript_path", "transcriptPath");
|
|
79864
80574
|
const capability = NATIVE_SESSION_PROVIDER_CAPABILITIES.find(
|
|
79865
80575
|
(candidate) => candidate.providerKind === input2.provider
|
|
79866
80576
|
);
|
|
79867
80577
|
if (!capability) throw new Error(`unsupported native session provider: ${input2.provider}`);
|
|
79868
|
-
const
|
|
79869
|
-
|
|
80578
|
+
const parentSessionId = stringField4(
|
|
80579
|
+
payload,
|
|
80580
|
+
"parent_session_id",
|
|
80581
|
+
"parentSessionId",
|
|
79870
80582
|
"session_id",
|
|
79871
80583
|
"sessionId",
|
|
79872
80584
|
"conversation_id",
|
|
@@ -79874,20 +80586,30 @@ function parseNativeHookEnvelope(input2) {
|
|
|
79874
80586
|
"thread_id",
|
|
79875
80587
|
"threadId"
|
|
79876
80588
|
);
|
|
80589
|
+
const externalSessionId = eventType === "subagent_start" || eventType === "subagent_end" ? stringField4(
|
|
80590
|
+
payload,
|
|
80591
|
+
"agent_id",
|
|
80592
|
+
"agentId",
|
|
80593
|
+
"subagent_id",
|
|
80594
|
+
"subagentId",
|
|
80595
|
+
"task_id",
|
|
80596
|
+
"taskId"
|
|
80597
|
+
) ?? parentSessionId : parentSessionId;
|
|
79877
80598
|
if (!externalSessionId) throw new Error("hook payload is missing a provider session id");
|
|
79878
|
-
const cursor = stringField4(
|
|
80599
|
+
const cursor = stringField4(payload, "source_cursor", "sourceCursor") ?? nonNegativeIntegerField(payload, "byte_offset", "byteOffset")?.toString() ?? nonNegativeIntegerField(payload, "sequence", "seq")?.toString();
|
|
80600
|
+
const providerPayload = capability.providerKind === "cursor_agent_cli" && eventType === "transcript_update" && !transcriptPath && typeof payload.text === "string" ? { ...payload, assistant_response: payload.text } : payload;
|
|
79879
80601
|
return {
|
|
79880
80602
|
schemaVersion: 1,
|
|
79881
80603
|
eventId: (0, import_node_crypto19.randomUUID)(),
|
|
79882
80604
|
provider: capability.provider,
|
|
79883
|
-
eventType
|
|
80605
|
+
eventType,
|
|
79884
80606
|
observedAt: (input2.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
79885
80607
|
externalSessionId,
|
|
79886
|
-
|
|
79887
|
-
...cwd ? { cwd: (0,
|
|
79888
|
-
...transcriptPath ? { transcriptPath: (0,
|
|
80608
|
+
...(eventType === "subagent_start" || eventType === "subagent_end") && parentSessionId ? { parentExternalSessionId: parentSessionId } : {},
|
|
80609
|
+
...cwd ? { cwd: (0, import_node_path26.resolve)(cwd) } : {},
|
|
80610
|
+
...transcriptPath ? { transcriptPath: (0, import_node_path26.resolve)(transcriptPath) } : {},
|
|
79889
80611
|
...cursor ? { sourceCursor: cursor } : {},
|
|
79890
|
-
providerPayload
|
|
80612
|
+
providerPayload
|
|
79891
80613
|
};
|
|
79892
80614
|
}
|
|
79893
80615
|
function normalizeHookEvent(raw) {
|
|
@@ -79896,6 +80618,8 @@ function normalizeHookEvent(raw) {
|
|
|
79896
80618
|
case "session_start":
|
|
79897
80619
|
return "session_start";
|
|
79898
80620
|
case "userpromptsubmit":
|
|
80621
|
+
case "userpromptsubmitted":
|
|
80622
|
+
case "beforesubmitprompt":
|
|
79899
80623
|
case "user_prompt":
|
|
79900
80624
|
return "user_prompt";
|
|
79901
80625
|
case "subagentstart":
|
|
@@ -79908,8 +80632,19 @@ function normalizeHookEvent(raw) {
|
|
|
79908
80632
|
case "session_end":
|
|
79909
80633
|
return "session_end";
|
|
79910
80634
|
case "stop":
|
|
80635
|
+
case "agentstop":
|
|
80636
|
+
case "agent_stop":
|
|
79911
80637
|
case "agent_turn_complete":
|
|
80638
|
+
case "stopfailure":
|
|
80639
|
+
case "stop_failure":
|
|
80640
|
+
case "stopcancelled":
|
|
80641
|
+
case "stop_cancelled":
|
|
80642
|
+
case "interrupt":
|
|
79912
80643
|
return "stop";
|
|
80644
|
+
case "afteragentresponse":
|
|
80645
|
+
case "message.part.updated":
|
|
80646
|
+
case "transcript_update":
|
|
80647
|
+
return "transcript_update";
|
|
79913
80648
|
default:
|
|
79914
80649
|
return "transcript_update";
|
|
79915
80650
|
}
|
|
@@ -79954,21 +80689,34 @@ function runNativeHookCommand(args) {
|
|
|
79954
80689
|
try {
|
|
79955
80690
|
const payload = readBoundedHookPayload();
|
|
79956
80691
|
const enqueued = enqueueNativeHookFromConfig({ args, payload });
|
|
79957
|
-
const hookEvent = argumentValue(args, "--event")
|
|
79958
|
-
|
|
80692
|
+
const hookEvent = argumentValue(args, "--event");
|
|
80693
|
+
const normalizedEvent = normalizeHookEvent(hookEvent ?? "notification");
|
|
80694
|
+
if (enqueued && (normalizedEvent === "user_prompt" || normalizedEvent === "session_start")) {
|
|
79959
80695
|
const providerKind = argumentValue(args, "--provider");
|
|
79960
|
-
const externalSessionId = stringField4(
|
|
80696
|
+
const externalSessionId = stringField4(
|
|
80697
|
+
payload,
|
|
80698
|
+
"session_id",
|
|
80699
|
+
"sessionId",
|
|
80700
|
+
"conversation_id",
|
|
80701
|
+
"conversationId",
|
|
80702
|
+
"thread_id",
|
|
80703
|
+
"threadId"
|
|
80704
|
+
);
|
|
79961
80705
|
const capability = providerKind ? NATIVE_SESSION_PROVIDER_CAPABILITIES.find(
|
|
79962
80706
|
(candidate) => candidate.providerKind === providerKind
|
|
79963
80707
|
) : void 0;
|
|
79964
|
-
|
|
80708
|
+
const shouldInjectLinkingContext = capability && externalSessionId && (capability.providerKind === "claude_cli" || capability.providerKind === "codex_app_server" || capability.providerKind === "kimi_cli" ? normalizedEvent === "user_prompt" : capability.providerKind === "cursor_agent_cli" && normalizedEvent === "session_start");
|
|
80709
|
+
if (shouldInjectLinkingContext && capability && externalSessionId) {
|
|
80710
|
+
const additionalContext = `First call get_native_session_link_status with provider=${capability.provider} and externalSessionId=${externalSessionId}. If status is linked, continue without asking or linking again. If status is syncing, wait briefly and retry the status check. Only when status is pending, ask the user one question: work on an Alan task or continue as a direct session. Resolve a named task with find_records, then call link_native_session. Do not guess a task and do not change task status.`;
|
|
79965
80711
|
process.stdout.write(
|
|
79966
|
-
`${JSON.stringify(
|
|
79967
|
-
|
|
79968
|
-
|
|
79969
|
-
|
|
80712
|
+
`${JSON.stringify(
|
|
80713
|
+
capability.providerKind === "cursor_agent_cli" ? { additional_context: additionalContext } : {
|
|
80714
|
+
hookSpecificOutput: {
|
|
80715
|
+
hookEventName: "UserPromptSubmit",
|
|
80716
|
+
additionalContext
|
|
80717
|
+
}
|
|
79970
80718
|
}
|
|
79971
|
-
|
|
80719
|
+
)}
|
|
79972
80720
|
`
|
|
79973
80721
|
);
|
|
79974
80722
|
}
|
|
@@ -79986,10 +80734,12 @@ function collectNativeIntegrationStatus(args = []) {
|
|
|
79986
80734
|
bindConfigPath(args);
|
|
79987
80735
|
const config2 = readConfig();
|
|
79988
80736
|
const env = getDaemonCliEnvironment();
|
|
80737
|
+
const homeDir = (0, import_node_os15.homedir)();
|
|
79989
80738
|
return NATIVE_SESSION_PROVIDER_CAPABILITIES.map((capability) => ({
|
|
79990
80739
|
provider: capability.providerKind,
|
|
79991
80740
|
command: capability.command,
|
|
79992
80741
|
installed: resolveCliExecutable(capability.command, env) !== null,
|
|
80742
|
+
hooksConfigured: inspectNativeHooksConfigured(capability.providerKind, homeDir),
|
|
79993
80743
|
hookCoverage: capability.capabilities.lifecycleHooks ? "lifecycle" : capability.capabilities.state === "degraded" ? "notification" : "none",
|
|
79994
80744
|
transcriptStreaming: capability.capabilities.transcriptDelta,
|
|
79995
80745
|
inboxReady: Boolean(config2.eventSpoolKey)
|
|
@@ -80013,7 +80763,7 @@ function decodeResumeFallbackContext(encoded) {
|
|
|
80013
80763
|
}
|
|
80014
80764
|
|
|
80015
80765
|
// src/sandbox.ts
|
|
80016
|
-
var
|
|
80766
|
+
var import_node_os16 = require("os");
|
|
80017
80767
|
|
|
80018
80768
|
// src/execution-activity-tracker.ts
|
|
80019
80769
|
var ExecutionActivityTracker = class {
|
|
@@ -81310,7 +82060,7 @@ async function runSandbox(config2) {
|
|
|
81310
82060
|
}
|
|
81311
82061
|
const presenter = new WebPresenter(wsClient, config2.sessionId, config2.projectPath);
|
|
81312
82062
|
presenter.setSuppressSessionLifecycle(true);
|
|
81313
|
-
const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0,
|
|
82063
|
+
const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os16.homedir)() });
|
|
81314
82064
|
let lastProviderSessionId = config2.providerSessionId;
|
|
81315
82065
|
let resumeFallbackContext = config2.resumeFallbackContext;
|
|
81316
82066
|
let activeBackendKind = config2.backendKind || "claude_cli";
|
|
@@ -81610,8 +82360,8 @@ async function runSandbox(config2) {
|
|
|
81610
82360
|
// src/service-manager.ts
|
|
81611
82361
|
var import_node_child_process9 = require("child_process");
|
|
81612
82362
|
var import_node_fs25 = require("fs");
|
|
81613
|
-
var
|
|
81614
|
-
var
|
|
82363
|
+
var import_node_os17 = require("os");
|
|
82364
|
+
var import_node_path27 = require("path");
|
|
81615
82365
|
var SERVICE_LABEL = "ai.tryalan.agent";
|
|
81616
82366
|
var SYSTEMD_UNIT = "alan-agent.service";
|
|
81617
82367
|
var WINDOWS_TASK = "Alan Agent";
|
|
@@ -81631,8 +82381,8 @@ function buildDaemonServicePlan(input2) {
|
|
|
81631
82381
|
if (userId === void 0) throw new Error("Cannot determine the current macOS user ID");
|
|
81632
82382
|
const domain2 = `gui/${userId}`;
|
|
81633
82383
|
const serviceTarget = `${domain2}/${SERVICE_LABEL}`;
|
|
81634
|
-
const manifestPath = (0,
|
|
81635
|
-
const logDir = (0,
|
|
82384
|
+
const manifestPath = (0, import_node_path27.join)(input2.homeDir, "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
82385
|
+
const logDir = (0, import_node_path27.join)(input2.homeDir, ".alan", "agent", "logs");
|
|
81636
82386
|
const programArguments = daemonArgs.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
|
|
81637
82387
|
const environmentEntries = Object.entries(input2.environment ?? {}).map(([key, value2]) => ` <key>${xml(key)}</key>
|
|
81638
82388
|
<string>${xml(value2)}</string>`).join("\n");
|
|
@@ -81661,9 +82411,9 @@ ${environmentBlock} <key>RunAtLoad</key>
|
|
|
81661
82411
|
<key>ThrottleInterval</key>
|
|
81662
82412
|
<integer>5</integer>
|
|
81663
82413
|
<key>StandardOutPath</key>
|
|
81664
|
-
<string>${xml((0,
|
|
82414
|
+
<string>${xml((0, import_node_path27.join)(logDir, "daemon.log"))}</string>
|
|
81665
82415
|
<key>StandardErrorPath</key>
|
|
81666
|
-
<string>${xml((0,
|
|
82416
|
+
<string>${xml((0, import_node_path27.join)(logDir, "daemon-error.log"))}</string>
|
|
81667
82417
|
</dict>
|
|
81668
82418
|
</plist>
|
|
81669
82419
|
`;
|
|
@@ -81702,7 +82452,7 @@ ${environmentBlock} <key>RunAtLoad</key>
|
|
|
81702
82452
|
};
|
|
81703
82453
|
}
|
|
81704
82454
|
if (input2.platform === "linux") {
|
|
81705
|
-
const manifestPath = (0,
|
|
82455
|
+
const manifestPath = (0, import_node_path27.join)(input2.homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
81706
82456
|
const environmentLines = Object.entries(input2.environment ?? {}).map(([key, value2]) => `Environment=${systemdArg(`${key}=${value2}`)}`).join("\n");
|
|
81707
82457
|
const manifest = `[Unit]
|
|
81708
82458
|
Description=Alan local agent daemon
|
|
@@ -81803,7 +82553,7 @@ WantedBy=default.target
|
|
|
81803
82553
|
};
|
|
81804
82554
|
}
|
|
81805
82555
|
function currentServicePlan(args, runtime) {
|
|
81806
|
-
const currentPlatform = (0,
|
|
82556
|
+
const currentPlatform = (0, import_node_os17.platform)();
|
|
81807
82557
|
if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
|
|
81808
82558
|
throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
|
|
81809
82559
|
}
|
|
@@ -81812,15 +82562,15 @@ function currentServicePlan(args, runtime) {
|
|
|
81812
82562
|
if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
|
|
81813
82563
|
return buildDaemonServicePlan({
|
|
81814
82564
|
platform: currentPlatform,
|
|
81815
|
-
homeDir: (0,
|
|
82565
|
+
homeDir: (0, import_node_os17.homedir)(),
|
|
81816
82566
|
nodeExecutable: runtime?.executable ?? process.execPath,
|
|
81817
|
-
cliEntry: (0,
|
|
82567
|
+
cliEntry: (0, import_node_path27.resolve)(cliEntry),
|
|
81818
82568
|
profile,
|
|
81819
82569
|
environment: runtime?.environment
|
|
81820
82570
|
});
|
|
81821
82571
|
}
|
|
81822
82572
|
function writeManifest(path2, contents) {
|
|
81823
|
-
(0, import_node_fs25.mkdirSync)((0,
|
|
82573
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path27.dirname)(path2), { recursive: true, mode: 448 });
|
|
81824
82574
|
const pendingPath = `${path2}.pending-${process.pid}`;
|
|
81825
82575
|
try {
|
|
81826
82576
|
(0, import_node_fs25.writeFileSync)(pendingPath, contents, { mode: 384 });
|
|
@@ -81849,8 +82599,8 @@ function installDaemonService(args = [], runtime) {
|
|
|
81849
82599
|
}
|
|
81850
82600
|
const plan = currentServicePlan(args, runtime);
|
|
81851
82601
|
if (plan.manifestPath && plan.manifest) {
|
|
81852
|
-
if ((0,
|
|
81853
|
-
(0, import_node_fs25.mkdirSync)((0,
|
|
82602
|
+
if ((0, import_node_os17.platform)() === "darwin") {
|
|
82603
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path27.join)((0, import_node_os17.homedir)(), ".alan", "agent", "logs"), { recursive: true, mode: 448 });
|
|
81854
82604
|
}
|
|
81855
82605
|
writeManifest(plan.manifestPath, plan.manifest);
|
|
81856
82606
|
}
|
|
@@ -81872,16 +82622,16 @@ function printDaemonServiceStatus(args = []) {
|
|
|
81872
82622
|
|
|
81873
82623
|
// src/skills/skill-cli.ts
|
|
81874
82624
|
var import_promises6 = require("fs/promises");
|
|
81875
|
-
var
|
|
81876
|
-
var
|
|
82625
|
+
var import_node_os18 = require("os");
|
|
82626
|
+
var import_node_path28 = require("path");
|
|
81877
82627
|
async function runSkillsCommand(args) {
|
|
81878
82628
|
const [subcommand, ...options] = args;
|
|
81879
|
-
const
|
|
81880
|
-
const manager = await RuntimeSkillManager.open({ homeDirectory });
|
|
82629
|
+
const homeDirectory2 = option(options, "--home") ?? (0, import_node_os18.homedir)();
|
|
82630
|
+
const manager = await RuntimeSkillManager.open({ homeDirectory: homeDirectory2 });
|
|
81881
82631
|
if (subcommand === "scan") {
|
|
81882
82632
|
const inputPath = option(options, "--input");
|
|
81883
82633
|
const declaredInput = inputPath ? scanSkillsInputSchema.parse(await readProtectedJson(inputPath)) : null;
|
|
81884
|
-
const input2 = declaredInput ? options.includes("--include-configured") ? await resolveSkillScanInput(
|
|
82634
|
+
const input2 = declaredInput ? options.includes("--include-configured") ? await resolveSkillScanInput(homeDirectory2, declaredInput) : declaredInput : await defaultScanInput(homeDirectory2);
|
|
81885
82635
|
const outcome = await manager.scan(input2);
|
|
81886
82636
|
process.stdout.write(`${JSON.stringify(outcome)}
|
|
81887
82637
|
`);
|
|
@@ -81908,8 +82658,8 @@ async function runSkillsCommand(args) {
|
|
|
81908
82658
|
"Usage: alan-agent skills scan [--input <0600-json>] [--include-configured] [--home <path>] | skills reconcile --manifest <0600-json> [--home <path>] | skills publish --input <0600-json> [--home <path>]"
|
|
81909
82659
|
);
|
|
81910
82660
|
}
|
|
81911
|
-
async function defaultScanInput(
|
|
81912
|
-
return resolveSkillScanInput(
|
|
82661
|
+
async function defaultScanInput(homeDirectory2) {
|
|
82662
|
+
return resolveSkillScanInput(homeDirectory2, {
|
|
81913
82663
|
mode: "audit",
|
|
81914
82664
|
reason: "refresh",
|
|
81915
82665
|
enabledProviderKinds: [],
|
|
@@ -81917,7 +82667,7 @@ async function defaultScanInput(homeDirectory) {
|
|
|
81917
82667
|
});
|
|
81918
82668
|
}
|
|
81919
82669
|
async function readProtectedJson(path2) {
|
|
81920
|
-
const absolutePath = (0,
|
|
82670
|
+
const absolutePath = (0, import_node_path28.resolve)(path2);
|
|
81921
82671
|
const stat2 = await (0, import_promises6.lstat)(absolutePath);
|
|
81922
82672
|
if (!stat2.isFile()) throw new Error(`Skill input is not a regular file: ${absolutePath}`);
|
|
81923
82673
|
if (process.platform !== "win32" && (stat2.mode & 63) !== 0) {
|