agent-shim 7.7.0 → 7.8.0
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/README.md +2 -1
- package/dist/cli.cjs +3682 -3677
- package/dist/index.cjs +1052 -173
- package/dist/index.mjs +982 -158
- package/dist/types/cli/bool.d.ts +8 -0
- package/dist/types/cli/parsers.d.ts +40 -0
- package/dist/types/configProfilesStore.d.ts +61 -0
- package/dist/types/credential.d.ts +136 -0
- package/dist/types/credentialCache.d.ts +46 -0
- package/dist/types/directoryRulesStore.d.ts +43 -0
- package/dist/types/headroom/headers.d.ts +11 -0
- package/dist/types/identityStore.d.ts +85 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/launcher/flags.d.ts +96 -0
- package/dist/types/launcher/identity.d.ts +95 -0
- package/dist/types/poolStore.d.ts +18 -0
- package/dist/types/providersStore.d.ts +137 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,9 @@ __export(index_exports, {
|
|
|
42
42
|
CredentialCacheSchema: () => CredentialCacheSchema,
|
|
43
43
|
CredentialSchema: () => CredentialSchema,
|
|
44
44
|
CredentialSourceSchema: () => CredentialSourceSchema,
|
|
45
|
+
DirectoryRuleAlreadyExistsError: () => DirectoryRuleAlreadyExistsError,
|
|
46
|
+
DirectoryRuleMissingTargetError: () => DirectoryRuleMissingTargetError,
|
|
47
|
+
DirectoryRuleNotFoundError: () => DirectoryRuleNotFoundError,
|
|
45
48
|
DirectoryRuleSchema: () => DirectoryRuleSchema,
|
|
46
49
|
DirectoryRulesSchema: () => DirectoryRulesSchema,
|
|
47
50
|
EXIT_FAILURE: () => EXIT_FAILURE,
|
|
@@ -51,20 +54,38 @@ __export(index_exports, {
|
|
|
51
54
|
FrontDoorStartError: () => FrontDoorStartError,
|
|
52
55
|
GlobalConfigSchema: () => GlobalConfigSchema,
|
|
53
56
|
HeadroomStartError: () => HeadroomStartError,
|
|
57
|
+
IdentityAlreadyExistsError: () => IdentityAlreadyExistsError,
|
|
58
|
+
IdentityNotFoundError: () => IdentityNotFoundError,
|
|
54
59
|
IdentitySchema: () => IdentitySchema,
|
|
60
|
+
InvalidCategoryNameError: () => InvalidCategoryNameError,
|
|
61
|
+
InvalidIdentityNameError: () => InvalidIdentityNameError,
|
|
62
|
+
InvalidProviderNameError: () => InvalidProviderNameError,
|
|
63
|
+
LegacyProviderFileError: () => LegacyProviderFileError,
|
|
55
64
|
PoolNameSchema: () => PoolNameSchema,
|
|
65
|
+
PoolNotFoundError: () => PoolNotFoundError,
|
|
56
66
|
PoolSchema: () => PoolSchema,
|
|
57
67
|
PortableConfigSchema: () => PortableConfigSchema,
|
|
68
|
+
ProfileAlreadyExistsError: () => ProfileAlreadyExistsError,
|
|
69
|
+
ProfileNotFoundError: () => ProfileNotFoundError,
|
|
70
|
+
ProviderAlreadyExistsError: () => ProviderAlreadyExistsError,
|
|
71
|
+
ProviderKindMismatchError: () => ProviderKindMismatchError,
|
|
72
|
+
ProviderNotFoundError: () => ProviderNotFoundError,
|
|
58
73
|
ProviderSchema: () => ProviderSchema,
|
|
59
74
|
ROUTED_PATH_PREFIX: () => ROUTED_PATH_PREFIX,
|
|
60
75
|
UsageError: () => UsageError,
|
|
61
76
|
UsageSnapshotError: () => UsageSnapshotError,
|
|
62
77
|
UsageSnapshotSchema: () => UsageSnapshotSchema,
|
|
63
78
|
WhenSchema: () => WhenSchema,
|
|
79
|
+
addDirectoryRule: () => addDirectoryRule,
|
|
80
|
+
addIdentity: () => addIdentity,
|
|
81
|
+
addPool: () => addPool,
|
|
82
|
+
addProvider: () => addProvider,
|
|
64
83
|
buildEntryFacts: () => buildEntryFacts,
|
|
65
84
|
buildLayoutPaths: () => buildLayoutPaths,
|
|
66
85
|
carryOver: () => carryOver,
|
|
67
86
|
createLeafCache: () => createLeafCache,
|
|
87
|
+
createProfile: () => createProfile,
|
|
88
|
+
describeProviderEndpoint: () => describeProviderEndpoint,
|
|
68
89
|
detectAmbientCredential: () => detectAmbientCredential,
|
|
69
90
|
ensureCa: () => ensureCa,
|
|
70
91
|
ensureFrontDoor: () => ensureFrontDoor,
|
|
@@ -73,16 +94,37 @@ __export(index_exports, {
|
|
|
73
94
|
formatAmbientCredentialGuardMessage: () => formatAmbientCredentialGuardMessage,
|
|
74
95
|
forwardableHeaders: () => forwardableHeaders,
|
|
75
96
|
generateCa: () => generateCa,
|
|
97
|
+
identityExists: () => identityExists,
|
|
98
|
+
isIdentityDirectoryName: () => isIdentityDirectoryName,
|
|
76
99
|
isInterceptedHost: () => isInterceptedHost,
|
|
100
|
+
listDirectoryRules: () => listDirectoryRules,
|
|
101
|
+
listIdentities: () => listIdentities,
|
|
102
|
+
listProfiles: () => listProfiles,
|
|
103
|
+
listProviders: () => listProviders,
|
|
77
104
|
listUsageSnapshots: () => listUsageSnapshots,
|
|
78
105
|
mintLeaf: () => mintLeaf,
|
|
79
106
|
parseConnectTarget: () => parseConnectTarget,
|
|
107
|
+
profileExists: () => profileExists,
|
|
108
|
+
providerExists: () => providerExists,
|
|
109
|
+
readActiveIdentity: () => readActiveIdentity,
|
|
110
|
+
readDirectoryRules: () => readDirectoryRules,
|
|
80
111
|
readFarmManifest: () => readFarmManifest,
|
|
112
|
+
readGlobalConfig: () => readGlobalConfig,
|
|
113
|
+
readIdentity: () => readIdentity,
|
|
114
|
+
readPools: () => readPools,
|
|
115
|
+
readProfile: () => readProfile,
|
|
116
|
+
readProvider: () => readProvider,
|
|
81
117
|
readUsageSnapshot: () => readUsageSnapshot,
|
|
82
118
|
realConnectCertStore: () => realConnectCertStore,
|
|
83
119
|
realConnectEffects: () => realConnectEffects,
|
|
84
120
|
recoverFarm: () => recoverFarm,
|
|
85
121
|
recoveryDiagnostics: () => recoveryDiagnostics,
|
|
122
|
+
removeDirectoryRule: () => removeDirectoryRule,
|
|
123
|
+
removeIdentity: () => removeIdentity,
|
|
124
|
+
removePool: () => removePool,
|
|
125
|
+
removeProfile: () => removeProfile,
|
|
126
|
+
removeProvider: () => removeProvider,
|
|
127
|
+
requirePool: () => requirePool,
|
|
86
128
|
resolveAgentShimHome: () => resolveAgentShimHome,
|
|
87
129
|
resolveClaudeHome: () => resolveClaudeHome,
|
|
88
130
|
resolveDecisions: () => resolveDecisions,
|
|
@@ -92,9 +134,22 @@ __export(index_exports, {
|
|
|
92
134
|
runFrontDoorSupervisor: () => runFrontDoorSupervisor,
|
|
93
135
|
runSupervisor: () => runSupervisor,
|
|
94
136
|
servedByPipeline: () => servedByPipeline,
|
|
137
|
+
setAllowAmbientCredential: () => setAllowAmbientCredential,
|
|
138
|
+
setDefaultConfigProfile: () => setDefaultConfigProfile,
|
|
139
|
+
setGlobalDefaultProfile: () => setGlobalDefaultProfile,
|
|
140
|
+
setIdentityCredential: () => setIdentityCredential,
|
|
141
|
+
setPool: () => setPool,
|
|
142
|
+
setProfileCategories: () => setProfileCategories,
|
|
143
|
+
setProfileEntries: () => setProfileEntries,
|
|
144
|
+
setProfileLaunchFlags: () => setProfileLaunchFlags,
|
|
145
|
+
setProfileMetadata: () => setProfileMetadata,
|
|
95
146
|
snapshotPath: () => snapshotPath,
|
|
96
147
|
startConnectServer: () => startConnectServer,
|
|
97
|
-
topLevelNames: () => topLevelNames
|
|
148
|
+
topLevelNames: () => topLevelNames,
|
|
149
|
+
updateDirectoryRule: () => updateDirectoryRule,
|
|
150
|
+
updateProvider: () => updateProvider,
|
|
151
|
+
useIdentity: () => useIdentity,
|
|
152
|
+
writeDirectoryRules: () => writeDirectoryRules
|
|
98
153
|
});
|
|
99
154
|
module.exports = __toCommonJS(index_exports);
|
|
100
155
|
|
|
@@ -343,6 +398,11 @@ var SHIPPED_CATEGORY_DEFAULTS = Object.freeze({
|
|
|
343
398
|
settings: true
|
|
344
399
|
});
|
|
345
400
|
|
|
401
|
+
// src/config/store.ts
|
|
402
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
403
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
404
|
+
var import_node_crypto = require("node:crypto");
|
|
405
|
+
|
|
346
406
|
// src/config/load.ts
|
|
347
407
|
var import_cosmiconfig = require("cosmiconfig");
|
|
348
408
|
|
|
@@ -361,6 +421,98 @@ var UsageError = class extends CliError {
|
|
|
361
421
|
}
|
|
362
422
|
};
|
|
363
423
|
|
|
424
|
+
// src/config/load.ts
|
|
425
|
+
var ConfigValidationError = class extends CliError {
|
|
426
|
+
constructor(filepath, issues) {
|
|
427
|
+
const detail = issues.map((issue) => ` ${issue.path.join(".") || "(root)"}: ${issue.message}`).join("\n");
|
|
428
|
+
super(`Invalid configuration in ${filepath}:
|
|
429
|
+
${detail}`);
|
|
430
|
+
this.filepath = filepath;
|
|
431
|
+
this.issues = issues;
|
|
432
|
+
this.name = "ConfigValidationError";
|
|
433
|
+
}
|
|
434
|
+
filepath;
|
|
435
|
+
issues;
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// src/config/store.ts
|
|
439
|
+
function isEnoent(error) {
|
|
440
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
441
|
+
}
|
|
442
|
+
var nodeStoreFs = {
|
|
443
|
+
readFileUtf8(filePath) {
|
|
444
|
+
try {
|
|
445
|
+
return import_node_fs.default.readFileSync(filePath, "utf8");
|
|
446
|
+
} catch (error) {
|
|
447
|
+
if (isEnoent(error)) {
|
|
448
|
+
return void 0;
|
|
449
|
+
}
|
|
450
|
+
throw error;
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
writeFileUtf8(filePath, contents) {
|
|
454
|
+
import_node_fs.default.writeFileSync(filePath, contents, "utf8");
|
|
455
|
+
},
|
|
456
|
+
renameSync(from, to) {
|
|
457
|
+
import_node_fs.default.renameSync(from, to);
|
|
458
|
+
},
|
|
459
|
+
mkdirSync(dirPath) {
|
|
460
|
+
import_node_fs.default.mkdirSync(dirPath, { recursive: true });
|
|
461
|
+
},
|
|
462
|
+
unlinkSync(filePath) {
|
|
463
|
+
try {
|
|
464
|
+
import_node_fs.default.unlinkSync(filePath);
|
|
465
|
+
} catch (error) {
|
|
466
|
+
if (!isEnoent(error)) {
|
|
467
|
+
throw error;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
function readJson(filePath, schema, storeFs = nodeStoreFs) {
|
|
473
|
+
const raw = storeFs.readFileUtf8(filePath);
|
|
474
|
+
if (raw === void 0) {
|
|
475
|
+
return void 0;
|
|
476
|
+
}
|
|
477
|
+
const parsed = JSON.parse(raw);
|
|
478
|
+
const result = schema.safeParse(parsed);
|
|
479
|
+
if (!result.success) {
|
|
480
|
+
throw new ConfigValidationError(filePath, result.error.issues);
|
|
481
|
+
}
|
|
482
|
+
return result.data;
|
|
483
|
+
}
|
|
484
|
+
function writeTextAtomic(filePath, contents, storeFs = nodeStoreFs) {
|
|
485
|
+
const dir = import_node_path2.default.dirname(filePath);
|
|
486
|
+
storeFs.mkdirSync(dir);
|
|
487
|
+
const tempPath = import_node_path2.default.join(dir, `.${import_node_path2.default.basename(filePath)}.${String(process.pid)}.${(0, import_node_crypto.randomUUID)()}.tmp`);
|
|
488
|
+
storeFs.writeFileUtf8(tempPath, contents);
|
|
489
|
+
try {
|
|
490
|
+
storeFs.renameSync(tempPath, filePath);
|
|
491
|
+
} catch (error) {
|
|
492
|
+
storeFs.unlinkSync(tempPath);
|
|
493
|
+
throw error;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function writeJsonAtomic(filePath, data, storeFs = nodeStoreFs) {
|
|
497
|
+
writeTextAtomic(filePath, `${JSON.stringify(data, null, 2)}
|
|
498
|
+
`, storeFs);
|
|
499
|
+
}
|
|
500
|
+
function applyPatch(filePath, schema, patch, options = {}) {
|
|
501
|
+
const storeFs = options.storeFs ?? nodeStoreFs;
|
|
502
|
+
const existing = readJson(filePath, schema, storeFs) ?? options.defaults;
|
|
503
|
+
if (existing === void 0) {
|
|
504
|
+
throw new Error(`Cannot patch ${filePath}: it does not exist yet and no defaults were provided.`);
|
|
505
|
+
}
|
|
506
|
+
const merged = { ...existing, ...patch };
|
|
507
|
+
const result = schema.safeParse(merged);
|
|
508
|
+
if (!result.success) {
|
|
509
|
+
throw new ConfigValidationError(filePath, result.error.issues);
|
|
510
|
+
}
|
|
511
|
+
const validated = result.data;
|
|
512
|
+
writeJsonAtomic(filePath, validated, storeFs);
|
|
513
|
+
return validated;
|
|
514
|
+
}
|
|
515
|
+
|
|
364
516
|
// src/config/classify.ts
|
|
365
517
|
var GLOB_METACHARACTERS = /[*?[\]{}!()]/;
|
|
366
518
|
function isExactPattern(pattern) {
|
|
@@ -952,7 +1104,7 @@ function dedupeDiagnostics(diagnostics) {
|
|
|
952
1104
|
}
|
|
953
1105
|
|
|
954
1106
|
// src/resolve/plan.ts
|
|
955
|
-
var
|
|
1107
|
+
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
956
1108
|
function parentOf(rel) {
|
|
957
1109
|
const index = rel.lastIndexOf("/");
|
|
958
1110
|
return index === -1 ? "" : rel.slice(0, index);
|
|
@@ -1002,7 +1154,7 @@ function planFarm(params) {
|
|
|
1002
1154
|
}
|
|
1003
1155
|
return value;
|
|
1004
1156
|
};
|
|
1005
|
-
const linkTarget = (rel) =>
|
|
1157
|
+
const linkTarget = (rel) => import_node_path3.default.join(params.facts.claudeHome, rel);
|
|
1006
1158
|
const visit = (rel) => {
|
|
1007
1159
|
const fact = params.facts.entries.get(rel);
|
|
1008
1160
|
const decision = params.decisions.get(rel);
|
|
@@ -1226,7 +1378,7 @@ function resolveDecisions(input) {
|
|
|
1226
1378
|
}
|
|
1227
1379
|
|
|
1228
1380
|
// src/launcher/farm.ts
|
|
1229
|
-
var
|
|
1381
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
1230
1382
|
var import_zod2 = require("zod");
|
|
1231
1383
|
|
|
1232
1384
|
// src/resolve/reconcile.ts
|
|
@@ -1325,8 +1477,8 @@ var LEGACY_HOME_DIRNAME = ".claude-use";
|
|
|
1325
1477
|
var LEGACY_FARM_MANIFEST_FILENAME = ".claude-use-farm.json";
|
|
1326
1478
|
|
|
1327
1479
|
// src/launcher/lock.ts
|
|
1328
|
-
var
|
|
1329
|
-
var
|
|
1480
|
+
var import_node_crypto2 = require("node:crypto");
|
|
1481
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
1330
1482
|
var DEFAULT_STALE_AFTER_MS = 12e4;
|
|
1331
1483
|
var DEFAULT_RETRY_DELAY_MS = 50;
|
|
1332
1484
|
var DEFAULT_MAX_ATTEMPTS = 200;
|
|
@@ -1345,7 +1497,7 @@ var IdentityLockBusyError = class extends CliError {
|
|
|
1345
1497
|
holderPid;
|
|
1346
1498
|
};
|
|
1347
1499
|
function identityLockPath(dir, identity) {
|
|
1348
|
-
return
|
|
1500
|
+
return import_node_path4.default.join(dir, `.${identity}.lock`);
|
|
1349
1501
|
}
|
|
1350
1502
|
function parseLockRecord(raw) {
|
|
1351
1503
|
if (raw === void 0) {
|
|
@@ -1374,7 +1526,7 @@ function acquireIdentityLock(params) {
|
|
|
1374
1526
|
const staleAfterMs = params.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
1375
1527
|
const retryDelayMs = params.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
1376
1528
|
const maxAttempts = params.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
1377
|
-
const token = (0,
|
|
1529
|
+
const token = (0, import_node_crypto2.randomUUID)();
|
|
1378
1530
|
if (params.fs.lstat(params.dir) === void 0) {
|
|
1379
1531
|
params.fs.mkdirp(params.dir);
|
|
1380
1532
|
}
|
|
@@ -1423,8 +1575,8 @@ var FarmManifestSchema = import_zod2.z.strictObject({
|
|
|
1423
1575
|
materialised: import_zod2.z.array(import_zod2.z.string()),
|
|
1424
1576
|
links: import_zod2.z.array(import_zod2.z.strictObject({ rel: import_zod2.z.string(), target: import_zod2.z.string() }))
|
|
1425
1577
|
});
|
|
1426
|
-
function readFarmManifest(
|
|
1427
|
-
const raw =
|
|
1578
|
+
function readFarmManifest(fs7, farmRoot) {
|
|
1579
|
+
const raw = fs7.readFileUtf8(import_node_path5.default.join(farmRoot, FARM_MANIFEST_FILENAME)) ?? fs7.readFileUtf8(import_node_path5.default.join(farmRoot, LEGACY_FARM_MANIFEST_FILENAME));
|
|
1428
1580
|
if (raw === void 0) {
|
|
1429
1581
|
return void 0;
|
|
1430
1582
|
}
|
|
@@ -1440,7 +1592,7 @@ function readFarmManifest(fs3, farmRoot) {
|
|
|
1440
1592
|
function buildEntryFacts(params) {
|
|
1441
1593
|
const entries = /* @__PURE__ */ new Map();
|
|
1442
1594
|
const visit = (rel) => {
|
|
1443
|
-
const absolute =
|
|
1595
|
+
const absolute = import_node_path5.default.join(params.claudeHome, rel);
|
|
1444
1596
|
const stat = params.fs.lstat(absolute);
|
|
1445
1597
|
if (stat === void 0) {
|
|
1446
1598
|
return void 0;
|
|
@@ -1482,9 +1634,9 @@ function buildEntryFacts(params) {
|
|
|
1482
1634
|
entries
|
|
1483
1635
|
};
|
|
1484
1636
|
}
|
|
1485
|
-
function listSubtree(
|
|
1486
|
-
const absolute =
|
|
1487
|
-
const stat =
|
|
1637
|
+
function listSubtree(fs7, root, rel) {
|
|
1638
|
+
const absolute = import_node_path5.default.join(root, rel);
|
|
1639
|
+
const stat = fs7.lstat(absolute);
|
|
1488
1640
|
if (stat === void 0) {
|
|
1489
1641
|
return [];
|
|
1490
1642
|
}
|
|
@@ -1492,10 +1644,10 @@ function listSubtree(fs3, root, rel) {
|
|
|
1492
1644
|
return [{ rel, kind: "symlink" }];
|
|
1493
1645
|
}
|
|
1494
1646
|
if (stat.kind === "dir") {
|
|
1495
|
-
const children = [...
|
|
1647
|
+
const children = [...fs7.readdir(absolute)].sort().flatMap((name) => listSubtree(fs7, root, `${rel}/${name}`));
|
|
1496
1648
|
return [{ rel, kind: "dir" }, ...children];
|
|
1497
1649
|
}
|
|
1498
|
-
const contentHash =
|
|
1650
|
+
const contentHash = fs7.hashFile(absolute);
|
|
1499
1651
|
return [{ rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } }];
|
|
1500
1652
|
}
|
|
1501
1653
|
function topLevelScopeRoots(roots) {
|
|
@@ -1509,25 +1661,25 @@ function topLevelScopeRoots(roots) {
|
|
|
1509
1661
|
}
|
|
1510
1662
|
return kept;
|
|
1511
1663
|
}
|
|
1512
|
-
function reconciliationScope(
|
|
1664
|
+
function reconciliationScope(fs7, farmRoot, manifest) {
|
|
1513
1665
|
if (manifest !== void 0) {
|
|
1514
1666
|
return topLevelScopeRoots(manifest.materialised);
|
|
1515
1667
|
}
|
|
1516
|
-
return [...
|
|
1668
|
+
return [...fs7.readdir(farmRoot)].filter((name) => name !== FARM_MANIFEST_FILENAME && name !== LEGACY_FARM_MANIFEST_FILENAME && fs7.lstat(import_node_path5.default.join(farmRoot, name))?.kind === "dir").sort();
|
|
1517
1669
|
}
|
|
1518
|
-
function collectFarmListing(
|
|
1519
|
-
return scopeRoots.flatMap((root) => listSubtree(
|
|
1670
|
+
function collectFarmListing(fs7, farmRoot, scopeRoots) {
|
|
1671
|
+
return scopeRoots.flatMap((root) => listSubtree(fs7, farmRoot, root));
|
|
1520
1672
|
}
|
|
1521
|
-
function collectCanonicalCounterparts(
|
|
1673
|
+
function collectCanonicalCounterparts(fs7, claudeHome, farmListing) {
|
|
1522
1674
|
const out = [];
|
|
1523
1675
|
for (const entry of farmListing) {
|
|
1524
|
-
const absolute =
|
|
1525
|
-
const stat =
|
|
1676
|
+
const absolute = import_node_path5.default.join(claudeHome, entry.rel);
|
|
1677
|
+
const stat = fs7.lstat(absolute);
|
|
1526
1678
|
if (stat === void 0) {
|
|
1527
1679
|
continue;
|
|
1528
1680
|
}
|
|
1529
1681
|
if (stat.kind === "file") {
|
|
1530
|
-
const contentHash =
|
|
1682
|
+
const contentHash = fs7.hashFile(absolute);
|
|
1531
1683
|
out.push({ rel: entry.rel, kind: "file", ...contentHash === void 0 ? {} : { contentHash } });
|
|
1532
1684
|
continue;
|
|
1533
1685
|
}
|
|
@@ -1551,21 +1703,21 @@ function carryOver(params) {
|
|
|
1551
1703
|
if (accounted.has(name)) {
|
|
1552
1704
|
continue;
|
|
1553
1705
|
}
|
|
1554
|
-
const stat = params.fs.lstat(
|
|
1706
|
+
const stat = params.fs.lstat(import_node_path5.default.join(params.previousRoot, name));
|
|
1555
1707
|
if (stat === void 0 || stat.kind === "symlink") {
|
|
1556
1708
|
continue;
|
|
1557
1709
|
}
|
|
1558
|
-
if (params.fs.lstat(
|
|
1710
|
+
if (params.fs.lstat(import_node_path5.default.join(params.farmRoot, name)) !== void 0) {
|
|
1559
1711
|
const category = params.classification === void 0 ? void 0 : classifyEntries([name], params.classification).classification.get(name);
|
|
1560
1712
|
if (category === "runtime") {
|
|
1561
|
-
params.fs.removeRecursive(
|
|
1713
|
+
params.fs.removeRecursive(import_node_path5.default.join(params.previousRoot, name));
|
|
1562
1714
|
autoResolved.push(name);
|
|
1563
1715
|
continue;
|
|
1564
1716
|
}
|
|
1565
1717
|
collided.push(name);
|
|
1566
1718
|
continue;
|
|
1567
1719
|
}
|
|
1568
|
-
params.fs.rename(
|
|
1720
|
+
params.fs.rename(import_node_path5.default.join(params.previousRoot, name), import_node_path5.default.join(params.farmRoot, name));
|
|
1569
1721
|
carried.push(name);
|
|
1570
1722
|
}
|
|
1571
1723
|
return { carried, autoResolved, collided };
|
|
@@ -1573,9 +1725,9 @@ function carryOver(params) {
|
|
|
1573
1725
|
function buildScratchTree(params) {
|
|
1574
1726
|
params.fs.mkdirp(params.scratchRoot);
|
|
1575
1727
|
for (const entry of params.plan.entries) {
|
|
1576
|
-
const absolute =
|
|
1728
|
+
const absolute = import_node_path5.default.join(params.scratchRoot, entry.rel);
|
|
1577
1729
|
if (entry.kind === "link") {
|
|
1578
|
-
params.fs.mkdirp(
|
|
1730
|
+
params.fs.mkdirp(import_node_path5.default.dirname(absolute));
|
|
1579
1731
|
params.fs.symlink(entry.target, absolute);
|
|
1580
1732
|
continue;
|
|
1581
1733
|
}
|
|
@@ -1584,14 +1736,14 @@ function buildScratchTree(params) {
|
|
|
1584
1736
|
}
|
|
1585
1737
|
}
|
|
1586
1738
|
params.fs.writeFileUtf8(
|
|
1587
|
-
|
|
1739
|
+
import_node_path5.default.join(params.scratchRoot, FARM_MANIFEST_FILENAME),
|
|
1588
1740
|
`${JSON.stringify(params.manifest, null, 2)}
|
|
1589
1741
|
`
|
|
1590
1742
|
);
|
|
1591
1743
|
}
|
|
1592
1744
|
function swapIn(params) {
|
|
1593
1745
|
if (params.fs.lstat(params.farmRoot) === void 0) {
|
|
1594
|
-
params.fs.mkdirp(
|
|
1746
|
+
params.fs.mkdirp(import_node_path5.default.dirname(params.farmRoot));
|
|
1595
1747
|
params.fs.rename(params.scratchRoot, params.farmRoot);
|
|
1596
1748
|
return { carried: [], autoResolved: [], collided: [] };
|
|
1597
1749
|
}
|
|
@@ -1615,14 +1767,14 @@ function recoverInterruptedSwap(params) {
|
|
|
1615
1767
|
const names = [...params.fs.readdir(params.identitiesDir)].sort();
|
|
1616
1768
|
const removedScratch = [];
|
|
1617
1769
|
for (const name of names.filter((candidate) => candidate.startsWith(scratchPrefix))) {
|
|
1618
|
-
params.fs.removeRecursive(
|
|
1770
|
+
params.fs.removeRecursive(import_node_path5.default.join(params.identitiesDir, name));
|
|
1619
1771
|
removedScratch.push(name);
|
|
1620
1772
|
}
|
|
1621
1773
|
let previous = names.filter((candidate) => candidate.startsWith(previousPrefix));
|
|
1622
1774
|
let restoredFrom;
|
|
1623
1775
|
const first = previous[0];
|
|
1624
1776
|
if (first !== void 0 && params.fs.lstat(params.farmRoot) === void 0) {
|
|
1625
|
-
params.fs.rename(
|
|
1777
|
+
params.fs.rename(import_node_path5.default.join(params.identitiesDir, first), params.farmRoot);
|
|
1626
1778
|
restoredFrom = first;
|
|
1627
1779
|
previous = previous.slice(1);
|
|
1628
1780
|
}
|
|
@@ -1630,7 +1782,7 @@ function recoverInterruptedSwap(params) {
|
|
|
1630
1782
|
const autoResolved = [];
|
|
1631
1783
|
const retained = [];
|
|
1632
1784
|
for (const name of previous) {
|
|
1633
|
-
const previousRoot =
|
|
1785
|
+
const previousRoot = import_node_path5.default.join(params.identitiesDir, name);
|
|
1634
1786
|
const result = carryOver({
|
|
1635
1787
|
fs: params.fs,
|
|
1636
1788
|
previousRoot,
|
|
@@ -1655,7 +1807,7 @@ function recoverInterruptedSwap(params) {
|
|
|
1655
1807
|
};
|
|
1656
1808
|
}
|
|
1657
1809
|
function recoverFarm(params) {
|
|
1658
|
-
const farmRoot =
|
|
1810
|
+
const farmRoot = import_node_path5.default.join(params.identitiesDir, params.identity);
|
|
1659
1811
|
const lock = acquireIdentityLock({
|
|
1660
1812
|
identity: params.identity,
|
|
1661
1813
|
dir: params.identitiesDir,
|
|
@@ -1714,16 +1866,16 @@ function executeReconciliation(params) {
|
|
|
1714
1866
|
});
|
|
1715
1867
|
continue;
|
|
1716
1868
|
}
|
|
1717
|
-
const from =
|
|
1718
|
-
const canonical =
|
|
1869
|
+
const from = import_node_path5.default.join(params.farmRoot, action.rel);
|
|
1870
|
+
const canonical = import_node_path5.default.join(params.claudeHome, action.rel);
|
|
1719
1871
|
if (action.kind === "adopt") {
|
|
1720
|
-
params.fs.mkdirp(
|
|
1872
|
+
params.fs.mkdirp(import_node_path5.default.dirname(canonical));
|
|
1721
1873
|
params.fs.copyRecursive(from, canonical);
|
|
1722
1874
|
adopted.push(action.rel);
|
|
1723
1875
|
continue;
|
|
1724
1876
|
}
|
|
1725
1877
|
const preserved = `${canonical}.farm-conflict-${String(params.nowMs)}`;
|
|
1726
|
-
params.fs.mkdirp(
|
|
1878
|
+
params.fs.mkdirp(import_node_path5.default.dirname(canonical));
|
|
1727
1879
|
params.fs.copyRecursive(from, preserved);
|
|
1728
1880
|
conflicts.push(action.rel);
|
|
1729
1881
|
}
|
|
@@ -1748,7 +1900,7 @@ function farmAlreadyMatches(existing, next) {
|
|
|
1748
1900
|
return existing.identity === next.identity && existing.claudeHome === next.claudeHome && sameStrings(existing.materialised, next.materialised) && sameLinks(existing.links, next.links);
|
|
1749
1901
|
}
|
|
1750
1902
|
function resyncFarm(params) {
|
|
1751
|
-
const farmRoot =
|
|
1903
|
+
const farmRoot = import_node_path5.default.join(params.identitiesDir, params.identity);
|
|
1752
1904
|
const lock = acquireIdentityLock({
|
|
1753
1905
|
identity: params.identity,
|
|
1754
1906
|
dir: params.identitiesDir,
|
|
@@ -1827,8 +1979,8 @@ function resyncFarm(params) {
|
|
|
1827
1979
|
diagnostics
|
|
1828
1980
|
};
|
|
1829
1981
|
}
|
|
1830
|
-
const scratchRoot =
|
|
1831
|
-
const previousRoot =
|
|
1982
|
+
const scratchRoot = import_node_path5.default.join(params.identitiesDir, `.${params.identity}.scratch.${params.uniqueSuffix}`);
|
|
1983
|
+
const previousRoot = import_node_path5.default.join(params.identitiesDir, `.${params.identity}.previous.${params.uniqueSuffix}`);
|
|
1832
1984
|
buildScratchTree({ fs: params.fs, scratchRoot, plan: resolved.farm, manifest });
|
|
1833
1985
|
const swap = swapIn({ fs: params.fs, farmRoot, scratchRoot, previousRoot, classification: params.classification });
|
|
1834
1986
|
if (swap.retainedPrevious !== void 0) {
|
|
@@ -1885,11 +2037,11 @@ function recoveryDiagnostics(recovery, identity) {
|
|
|
1885
2037
|
}
|
|
1886
2038
|
|
|
1887
2039
|
// src/frontdoor/connect.ts
|
|
1888
|
-
var
|
|
1889
|
-
var
|
|
2040
|
+
var import_node_crypto4 = require("node:crypto");
|
|
2041
|
+
var fs2 = __toESM(require("node:fs"), 1);
|
|
1890
2042
|
|
|
1891
2043
|
// src/frontdoor/x509.ts
|
|
1892
|
-
var
|
|
2044
|
+
var import_node_crypto3 = require("node:crypto");
|
|
1893
2045
|
var import_node_net = __toESM(require("node:net"), 1);
|
|
1894
2046
|
var TAG_BOOLEAN = 1;
|
|
1895
2047
|
var TAG_INTEGER = 2;
|
|
@@ -2041,7 +2193,7 @@ function ipBytes(address) {
|
|
|
2041
2193
|
return bytes;
|
|
2042
2194
|
}
|
|
2043
2195
|
function keyIdentifier(publicKey) {
|
|
2044
|
-
return (0,
|
|
2196
|
+
return (0, import_node_crypto3.createHash)("sha1").update(publicKey.export({ type: "pkcs1", format: "der" })).digest();
|
|
2045
2197
|
}
|
|
2046
2198
|
function readElement(buffer, offset) {
|
|
2047
2199
|
const tag = buffer[offset];
|
|
@@ -2087,7 +2239,7 @@ ${body.join("\n")}
|
|
|
2087
2239
|
`;
|
|
2088
2240
|
}
|
|
2089
2241
|
function randomSerial() {
|
|
2090
|
-
const bytes = (0,
|
|
2242
|
+
const bytes = (0, import_node_crypto3.randomBytes)(SERIAL_NUMBER_BYTES);
|
|
2091
2243
|
bytes[0] = (bytes[0] ?? 0) & BASE_128_PAYLOAD_MASK | HIGH_BIT >> 1;
|
|
2092
2244
|
return bytes;
|
|
2093
2245
|
}
|
|
@@ -2102,7 +2254,7 @@ function assemble(spec) {
|
|
|
2102
2254
|
spec.subjectPublicKey.export({ type: "spki", format: "der" }),
|
|
2103
2255
|
tlv(TAG_EXTENSIONS, sequence(...spec.extensions))
|
|
2104
2256
|
);
|
|
2105
|
-
const signature = (0,
|
|
2257
|
+
const signature = (0, import_node_crypto3.sign)("sha256", tbs, spec.signingKey);
|
|
2106
2258
|
return sequence(tbs, SIGNATURE_ALGORITHM, wholeBitString(signature));
|
|
2107
2259
|
}
|
|
2108
2260
|
function subjectKeyIdentifierExtension(publicKey) {
|
|
@@ -2112,7 +2264,7 @@ function basicConstraintsExtension(isCa) {
|
|
|
2112
2264
|
return extension(OID_BASIC_CONSTRAINTS, true, sequence(...isCa ? [boolean(true)] : []));
|
|
2113
2265
|
}
|
|
2114
2266
|
function rsaKeyPair() {
|
|
2115
|
-
return (0,
|
|
2267
|
+
return (0, import_node_crypto3.generateKeyPairSync)("rsa", { modulusLength: RSA_MODULUS_BITS });
|
|
2116
2268
|
}
|
|
2117
2269
|
function keyPem(privateKey) {
|
|
2118
2270
|
return privateKey.export({ type: "pkcs8", format: "pem" });
|
|
@@ -2136,8 +2288,8 @@ function issueLeafCertificate(ca, names, notBefore, notAfter) {
|
|
|
2136
2288
|
if (commonName === void 0) {
|
|
2137
2289
|
throw new Error("a leaf certificate needs at least one name");
|
|
2138
2290
|
}
|
|
2139
|
-
const caCertificate = new
|
|
2140
|
-
const caPrivateKey = (0,
|
|
2291
|
+
const caCertificate = new import_node_crypto3.X509Certificate(ca.certPem);
|
|
2292
|
+
const caPrivateKey = (0, import_node_crypto3.createPrivateKey)(ca.keyPem);
|
|
2141
2293
|
const { publicKey, privateKey } = rsaKeyPair();
|
|
2142
2294
|
const generalNames = names.map((name) => import_node_net.default.isIP(name) === 0 ? tlv(TAG_GENERAL_NAME_DNS, Buffer.from(name, "ascii")) : tlv(TAG_GENERAL_NAME_IP, ipBytes(name)));
|
|
2143
2295
|
const der = assemble({
|
|
@@ -2232,7 +2384,7 @@ function capabilityFromProxyAuthorization(value) {
|
|
|
2232
2384
|
var AUTH_HEADER = "x-agent-shim-auth";
|
|
2233
2385
|
|
|
2234
2386
|
// src/frontdoor/state.ts
|
|
2235
|
-
var
|
|
2387
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
2236
2388
|
var import_zod3 = require("zod");
|
|
2237
2389
|
var FRONT_DOOR_PROTOCOL = 1;
|
|
2238
2390
|
var FrontDoorSessionSchema = import_zod3.z.strictObject({ pid: import_zod3.z.number().int().positive(), startedAt: import_zod3.z.number(), token: import_zod3.z.string().min(1) });
|
|
@@ -2266,10 +2418,10 @@ var FrontDoorStateSchema = import_zod3.z.strictObject({
|
|
|
2266
2418
|
/** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
|
|
2267
2419
|
lastError: import_zod3.z.string().optional()
|
|
2268
2420
|
});
|
|
2269
|
-
function readFrontDoorState(
|
|
2421
|
+
function readFrontDoorState(fs7, stateFile) {
|
|
2270
2422
|
let raw;
|
|
2271
2423
|
try {
|
|
2272
|
-
raw =
|
|
2424
|
+
raw = fs7.readFileUtf8(stateFile);
|
|
2273
2425
|
} catch {
|
|
2274
2426
|
return void 0;
|
|
2275
2427
|
}
|
|
@@ -2283,28 +2435,28 @@ function readFrontDoorState(fs3, stateFile) {
|
|
|
2283
2435
|
return void 0;
|
|
2284
2436
|
}
|
|
2285
2437
|
}
|
|
2286
|
-
function writeFrontDoorState(
|
|
2287
|
-
|
|
2288
|
-
|
|
2438
|
+
function writeFrontDoorState(fs7, stateFile, state) {
|
|
2439
|
+
fs7.mkdirp(import_node_path6.default.dirname(stateFile));
|
|
2440
|
+
fs7.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2289
2441
|
`);
|
|
2290
2442
|
}
|
|
2291
2443
|
function frontDoorOrigin(state) {
|
|
2292
2444
|
const port = state?.directPort ?? state?.lastDirectPort;
|
|
2293
2445
|
return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
|
|
2294
2446
|
}
|
|
2295
|
-
function writeFrontDoorSession(
|
|
2296
|
-
|
|
2297
|
-
|
|
2447
|
+
function writeFrontDoorSession(fs7, sessionsDir, session) {
|
|
2448
|
+
fs7.mkdirPrivate(sessionsDir);
|
|
2449
|
+
fs7.writeFilePrivate(import_node_path6.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
2298
2450
|
`);
|
|
2299
2451
|
}
|
|
2300
|
-
function listFrontDoorSessions(
|
|
2452
|
+
function listFrontDoorSessions(fs7, sessionsDir) {
|
|
2301
2453
|
const sessions = [];
|
|
2302
|
-
for (const name of
|
|
2454
|
+
for (const name of fs7.readdir(sessionsDir)) {
|
|
2303
2455
|
if (!name.endsWith(".json")) {
|
|
2304
2456
|
continue;
|
|
2305
2457
|
}
|
|
2306
2458
|
try {
|
|
2307
|
-
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(
|
|
2459
|
+
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs7.readFileUtf8(import_node_path6.default.join(sessionsDir, name)) ?? ""));
|
|
2308
2460
|
if (parsed.success) {
|
|
2309
2461
|
sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
|
|
2310
2462
|
}
|
|
@@ -2314,14 +2466,14 @@ function listFrontDoorSessions(fs3, sessionsDir) {
|
|
|
2314
2466
|
}
|
|
2315
2467
|
return sessions.sort((a, b) => a.pid - b.pid);
|
|
2316
2468
|
}
|
|
2317
|
-
function removeFrontDoorSession(
|
|
2318
|
-
|
|
2469
|
+
function removeFrontDoorSession(fs7, sessionsDir, pid) {
|
|
2470
|
+
fs7.removeRecursive(import_node_path6.default.join(sessionsDir, `${String(pid)}.json`));
|
|
2319
2471
|
}
|
|
2320
|
-
function pruneDeadFrontDoorSessions(
|
|
2472
|
+
function pruneDeadFrontDoorSessions(fs7, sessionsDir, isRunning) {
|
|
2321
2473
|
const removed = [];
|
|
2322
|
-
for (const session of listFrontDoorSessions(
|
|
2474
|
+
for (const session of listFrontDoorSessions(fs7, sessionsDir)) {
|
|
2323
2475
|
if (!isRunning(session.pid)) {
|
|
2324
|
-
removeFrontDoorSession(
|
|
2476
|
+
removeFrontDoorSession(fs7, sessionsDir, session.pid);
|
|
2325
2477
|
removed.push(session.pid);
|
|
2326
2478
|
}
|
|
2327
2479
|
}
|
|
@@ -2333,8 +2485,8 @@ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
|
|
|
2333
2485
|
var FRONTDOOR_POLL_MS = 1e3;
|
|
2334
2486
|
var MS_PER_MINUTE = 6e4;
|
|
2335
2487
|
async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
|
|
2336
|
-
const { fs:
|
|
2337
|
-
const previous = readFrontDoorState(
|
|
2488
|
+
const { fs: fs7, paths } = ports;
|
|
2489
|
+
const previous = readFrontDoorState(fs7, paths.frontdoorStateFile);
|
|
2338
2490
|
let lastPort = previous?.lastPort;
|
|
2339
2491
|
let lastConnectPort = previous?.lastConnectPort;
|
|
2340
2492
|
let lastDirectPort = previous?.lastDirectPort;
|
|
@@ -2344,12 +2496,12 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
2344
2496
|
...lastDirectPort === void 0 ? {} : { lastDirectPort }
|
|
2345
2497
|
});
|
|
2346
2498
|
const fail = (message) => {
|
|
2347
|
-
writeFrontDoorState(
|
|
2348
|
-
|
|
2499
|
+
writeFrontDoorState(fs7, paths.frontdoorStateFile, { lastError: message, ...sticky() });
|
|
2500
|
+
fs7.removeRecursive(paths.frontdoorLockFile);
|
|
2349
2501
|
ports.log(`agent-shim frontdoor supervisor: ${message}`);
|
|
2350
2502
|
return 1;
|
|
2351
2503
|
};
|
|
2352
|
-
writeFrontDoorState(
|
|
2504
|
+
writeFrontDoorState(fs7, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
|
|
2353
2505
|
const previousSticky = lastPort;
|
|
2354
2506
|
let http2;
|
|
2355
2507
|
try {
|
|
@@ -2386,8 +2538,8 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
2386
2538
|
ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom must be restarted to admit the new address)`);
|
|
2387
2539
|
}
|
|
2388
2540
|
lastDirectPort = direct.port;
|
|
2389
|
-
writeFrontDoorState(
|
|
2390
|
-
|
|
2541
|
+
writeFrontDoorState(fs7, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http2.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
|
|
2542
|
+
fs7.removeRecursive(paths.frontdoorLockFile);
|
|
2391
2543
|
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http2.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
|
|
2392
2544
|
let idleSince;
|
|
2393
2545
|
let ticks = 0;
|
|
@@ -2396,15 +2548,15 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
2396
2548
|
return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
|
|
2397
2549
|
}
|
|
2398
2550
|
ticks += 1;
|
|
2399
|
-
pruneDeadFrontDoorSessions(
|
|
2400
|
-
if (listFrontDoorSessions(
|
|
2551
|
+
pruneDeadFrontDoorSessions(fs7, paths.frontdoorSessionsDir, ports.isRunning);
|
|
2552
|
+
if (listFrontDoorSessions(fs7, paths.frontdoorSessionsDir).length === 0) {
|
|
2401
2553
|
idleSince ??= ports.now();
|
|
2402
2554
|
if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
|
|
2403
2555
|
ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
|
|
2404
2556
|
await direct.close();
|
|
2405
2557
|
await connect3.close();
|
|
2406
2558
|
await http2.close();
|
|
2407
|
-
writeFrontDoorState(
|
|
2559
|
+
writeFrontDoorState(fs7, paths.frontdoorStateFile, sticky());
|
|
2408
2560
|
return 0;
|
|
2409
2561
|
}
|
|
2410
2562
|
} else {
|
|
@@ -2459,8 +2611,8 @@ function parseConnectTarget(authority) {
|
|
|
2459
2611
|
function isInterceptedHost(host, interceptHosts) {
|
|
2460
2612
|
return interceptHosts.includes(host);
|
|
2461
2613
|
}
|
|
2462
|
-
function servedByPipeline(
|
|
2463
|
-
return
|
|
2614
|
+
function servedByPipeline(path13) {
|
|
2615
|
+
return path13?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
2464
2616
|
}
|
|
2465
2617
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
2466
2618
|
"connection",
|
|
@@ -2519,8 +2671,8 @@ function ensureCa(store, generate) {
|
|
|
2519
2671
|
}
|
|
2520
2672
|
function caParses(ca) {
|
|
2521
2673
|
try {
|
|
2522
|
-
new
|
|
2523
|
-
(0,
|
|
2674
|
+
new import_node_crypto4.X509Certificate(ca.certPem);
|
|
2675
|
+
(0, import_node_crypto4.createPrivateKey)(ca.keyPem);
|
|
2524
2676
|
return true;
|
|
2525
2677
|
} catch {
|
|
2526
2678
|
return false;
|
|
@@ -2758,15 +2910,15 @@ async function blindTunnel(socket, target, effects) {
|
|
|
2758
2910
|
socket.destroy();
|
|
2759
2911
|
});
|
|
2760
2912
|
}
|
|
2761
|
-
function
|
|
2913
|
+
function isEnoent2(error) {
|
|
2762
2914
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
2763
2915
|
}
|
|
2764
2916
|
function realConnectCertStore(paths) {
|
|
2765
2917
|
const read = (file) => {
|
|
2766
2918
|
try {
|
|
2767
|
-
return
|
|
2919
|
+
return fs2.readFileSync(file, "utf8");
|
|
2768
2920
|
} catch (error) {
|
|
2769
|
-
if (
|
|
2921
|
+
if (isEnoent2(error)) {
|
|
2770
2922
|
return void 0;
|
|
2771
2923
|
}
|
|
2772
2924
|
throw error;
|
|
@@ -2779,10 +2931,10 @@ function realConnectCertStore(paths) {
|
|
|
2779
2931
|
return certPem === void 0 || keyPem2 === void 0 ? void 0 : { certPem, keyPem: keyPem2 };
|
|
2780
2932
|
},
|
|
2781
2933
|
writeCa: (ca) => {
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2934
|
+
fs2.mkdirSync(paths.frontdoorCaDir, { recursive: true });
|
|
2935
|
+
fs2.writeFileSync(paths.frontdoorCaCertFile, ca.certPem, "utf8");
|
|
2936
|
+
fs2.writeFileSync(paths.frontdoorCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
|
|
2937
|
+
fs2.chmodSync(paths.frontdoorCaKeyFile, CA_KEY_FILE_MODE);
|
|
2786
2938
|
}
|
|
2787
2939
|
};
|
|
2788
2940
|
}
|
|
@@ -2951,11 +3103,11 @@ function realConnectEffects() {
|
|
|
2951
3103
|
}
|
|
2952
3104
|
|
|
2953
3105
|
// src/frontdoor/ensure.ts
|
|
2954
|
-
var
|
|
3106
|
+
var import_node_crypto6 = require("node:crypto");
|
|
2955
3107
|
|
|
2956
3108
|
// src/headroom/state.ts
|
|
2957
|
-
var
|
|
2958
|
-
var
|
|
3109
|
+
var import_node_crypto5 = require("node:crypto");
|
|
3110
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
2959
3111
|
var import_zod4 = require("zod");
|
|
2960
3112
|
var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2961
3113
|
var HeadroomStateSchema = import_zod4.z.strictObject({
|
|
@@ -2989,16 +3141,16 @@ function parseJson(raw, schema) {
|
|
|
2989
3141
|
const parsed = schema.safeParse(JSON.parse(raw));
|
|
2990
3142
|
return parsed.success ? parsed.data : void 0;
|
|
2991
3143
|
}
|
|
2992
|
-
function readHeadroomState(
|
|
3144
|
+
function readHeadroomState(fs7, stateFile) {
|
|
2993
3145
|
try {
|
|
2994
|
-
return parseJson(
|
|
3146
|
+
return parseJson(fs7.readFileUtf8(stateFile), HeadroomStateSchema);
|
|
2995
3147
|
} catch {
|
|
2996
3148
|
return void 0;
|
|
2997
3149
|
}
|
|
2998
3150
|
}
|
|
2999
|
-
function writeHeadroomState(
|
|
3000
|
-
|
|
3001
|
-
|
|
3151
|
+
function writeHeadroomState(fs7, stateFile, state) {
|
|
3152
|
+
fs7.mkdirp(import_node_path7.default.dirname(stateFile));
|
|
3153
|
+
fs7.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
3002
3154
|
`);
|
|
3003
3155
|
}
|
|
3004
3156
|
function headroomAllowlist(providers) {
|
|
@@ -3016,16 +3168,16 @@ function headroomUpstreams(providers, frontDoorOrigin2) {
|
|
|
3016
3168
|
return upstreams;
|
|
3017
3169
|
}
|
|
3018
3170
|
function hashAllowlist(allowlist) {
|
|
3019
|
-
return (0,
|
|
3171
|
+
return (0, import_node_crypto5.createHash)("sha256").update(allowlist.join("\n")).digest("hex");
|
|
3020
3172
|
}
|
|
3021
|
-
function readAllProviders(
|
|
3173
|
+
function readAllProviders(fs7, providersDir) {
|
|
3022
3174
|
const result = [];
|
|
3023
|
-
for (const name of
|
|
3175
|
+
for (const name of fs7.readdir(providersDir)) {
|
|
3024
3176
|
if (!name.endsWith(".json")) {
|
|
3025
3177
|
continue;
|
|
3026
3178
|
}
|
|
3027
3179
|
try {
|
|
3028
|
-
const parsed = parseJson(
|
|
3180
|
+
const parsed = parseJson(fs7.readFileUtf8(import_node_path7.default.join(providersDir, name)), ProviderSchema);
|
|
3029
3181
|
if (parsed !== void 0) {
|
|
3030
3182
|
result.push({ name: name.slice(0, -".json".length), provider: parsed });
|
|
3031
3183
|
}
|
|
@@ -3035,22 +3187,22 @@ function readAllProviders(fs3, providersDir) {
|
|
|
3035
3187
|
}
|
|
3036
3188
|
return result;
|
|
3037
3189
|
}
|
|
3038
|
-
function writeSession(
|
|
3039
|
-
|
|
3040
|
-
|
|
3190
|
+
function writeSession(fs7, sessionsDir, session) {
|
|
3191
|
+
fs7.mkdirp(sessionsDir);
|
|
3192
|
+
fs7.writeFileUtf8(import_node_path7.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
3041
3193
|
`);
|
|
3042
3194
|
}
|
|
3043
|
-
function removeSession(
|
|
3044
|
-
|
|
3195
|
+
function removeSession(fs7, sessionsDir, pid) {
|
|
3196
|
+
fs7.removeRecursive(import_node_path7.default.join(sessionsDir, `${String(pid)}.json`));
|
|
3045
3197
|
}
|
|
3046
|
-
function listSessions(
|
|
3198
|
+
function listSessions(fs7, sessionsDir) {
|
|
3047
3199
|
const sessions = [];
|
|
3048
|
-
for (const name of
|
|
3200
|
+
for (const name of fs7.readdir(sessionsDir)) {
|
|
3049
3201
|
if (!name.endsWith(".json")) {
|
|
3050
3202
|
continue;
|
|
3051
3203
|
}
|
|
3052
3204
|
try {
|
|
3053
|
-
const parsed = parseJson(
|
|
3205
|
+
const parsed = parseJson(fs7.readFileUtf8(import_node_path7.default.join(sessionsDir, name)), HeadroomSessionSchema);
|
|
3054
3206
|
if (parsed !== void 0) {
|
|
3055
3207
|
sessions.push(parsed);
|
|
3056
3208
|
}
|
|
@@ -3060,22 +3212,22 @@ function listSessions(fs3, sessionsDir) {
|
|
|
3060
3212
|
}
|
|
3061
3213
|
return sessions.sort((a, b) => a.pid - b.pid);
|
|
3062
3214
|
}
|
|
3063
|
-
function sessionsForSupervisor(
|
|
3064
|
-
return listSessions(
|
|
3215
|
+
function sessionsForSupervisor(fs7, sessionsDir, supervisorPid) {
|
|
3216
|
+
return listSessions(fs7, sessionsDir).filter((session) => session.supervisorPid === supervisorPid);
|
|
3065
3217
|
}
|
|
3066
|
-
function pruneDeadSessions(
|
|
3218
|
+
function pruneDeadSessions(fs7, sessionsDir, isRunning) {
|
|
3067
3219
|
const removed = [];
|
|
3068
|
-
for (const session of listSessions(
|
|
3220
|
+
for (const session of listSessions(fs7, sessionsDir)) {
|
|
3069
3221
|
if (!isRunning(session.pid)) {
|
|
3070
|
-
removeSession(
|
|
3222
|
+
removeSession(fs7, sessionsDir, session.pid);
|
|
3071
3223
|
removed.push(session.pid);
|
|
3072
3224
|
}
|
|
3073
3225
|
}
|
|
3074
3226
|
return removed;
|
|
3075
3227
|
}
|
|
3076
|
-
function readStartLock(
|
|
3228
|
+
function readStartLock(fs7, lockFile) {
|
|
3077
3229
|
try {
|
|
3078
|
-
return parseJson(
|
|
3230
|
+
return parseJson(fs7.readFileUtf8(lockFile), HeadroomLockSchema);
|
|
3079
3231
|
} catch {
|
|
3080
3232
|
return void 0;
|
|
3081
3233
|
}
|
|
@@ -3115,7 +3267,7 @@ function ensureFrontDoor(params) {
|
|
|
3115
3267
|
continue;
|
|
3116
3268
|
}
|
|
3117
3269
|
if (verdict.ok) {
|
|
3118
|
-
const token = (0,
|
|
3270
|
+
const token = (0, import_node_crypto6.randomUUID)();
|
|
3119
3271
|
writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token });
|
|
3120
3272
|
return { port: state.port, connectPort: state.connectPort, token };
|
|
3121
3273
|
}
|
|
@@ -3155,7 +3307,7 @@ function ensureFrontDoor(params) {
|
|
|
3155
3307
|
}
|
|
3156
3308
|
|
|
3157
3309
|
// src/usage/read.ts
|
|
3158
|
-
var
|
|
3310
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
3159
3311
|
|
|
3160
3312
|
// src/usage/schema.ts
|
|
3161
3313
|
var import_zod5 = require("zod");
|
|
@@ -3322,11 +3474,11 @@ function snapshotPath(snapshotsDir, identity) {
|
|
|
3322
3474
|
if (!isIdentityName(identity)) {
|
|
3323
3475
|
throw new Error(`"${identity}" is not a valid identity name.`);
|
|
3324
3476
|
}
|
|
3325
|
-
return
|
|
3477
|
+
return import_node_path8.default.join(snapshotsDir, `${identity}.json`);
|
|
3326
3478
|
}
|
|
3327
|
-
function readUsageSnapshot(
|
|
3479
|
+
function readUsageSnapshot(fs7, snapshotsDir, identity) {
|
|
3328
3480
|
const file = snapshotPath(snapshotsDir, identity);
|
|
3329
|
-
const raw =
|
|
3481
|
+
const raw = fs7.readFileUtf8(file);
|
|
3330
3482
|
if (raw === void 0) {
|
|
3331
3483
|
return void 0;
|
|
3332
3484
|
}
|
|
@@ -3342,8 +3494,8 @@ function readUsageSnapshot(fs3, snapshotsDir, identity) {
|
|
|
3342
3494
|
}
|
|
3343
3495
|
return snapshot.data;
|
|
3344
3496
|
}
|
|
3345
|
-
function listUsageSnapshots(
|
|
3346
|
-
return
|
|
3497
|
+
function listUsageSnapshots(fs7, snapshotsDir) {
|
|
3498
|
+
return fs7.readdir(snapshotsDir).flatMap((name) => {
|
|
3347
3499
|
if (!name.endsWith(".json")) {
|
|
3348
3500
|
return [];
|
|
3349
3501
|
}
|
|
@@ -3351,7 +3503,7 @@ function listUsageSnapshots(fs3, snapshotsDir) {
|
|
|
3351
3503
|
if (!isIdentityName(identity)) {
|
|
3352
3504
|
return [];
|
|
3353
3505
|
}
|
|
3354
|
-
const snapshot = readUsageSnapshot(
|
|
3506
|
+
const snapshot = readUsageSnapshot(fs7, snapshotsDir, identity);
|
|
3355
3507
|
return snapshot === void 0 ? [] : [snapshot];
|
|
3356
3508
|
}).sort((left, right) => left.identity.localeCompare(right.identity));
|
|
3357
3509
|
}
|
|
@@ -3411,7 +3563,7 @@ function ensureHeadroom(params) {
|
|
|
3411
3563
|
}
|
|
3412
3564
|
|
|
3413
3565
|
// src/headroom/settings.ts
|
|
3414
|
-
var
|
|
3566
|
+
var import_node_crypto7 = require("node:crypto");
|
|
3415
3567
|
function settingsOf(config) {
|
|
3416
3568
|
return {
|
|
3417
3569
|
...config.mode === void 0 ? {} : { mode: config.mode },
|
|
@@ -3436,7 +3588,7 @@ function settingsEnv(settings) {
|
|
|
3436
3588
|
return settings.rolloutChannel === void 0 ? {} : { HEADROOM_ROLLOUT_CHANNEL: settings.rolloutChannel };
|
|
3437
3589
|
}
|
|
3438
3590
|
function hashSettings(settings) {
|
|
3439
|
-
return (0,
|
|
3591
|
+
return (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify([...settingsArgs(settings), JSON.stringify(settingsEnv(settings))])).digest("hex");
|
|
3440
3592
|
}
|
|
3441
3593
|
|
|
3442
3594
|
// src/headroom/source.ts
|
|
@@ -3518,9 +3670,9 @@ function compareVersions(a, b) {
|
|
|
3518
3670
|
}
|
|
3519
3671
|
var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
|
|
3520
3672
|
async function runSupervisor(initialConfig, ports, options = {}) {
|
|
3521
|
-
const { fs:
|
|
3673
|
+
const { fs: fs7, paths } = ports;
|
|
3522
3674
|
let config = initialConfig;
|
|
3523
|
-
const previousState = readHeadroomState(
|
|
3675
|
+
const previousState = readHeadroomState(fs7, paths.headroomStateFile);
|
|
3524
3676
|
if (previousState?.supervisorPid !== void 0 && previousState.supervisorPid !== ports.ownPid && ports.isRunning(previousState.supervisorPid)) {
|
|
3525
3677
|
ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: supervisor ${String(previousState.supervisorPid)} already owns the daemon; exiting`);
|
|
3526
3678
|
return 0;
|
|
@@ -3529,19 +3681,19 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3529
3681
|
let lastPort = previousState?.lastPort;
|
|
3530
3682
|
const sticky = () => lastPort === void 0 ? {} : { lastPort };
|
|
3531
3683
|
const ownsState = () => {
|
|
3532
|
-
const owner = readHeadroomState(
|
|
3684
|
+
const owner = readHeadroomState(fs7, paths.headroomStateFile)?.supervisorPid;
|
|
3533
3685
|
return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
|
|
3534
3686
|
};
|
|
3535
3687
|
const writeOwnState = (state) => {
|
|
3536
3688
|
if (!ownsState()) {
|
|
3537
3689
|
return false;
|
|
3538
3690
|
}
|
|
3539
|
-
writeHeadroomState(
|
|
3691
|
+
writeHeadroomState(fs7, paths.headroomStateFile, state);
|
|
3540
3692
|
return true;
|
|
3541
3693
|
};
|
|
3542
3694
|
const fail = (message) => {
|
|
3543
3695
|
if (writeOwnState({ lastError: message, ...sticky() })) {
|
|
3544
|
-
|
|
3696
|
+
fs7.removeRecursive(paths.headroomLockFile);
|
|
3545
3697
|
}
|
|
3546
3698
|
ports.log(`agent-shim headroom supervisor: ${message}`);
|
|
3547
3699
|
return 1;
|
|
@@ -3590,7 +3742,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3590
3742
|
const settingsHash = hashSettings(config.settings);
|
|
3591
3743
|
const allowlist = allowlistOf(ports);
|
|
3592
3744
|
const allowlistHash = hashAllowlist(allowlist);
|
|
3593
|
-
pruneDeadSessions(
|
|
3745
|
+
pruneDeadSessions(fs7, paths.headroomSessionsDir, ports.isRunning);
|
|
3594
3746
|
const ownsNow = ownsState();
|
|
3595
3747
|
if (!ownsNow && !superseded) {
|
|
3596
3748
|
ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
|
|
@@ -3642,7 +3794,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3642
3794
|
...sticky()
|
|
3643
3795
|
});
|
|
3644
3796
|
if (recorded) {
|
|
3645
|
-
|
|
3797
|
+
fs7.removeRecursive(paths.headroomLockFile);
|
|
3646
3798
|
}
|
|
3647
3799
|
idleSince = void 0;
|
|
3648
3800
|
ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
|
|
@@ -3657,7 +3809,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3657
3809
|
}
|
|
3658
3810
|
} else {
|
|
3659
3811
|
if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config.source) {
|
|
3660
|
-
if (sessionsForSupervisor(
|
|
3812
|
+
if (sessionsForSupervisor(fs7, paths.headroomSessionsDir, ports.ownPid).length === 0) {
|
|
3661
3813
|
ports.log("agent-shim headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
|
|
3662
3814
|
ports.stopProcess(headroomPid);
|
|
3663
3815
|
headroomPid = void 0;
|
|
@@ -3666,7 +3818,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3666
3818
|
continue;
|
|
3667
3819
|
}
|
|
3668
3820
|
}
|
|
3669
|
-
const sessions = sessionsForSupervisor(
|
|
3821
|
+
const sessions = sessionsForSupervisor(fs7, paths.headroomSessionsDir, ports.ownPid);
|
|
3670
3822
|
if (sessions.length === 0) {
|
|
3671
3823
|
idleSince ??= ports.now();
|
|
3672
3824
|
const idleMs = ports.now() - idleSince;
|
|
@@ -3688,9 +3840,9 @@ async function runSupervisor(initialConfig, ports, options = {}) {
|
|
|
3688
3840
|
await ports.sleep(HEADROOM_POLL_MS);
|
|
3689
3841
|
}
|
|
3690
3842
|
}
|
|
3691
|
-
function currentHeadroomAllowlist(
|
|
3692
|
-
const providers = readAllProviders(
|
|
3693
|
-
return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(
|
|
3843
|
+
function currentHeadroomAllowlist(fs7, paths) {
|
|
3844
|
+
const providers = readAllProviders(fs7, paths.providersDir).map((entry) => entry.provider);
|
|
3845
|
+
return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs7, paths.frontdoorStateFile))));
|
|
3694
3846
|
}
|
|
3695
3847
|
function allowlistOf(ports) {
|
|
3696
3848
|
return currentHeadroomAllowlist(ports.fs, ports.paths);
|
|
@@ -3756,63 +3908,735 @@ function evaluateAmbientCredentialGuard(params) {
|
|
|
3756
3908
|
}
|
|
3757
3909
|
|
|
3758
3910
|
// src/paths.ts
|
|
3759
|
-
var
|
|
3911
|
+
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
3760
3912
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
3761
|
-
var
|
|
3913
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
3762
3914
|
function resolveAgentShimHome(env = process.env, home = import_node_os.default.homedir(), isDirectory = isExistingDirectory) {
|
|
3763
3915
|
const fromEnv = env.AGENT_SHIM_HOME;
|
|
3764
3916
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
3765
3917
|
return fromEnv;
|
|
3766
3918
|
}
|
|
3767
|
-
const current =
|
|
3768
|
-
const legacy =
|
|
3919
|
+
const current = import_node_path9.default.join(home, HOME_DIRNAME);
|
|
3920
|
+
const legacy = import_node_path9.default.join(home, LEGACY_HOME_DIRNAME);
|
|
3769
3921
|
return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
|
|
3770
3922
|
}
|
|
3771
3923
|
function isExistingDirectory(candidate) {
|
|
3772
|
-
return
|
|
3924
|
+
return import_node_fs2.default.statSync(candidate, { throwIfNoEntry: false })?.isDirectory() ?? false;
|
|
3773
3925
|
}
|
|
3774
3926
|
function resolveClaudeHome() {
|
|
3775
3927
|
const fromEnv = process.env.AGENT_SHIM_CLAUDE_HOME;
|
|
3776
3928
|
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
3777
3929
|
return fromEnv;
|
|
3778
3930
|
}
|
|
3779
|
-
return
|
|
3931
|
+
return import_node_path9.default.join(import_node_os.default.homedir(), ".claude");
|
|
3780
3932
|
}
|
|
3781
3933
|
function buildLayoutPaths(root) {
|
|
3782
3934
|
return {
|
|
3783
3935
|
root,
|
|
3784
|
-
identitiesDir:
|
|
3785
|
-
configProfilesDir:
|
|
3786
|
-
providersDir:
|
|
3787
|
-
directoryRulesFile:
|
|
3788
|
-
activeIdentityFile:
|
|
3789
|
-
globalConfigFile:
|
|
3790
|
-
categoriesLocalFile:
|
|
3791
|
-
claudeShimFile:
|
|
3792
|
-
headroomDir:
|
|
3793
|
-
headroomStateFile:
|
|
3794
|
-
headroomLockFile:
|
|
3795
|
-
headroomSessionsDir:
|
|
3796
|
-
logsDir:
|
|
3797
|
-
headroomLogPath:
|
|
3798
|
-
frontdoorDir:
|
|
3799
|
-
frontdoorCaDir:
|
|
3800
|
-
frontdoorCaCertFile:
|
|
3801
|
-
frontdoorCaKeyFile:
|
|
3802
|
-
frontdoorCaBundlesDir:
|
|
3803
|
-
frontdoorStateFile:
|
|
3804
|
-
frontdoorLockFile:
|
|
3805
|
-
frontdoorSessionsDir:
|
|
3806
|
-
frontdoorLogPath:
|
|
3807
|
-
usageDir:
|
|
3808
|
-
usageLogDir:
|
|
3809
|
-
usageSnapshotsDir:
|
|
3810
|
-
usagePicksFile:
|
|
3936
|
+
identitiesDir: import_node_path9.default.join(root, "identities"),
|
|
3937
|
+
configProfilesDir: import_node_path9.default.join(root, "config-profiles"),
|
|
3938
|
+
providersDir: import_node_path9.default.join(root, "providers"),
|
|
3939
|
+
directoryRulesFile: import_node_path9.default.join(root, "directory-rules.json"),
|
|
3940
|
+
activeIdentityFile: import_node_path9.default.join(root, "active-identity"),
|
|
3941
|
+
globalConfigFile: import_node_path9.default.join(root, "config.json"),
|
|
3942
|
+
categoriesLocalFile: import_node_path9.default.join(root, "categories.local.json"),
|
|
3943
|
+
claudeShimFile: import_node_path9.default.join(root, "claude-shim.json"),
|
|
3944
|
+
headroomDir: import_node_path9.default.join(root, "headroom"),
|
|
3945
|
+
headroomStateFile: import_node_path9.default.join(root, "headroom", "state.json"),
|
|
3946
|
+
headroomLockFile: import_node_path9.default.join(root, "headroom", "start.lock"),
|
|
3947
|
+
headroomSessionsDir: import_node_path9.default.join(root, "headroom", "sessions"),
|
|
3948
|
+
logsDir: import_node_path9.default.join(root, "logs"),
|
|
3949
|
+
headroomLogPath: import_node_path9.default.join(root, "logs", "headroom.log"),
|
|
3950
|
+
frontdoorDir: import_node_path9.default.join(root, "frontdoor"),
|
|
3951
|
+
frontdoorCaDir: import_node_path9.default.join(root, "frontdoor", "ca"),
|
|
3952
|
+
frontdoorCaCertFile: import_node_path9.default.join(root, "frontdoor", "ca", "ca.pem"),
|
|
3953
|
+
frontdoorCaKeyFile: import_node_path9.default.join(root, "frontdoor", "ca", "ca.key"),
|
|
3954
|
+
frontdoorCaBundlesDir: import_node_path9.default.join(root, "frontdoor", "ca", "bundles"),
|
|
3955
|
+
frontdoorStateFile: import_node_path9.default.join(root, "frontdoor", "state.json"),
|
|
3956
|
+
frontdoorLockFile: import_node_path9.default.join(root, "frontdoor", "start.lock"),
|
|
3957
|
+
frontdoorSessionsDir: import_node_path9.default.join(root, "frontdoor", "sessions"),
|
|
3958
|
+
frontdoorLogPath: import_node_path9.default.join(root, "logs", "frontdoor.log"),
|
|
3959
|
+
usageDir: import_node_path9.default.join(root, "usage"),
|
|
3960
|
+
usageLogDir: import_node_path9.default.join(root, "usage", "log"),
|
|
3961
|
+
usageSnapshotsDir: import_node_path9.default.join(root, "usage", "snapshots"),
|
|
3962
|
+
usagePicksFile: import_node_path9.default.join(root, "usage", "picks.json")
|
|
3811
3963
|
};
|
|
3812
3964
|
}
|
|
3813
3965
|
function resolveLayoutPaths() {
|
|
3814
3966
|
return buildLayoutPaths(resolveAgentShimHome());
|
|
3815
3967
|
}
|
|
3968
|
+
|
|
3969
|
+
// src/identityStore.ts
|
|
3970
|
+
var import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
3971
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
3972
|
+
|
|
3973
|
+
// src/launcher/identity.ts
|
|
3974
|
+
function poolNameOf(selector) {
|
|
3975
|
+
return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
|
|
3976
|
+
}
|
|
3977
|
+
|
|
3978
|
+
// src/configProfilesStore.ts
|
|
3979
|
+
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
3980
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
3981
|
+
var ProfileNotFoundError = class extends CliError {
|
|
3982
|
+
constructor(profileName) {
|
|
3983
|
+
super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
|
|
3984
|
+
this.profileName = profileName;
|
|
3985
|
+
this.name = "ProfileNotFoundError";
|
|
3986
|
+
}
|
|
3987
|
+
profileName;
|
|
3988
|
+
};
|
|
3989
|
+
var ProfileAlreadyExistsError = class extends CliError {
|
|
3990
|
+
constructor(profileName) {
|
|
3991
|
+
super(`A configuration profile named "${profileName}" already exists.`);
|
|
3992
|
+
this.profileName = profileName;
|
|
3993
|
+
this.name = "ProfileAlreadyExistsError";
|
|
3994
|
+
}
|
|
3995
|
+
profileName;
|
|
3996
|
+
};
|
|
3997
|
+
var InvalidCategoryNameError = class extends CliError {
|
|
3998
|
+
constructor(categoryName) {
|
|
3999
|
+
super(`"${categoryName}" is not a category a configuration profile may toggle (runtime, history, knowledge, settings).`);
|
|
4000
|
+
this.categoryName = categoryName;
|
|
4001
|
+
this.name = "InvalidCategoryNameError";
|
|
4002
|
+
}
|
|
4003
|
+
categoryName;
|
|
4004
|
+
};
|
|
4005
|
+
function profileJsonPath(paths, name) {
|
|
4006
|
+
return import_node_path10.default.join(paths.configProfilesDir, `${name}.json`);
|
|
4007
|
+
}
|
|
4008
|
+
function profileExists(paths, name) {
|
|
4009
|
+
return import_node_fs3.default.existsSync(profileJsonPath(paths, name));
|
|
4010
|
+
}
|
|
4011
|
+
function requireProfileExists(paths, name) {
|
|
4012
|
+
if (!profileExists(paths, name)) {
|
|
4013
|
+
throw new ProfileNotFoundError(name);
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
function readProfile(paths, name) {
|
|
4017
|
+
return readJson(profileJsonPath(paths, name), ConfigProfileSchema);
|
|
4018
|
+
}
|
|
4019
|
+
function createProfile(paths, name, extendsList, description) {
|
|
4020
|
+
if (profileExists(paths, name)) {
|
|
4021
|
+
throw new ProfileAlreadyExistsError(name);
|
|
4022
|
+
}
|
|
4023
|
+
const filePath = profileJsonPath(paths, name);
|
|
4024
|
+
const parsed = ConfigProfileSchema.safeParse({
|
|
4025
|
+
...description === void 0 ? {} : { description },
|
|
4026
|
+
...extendsList !== void 0 && extendsList.length > 0 ? { extends: [...extendsList] } : {}
|
|
4027
|
+
});
|
|
4028
|
+
if (!parsed.success) {
|
|
4029
|
+
throw new ConfigValidationError(filePath, parsed.error.issues);
|
|
4030
|
+
}
|
|
4031
|
+
writeJsonAtomic(filePath, parsed.data);
|
|
4032
|
+
return parsed.data;
|
|
4033
|
+
}
|
|
4034
|
+
function listProfiles(paths) {
|
|
4035
|
+
if (!import_node_fs3.default.existsSync(paths.configProfilesDir)) {
|
|
4036
|
+
return [];
|
|
4037
|
+
}
|
|
4038
|
+
const names = import_node_fs3.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort();
|
|
4039
|
+
const result = [];
|
|
4040
|
+
for (const name of names) {
|
|
4041
|
+
const profile = readProfile(paths, name);
|
|
4042
|
+
if (profile !== void 0) {
|
|
4043
|
+
result.push({ name, profile });
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
return result;
|
|
4047
|
+
}
|
|
4048
|
+
function globalConfigPath(paths) {
|
|
4049
|
+
return paths.globalConfigFile;
|
|
4050
|
+
}
|
|
4051
|
+
function readGlobalConfig(paths) {
|
|
4052
|
+
return readJson(globalConfigPath(paths), GlobalConfigSchema);
|
|
4053
|
+
}
|
|
4054
|
+
function setGlobalDefaultProfile(paths, name) {
|
|
4055
|
+
return applyPatch(
|
|
4056
|
+
globalConfigPath(paths),
|
|
4057
|
+
GlobalConfigSchema,
|
|
4058
|
+
{ defaultConfigProfile: name },
|
|
4059
|
+
{ defaults: {} }
|
|
4060
|
+
);
|
|
4061
|
+
}
|
|
4062
|
+
function validateCategoryNames(patch) {
|
|
4063
|
+
for (const key of Object.keys(patch)) {
|
|
4064
|
+
if (!isOverridableCategory(key)) {
|
|
4065
|
+
throw new InvalidCategoryNameError(key);
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
function setProfileCategories(paths, name, patch) {
|
|
4070
|
+
requireProfileExists(paths, name);
|
|
4071
|
+
const expandedPatch = expandAllCategoryKey(patch);
|
|
4072
|
+
validateCategoryNames(expandedPatch);
|
|
4073
|
+
const existing = readProfile(paths, name) ?? {};
|
|
4074
|
+
const mergedCategories = { ...existing.categories, ...expandedPatch };
|
|
4075
|
+
return applyPatch(profileJsonPath(paths, name), ConfigProfileSchema, { categories: mergedCategories });
|
|
4076
|
+
}
|
|
4077
|
+
function setProfileEntries(paths, name, patch) {
|
|
4078
|
+
requireProfileExists(paths, name);
|
|
4079
|
+
const existing = readProfile(paths, name) ?? {};
|
|
4080
|
+
const mergedEntries = { ...existing.entries, ...patch };
|
|
4081
|
+
return applyPatch(profileJsonPath(paths, name), ConfigProfileSchema, { entries: mergedEntries });
|
|
4082
|
+
}
|
|
4083
|
+
function setProfileLaunchFlags(paths, name, patch) {
|
|
4084
|
+
requireProfileExists(paths, name);
|
|
4085
|
+
const existing = readProfile(paths, name) ?? {};
|
|
4086
|
+
const mergedLaunch = { ...existing.launch, ...patch };
|
|
4087
|
+
return applyPatch(profileJsonPath(paths, name), ConfigProfileSchema, {
|
|
4088
|
+
// Read as `unknown` so the check sees the `undefined` a cleared key holds, which LaunchFlags' optional properties hide from the value type.
|
|
4089
|
+
launch: Object.values(mergedLaunch).every((value) => value === void 0) ? void 0 : mergedLaunch
|
|
4090
|
+
});
|
|
4091
|
+
}
|
|
4092
|
+
function setProfileMetadata(paths, name, patch) {
|
|
4093
|
+
requireProfileExists(paths, name);
|
|
4094
|
+
return applyPatch(profileJsonPath(paths, name), ConfigProfileSchema, {
|
|
4095
|
+
...patch.extends === void 0 ? {} : { extends: patch.extends.length === 0 ? void 0 : [...patch.extends] },
|
|
4096
|
+
...patch.description === void 0 ? {} : { description: patch.description === false ? void 0 : patch.description }
|
|
4097
|
+
});
|
|
4098
|
+
}
|
|
4099
|
+
function removeProfile(paths, name) {
|
|
4100
|
+
requireProfileExists(paths, name);
|
|
4101
|
+
import_node_fs3.default.rmSync(profileJsonPath(paths, name));
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
// src/poolStore.ts
|
|
4105
|
+
var PoolNotFoundError = class extends CliError {
|
|
4106
|
+
constructor(poolName) {
|
|
4107
|
+
super(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
|
|
4108
|
+
this.poolName = poolName;
|
|
4109
|
+
this.name = "PoolNotFoundError";
|
|
4110
|
+
}
|
|
4111
|
+
poolName;
|
|
4112
|
+
};
|
|
4113
|
+
var PoolAlreadyExistsError = class extends CliError {
|
|
4114
|
+
constructor(poolName) {
|
|
4115
|
+
super(`A pool named "${poolName}" already exists. Use \`agent-shim pool set ${poolName}\` to change its members.`);
|
|
4116
|
+
this.poolName = poolName;
|
|
4117
|
+
this.name = "PoolAlreadyExistsError";
|
|
4118
|
+
}
|
|
4119
|
+
poolName;
|
|
4120
|
+
};
|
|
4121
|
+
var InvalidPoolNameError = class extends CliError {
|
|
4122
|
+
constructor(attemptedName) {
|
|
4123
|
+
super(`"${attemptedName}" is not a valid pool name: it must start with a letter or number and may then contain letters, numbers, dots, hyphens and underscores.`);
|
|
4124
|
+
this.attemptedName = attemptedName;
|
|
4125
|
+
this.name = "InvalidPoolNameError";
|
|
4126
|
+
}
|
|
4127
|
+
attemptedName;
|
|
4128
|
+
};
|
|
4129
|
+
function readPools(paths) {
|
|
4130
|
+
return readGlobalConfig(paths)?.pools ?? {};
|
|
4131
|
+
}
|
|
4132
|
+
function requirePool(paths, name) {
|
|
4133
|
+
const pool = readPools(paths)[name];
|
|
4134
|
+
if (pool === void 0) {
|
|
4135
|
+
throw new PoolNotFoundError(name);
|
|
4136
|
+
}
|
|
4137
|
+
return pool;
|
|
4138
|
+
}
|
|
4139
|
+
function writePools(paths, pools) {
|
|
4140
|
+
applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
|
|
4141
|
+
}
|
|
4142
|
+
function addPool(paths, name, identities) {
|
|
4143
|
+
if (!PoolNameSchema.safeParse(name).success) {
|
|
4144
|
+
throw new InvalidPoolNameError(name);
|
|
4145
|
+
}
|
|
4146
|
+
const pools = readPools(paths);
|
|
4147
|
+
if (pools[name] !== void 0) {
|
|
4148
|
+
throw new PoolAlreadyExistsError(name);
|
|
4149
|
+
}
|
|
4150
|
+
const pool = { identities: [...identities] };
|
|
4151
|
+
writePools(paths, { ...pools, [name]: pool });
|
|
4152
|
+
return pool;
|
|
4153
|
+
}
|
|
4154
|
+
function setPool(paths, name, identities) {
|
|
4155
|
+
requirePool(paths, name);
|
|
4156
|
+
const pool = { identities: [...identities] };
|
|
4157
|
+
writePools(paths, { ...readPools(paths), [name]: pool });
|
|
4158
|
+
return pool;
|
|
4159
|
+
}
|
|
4160
|
+
function removePool(paths, name) {
|
|
4161
|
+
requirePool(paths, name);
|
|
4162
|
+
const remaining = Object.fromEntries(Object.entries(readPools(paths)).filter(([existing]) => existing !== name));
|
|
4163
|
+
writePools(paths, remaining);
|
|
4164
|
+
}
|
|
4165
|
+
|
|
4166
|
+
// src/identityStore.ts
|
|
4167
|
+
var IdentityNotFoundError = class extends CliError {
|
|
4168
|
+
constructor(name) {
|
|
4169
|
+
super(`No identity named "${name}". Run \`agent-shim identity add ${name}\` first.`);
|
|
4170
|
+
this.name = name;
|
|
4171
|
+
this.name = "IdentityNotFoundError";
|
|
4172
|
+
}
|
|
4173
|
+
name;
|
|
4174
|
+
};
|
|
4175
|
+
var IdentityAlreadyExistsError = class extends CliError {
|
|
4176
|
+
constructor(identityName) {
|
|
4177
|
+
super(`An identity named "${identityName}" already exists.`);
|
|
4178
|
+
this.identityName = identityName;
|
|
4179
|
+
this.name = "IdentityAlreadyExistsError";
|
|
4180
|
+
}
|
|
4181
|
+
identityName;
|
|
4182
|
+
};
|
|
4183
|
+
var InvalidIdentityNameError = class extends CliError {
|
|
4184
|
+
constructor(attemptedName) {
|
|
4185
|
+
super(
|
|
4186
|
+
`"${attemptedName}" is not a valid identity name \u2014 identity names must start with a letter or number and may then contain letters, numbers, dots, hyphens, underscores, and at signs.`
|
|
4187
|
+
);
|
|
4188
|
+
this.attemptedName = attemptedName;
|
|
4189
|
+
this.name = "InvalidIdentityNameError";
|
|
4190
|
+
}
|
|
4191
|
+
attemptedName;
|
|
4192
|
+
};
|
|
4193
|
+
function identityJsonPath(paths, name) {
|
|
4194
|
+
return import_node_path11.default.join(paths.identitiesDir, name, "identity.json");
|
|
4195
|
+
}
|
|
4196
|
+
function identityExists(paths, name) {
|
|
4197
|
+
return import_node_fs4.default.existsSync(identityJsonPath(paths, name));
|
|
4198
|
+
}
|
|
4199
|
+
function readIdentity(paths, name) {
|
|
4200
|
+
return readJson(identityJsonPath(paths, name), IdentitySchema);
|
|
4201
|
+
}
|
|
4202
|
+
function addIdentity(paths, name) {
|
|
4203
|
+
if (identityExists(paths, name)) {
|
|
4204
|
+
throw new IdentityAlreadyExistsError(name);
|
|
4205
|
+
}
|
|
4206
|
+
const parsed = IdentitySchema.safeParse({ name, allowAmbientCredential: false });
|
|
4207
|
+
if (!parsed.success) {
|
|
4208
|
+
throw new InvalidIdentityNameError(name);
|
|
4209
|
+
}
|
|
4210
|
+
writeJsonAtomic(identityJsonPath(paths, name), parsed.data);
|
|
4211
|
+
return parsed.data;
|
|
4212
|
+
}
|
|
4213
|
+
function useIdentity(paths, name) {
|
|
4214
|
+
const pool = poolNameOf(name);
|
|
4215
|
+
if (pool !== void 0) {
|
|
4216
|
+
requirePool(paths, pool);
|
|
4217
|
+
} else if (!identityExists(paths, name)) {
|
|
4218
|
+
throw new IdentityNotFoundError(name);
|
|
4219
|
+
}
|
|
4220
|
+
writeTextAtomic(paths.activeIdentityFile, `${name}
|
|
4221
|
+
`);
|
|
4222
|
+
}
|
|
4223
|
+
function readActiveIdentity(paths) {
|
|
4224
|
+
if (!import_node_fs4.default.existsSync(paths.activeIdentityFile)) {
|
|
4225
|
+
return void 0;
|
|
4226
|
+
}
|
|
4227
|
+
const raw = import_node_fs4.default.readFileSync(paths.activeIdentityFile, "utf8").trim();
|
|
4228
|
+
return raw === "" ? void 0 : raw;
|
|
4229
|
+
}
|
|
4230
|
+
function isIdentityDirectoryName(name) {
|
|
4231
|
+
return !name.startsWith(".");
|
|
4232
|
+
}
|
|
4233
|
+
function readIdentityForListing(paths, name) {
|
|
4234
|
+
try {
|
|
4235
|
+
return readIdentity(paths, name);
|
|
4236
|
+
} catch (error) {
|
|
4237
|
+
if (error instanceof ConfigValidationError || error instanceof SyntaxError) {
|
|
4238
|
+
return { problem: error.message.replace(/\s*\n\s*/g, " ") };
|
|
4239
|
+
}
|
|
4240
|
+
throw error;
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
function listIdentities(paths) {
|
|
4244
|
+
if (!import_node_fs4.default.existsSync(paths.identitiesDir)) {
|
|
4245
|
+
return [];
|
|
4246
|
+
}
|
|
4247
|
+
const active = readActiveIdentity(paths);
|
|
4248
|
+
const names = import_node_fs4.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort();
|
|
4249
|
+
const result = [];
|
|
4250
|
+
for (const name of names) {
|
|
4251
|
+
const read = readIdentityForListing(paths, name);
|
|
4252
|
+
if (read === void 0) {
|
|
4253
|
+
continue;
|
|
4254
|
+
}
|
|
4255
|
+
const isActive = name === active;
|
|
4256
|
+
result.push("problem" in read ? { name, isActive, problem: read.problem } : { name, identity: read, isActive });
|
|
4257
|
+
}
|
|
4258
|
+
return result;
|
|
4259
|
+
}
|
|
4260
|
+
function setDefaultConfigProfile(paths, identityName, profileName) {
|
|
4261
|
+
if (!identityExists(paths, identityName)) {
|
|
4262
|
+
throw new IdentityNotFoundError(identityName);
|
|
4263
|
+
}
|
|
4264
|
+
return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, {
|
|
4265
|
+
defaultConfigProfile: profileName
|
|
4266
|
+
});
|
|
4267
|
+
}
|
|
4268
|
+
function setAllowAmbientCredential(paths, identityName, allow) {
|
|
4269
|
+
if (!identityExists(paths, identityName)) {
|
|
4270
|
+
throw new IdentityNotFoundError(identityName);
|
|
4271
|
+
}
|
|
4272
|
+
return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, {
|
|
4273
|
+
allowAmbientCredential: allow
|
|
4274
|
+
});
|
|
4275
|
+
}
|
|
4276
|
+
function setIdentityCredential(paths, identityName, change) {
|
|
4277
|
+
const existing = readIdentity(paths, identityName);
|
|
4278
|
+
if (existing === void 0) {
|
|
4279
|
+
throw new IdentityNotFoundError(identityName);
|
|
4280
|
+
}
|
|
4281
|
+
if (change === false) {
|
|
4282
|
+
return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, { credential: void 0 });
|
|
4283
|
+
}
|
|
4284
|
+
const sources = change.sources ?? existing.credential?.sources;
|
|
4285
|
+
if (sources === void 0) {
|
|
4286
|
+
throw new UsageError(`Identity "${identityName}" has no credential yet: pass --credential to give it one before choosing its target.`);
|
|
4287
|
+
}
|
|
4288
|
+
const target = change.target ?? existing.credential?.target;
|
|
4289
|
+
const cache = change.cache === void 0 ? existing.credential?.cache : change.cache === false ? void 0 : change.cache;
|
|
4290
|
+
return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, {
|
|
4291
|
+
credential: { sources: [...sources], ...target === void 0 ? {} : { target }, ...cache === void 0 ? {} : { cache } }
|
|
4292
|
+
});
|
|
4293
|
+
}
|
|
4294
|
+
function belongsToIdentity(entry, name) {
|
|
4295
|
+
return entry === name || entry === import_node_path11.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
|
|
4296
|
+
}
|
|
4297
|
+
function removeIdentity(paths, name) {
|
|
4298
|
+
if (!identityExists(paths, name)) {
|
|
4299
|
+
throw new IdentityNotFoundError(name);
|
|
4300
|
+
}
|
|
4301
|
+
for (const entry of import_node_fs4.default.readdirSync(paths.identitiesDir)) {
|
|
4302
|
+
if (belongsToIdentity(entry, name)) {
|
|
4303
|
+
import_node_fs4.default.rmSync(import_node_path11.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
if (readActiveIdentity(paths) === name) {
|
|
4307
|
+
import_node_fs4.default.rmSync(paths.activeIdentityFile);
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
|
|
4311
|
+
// src/providersStore.ts
|
|
4312
|
+
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
4313
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
4314
|
+
|
|
4315
|
+
// src/credentialCache.ts
|
|
4316
|
+
var import_zod7 = require("zod");
|
|
4317
|
+
var CachedCredentialSchema = import_zod7.z.strictObject({
|
|
4318
|
+
token: import_zod7.z.string().min(1),
|
|
4319
|
+
fetchedAt: import_zod7.z.number().int().nonnegative(),
|
|
4320
|
+
source: CredentialSourceSchema
|
|
4321
|
+
});
|
|
4322
|
+
|
|
4323
|
+
// src/providersStore.ts
|
|
4324
|
+
var ProviderNotFoundError = class extends CliError {
|
|
4325
|
+
constructor(name) {
|
|
4326
|
+
super(`No provider named "${name}". Run \`agent-shim provider add ${name}\` first.`);
|
|
4327
|
+
this.name = name;
|
|
4328
|
+
this.name = "ProviderNotFoundError";
|
|
4329
|
+
}
|
|
4330
|
+
name;
|
|
4331
|
+
};
|
|
4332
|
+
var ProviderAlreadyExistsError = class extends CliError {
|
|
4333
|
+
constructor(providerName) {
|
|
4334
|
+
super(`A provider named "${providerName}" already exists.`);
|
|
4335
|
+
this.providerName = providerName;
|
|
4336
|
+
this.name = "ProviderAlreadyExistsError";
|
|
4337
|
+
}
|
|
4338
|
+
providerName;
|
|
4339
|
+
};
|
|
4340
|
+
var InvalidProviderNameError = class extends CliError {
|
|
4341
|
+
constructor(attemptedName) {
|
|
4342
|
+
super(
|
|
4343
|
+
`"${attemptedName}" is not a valid provider name. Provider names must start with a letter or number and may then contain letters, numbers, dots, hyphens, underscores, and at signs.`
|
|
4344
|
+
);
|
|
4345
|
+
this.attemptedName = attemptedName;
|
|
4346
|
+
this.name = "InvalidProviderNameError";
|
|
4347
|
+
}
|
|
4348
|
+
attemptedName;
|
|
4349
|
+
};
|
|
4350
|
+
var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
|
|
4351
|
+
function providerJsonPath(paths, name) {
|
|
4352
|
+
return import_node_path12.default.join(paths.providersDir, `${name}.json`);
|
|
4353
|
+
}
|
|
4354
|
+
function providerExists(paths, name) {
|
|
4355
|
+
return import_node_fs5.default.existsSync(providerJsonPath(paths, name));
|
|
4356
|
+
}
|
|
4357
|
+
var LEGACY_PROVIDER_FIELDS = ["tokenEnv", "tokenCommand", "authScheme"];
|
|
4358
|
+
var LEGACY_ENV_CREDENTIAL_KEYS = Object.values(CREDENTIAL_TARGET_VARS);
|
|
4359
|
+
var LEGACY_LITERAL_PLACEHOLDER = "<the value of env.ANTHROPIC_AUTH_TOKEN>";
|
|
4360
|
+
function isRecord(value) {
|
|
4361
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4362
|
+
}
|
|
4363
|
+
function legacyProviderConversion(raw) {
|
|
4364
|
+
if (!isRecord(raw) || "credential" in raw) {
|
|
4365
|
+
return void 0;
|
|
4366
|
+
}
|
|
4367
|
+
const env = isRecord(raw.env) ? raw.env : void 0;
|
|
4368
|
+
const legacyEnvKeys = env === void 0 ? [] : Object.keys(env).filter((key) => LEGACY_ENV_CREDENTIAL_KEYS.includes(key));
|
|
4369
|
+
const fields = [...LEGACY_PROVIDER_FIELDS.filter((field) => field in raw), ...legacyEnvKeys.map((key) => `env.${key}`)];
|
|
4370
|
+
if (fields.length === 0) {
|
|
4371
|
+
return void 0;
|
|
4372
|
+
}
|
|
4373
|
+
const sources = [];
|
|
4374
|
+
if (typeof raw.tokenEnv === "string") {
|
|
4375
|
+
sources.push({ env: raw.tokenEnv });
|
|
4376
|
+
}
|
|
4377
|
+
if (Array.isArray(raw.tokenCommand)) {
|
|
4378
|
+
sources.push({ command: raw.tokenCommand });
|
|
4379
|
+
}
|
|
4380
|
+
if (typeof env?.ANTHROPIC_AUTH_TOKEN === "string" && env.ANTHROPIC_AUTH_TOKEN !== "") {
|
|
4381
|
+
sources.push({ literal: LEGACY_LITERAL_PLACEHOLDER });
|
|
4382
|
+
}
|
|
4383
|
+
const remainingEnv = env === void 0 ? void 0 : Object.fromEntries(Object.entries(env).filter(([key]) => !LEGACY_ENV_CREDENTIAL_KEYS.includes(key)));
|
|
4384
|
+
const replacedKeys = [...LEGACY_PROVIDER_FIELDS, "env"];
|
|
4385
|
+
const rest = Object.fromEntries(Object.entries(raw).filter(([key]) => !replacedKeys.includes(key)));
|
|
4386
|
+
return {
|
|
4387
|
+
fields,
|
|
4388
|
+
replacement: {
|
|
4389
|
+
...rest,
|
|
4390
|
+
credential: { sources, ...raw.authScheme === "apiKey" ? { target: "apiKey" } : {} },
|
|
4391
|
+
...remainingEnv === void 0 || Object.keys(remainingEnv).length === 0 ? {} : { env: remainingEnv }
|
|
4392
|
+
}
|
|
4393
|
+
};
|
|
4394
|
+
}
|
|
4395
|
+
var LegacyProviderFileError = class extends CliError {
|
|
4396
|
+
constructor(filePath, conversion) {
|
|
4397
|
+
super(
|
|
4398
|
+
`${filePath} uses ${conversion.fields.join(", ")}, which a credential block replaced. Rewrite it as:
|
|
4399
|
+
` + JSON.stringify(conversion.replacement, null, 2)
|
|
4400
|
+
);
|
|
4401
|
+
this.filePath = filePath;
|
|
4402
|
+
this.conversion = conversion;
|
|
4403
|
+
this.name = "LegacyProviderFileError";
|
|
4404
|
+
}
|
|
4405
|
+
filePath;
|
|
4406
|
+
conversion;
|
|
4407
|
+
};
|
|
4408
|
+
function parseProviderFile(filePath, raw) {
|
|
4409
|
+
const conversion = legacyProviderConversion(raw);
|
|
4410
|
+
if (conversion !== void 0) {
|
|
4411
|
+
throw new LegacyProviderFileError(filePath, conversion);
|
|
4412
|
+
}
|
|
4413
|
+
const parsed = ProviderSchema.safeParse(raw);
|
|
4414
|
+
if (!parsed.success) {
|
|
4415
|
+
throw new ConfigValidationError(filePath, parsed.error.issues);
|
|
4416
|
+
}
|
|
4417
|
+
return parsed.data;
|
|
4418
|
+
}
|
|
4419
|
+
function readProvider(paths, name) {
|
|
4420
|
+
const filePath = providerJsonPath(paths, name);
|
|
4421
|
+
if (!import_node_fs5.default.existsSync(filePath)) {
|
|
4422
|
+
return void 0;
|
|
4423
|
+
}
|
|
4424
|
+
const raw = JSON.parse(import_node_fs5.default.readFileSync(filePath, "utf8"));
|
|
4425
|
+
return parseProviderFile(filePath, raw);
|
|
4426
|
+
}
|
|
4427
|
+
function listProviders(paths) {
|
|
4428
|
+
const names = listProviderNames(
|
|
4429
|
+
(dir) => import_node_fs5.default.readdirSync(dir),
|
|
4430
|
+
paths.providersDir
|
|
4431
|
+
);
|
|
4432
|
+
const result = [];
|
|
4433
|
+
for (const name of names) {
|
|
4434
|
+
let provider;
|
|
4435
|
+
try {
|
|
4436
|
+
provider = readProvider(paths, name);
|
|
4437
|
+
} catch (error) {
|
|
4438
|
+
if (!(error instanceof ConfigValidationError || error instanceof LegacyProviderFileError)) {
|
|
4439
|
+
throw error;
|
|
4440
|
+
}
|
|
4441
|
+
console.error(`agent-shim: providers/${name}.json is invalid and was skipped: ${error.message}`);
|
|
4442
|
+
continue;
|
|
4443
|
+
}
|
|
4444
|
+
if (provider !== void 0) {
|
|
4445
|
+
result.push({ name, provider });
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4448
|
+
return result;
|
|
4449
|
+
}
|
|
4450
|
+
function listProviderNames(readdir, providersDir) {
|
|
4451
|
+
let entries;
|
|
4452
|
+
try {
|
|
4453
|
+
entries = readdir(providersDir);
|
|
4454
|
+
} catch {
|
|
4455
|
+
return [];
|
|
4456
|
+
}
|
|
4457
|
+
return entries.filter((entry) => entry.endsWith(".json")).map((entry) => entry.slice(0, -".json".length)).sort();
|
|
4458
|
+
}
|
|
4459
|
+
function describeProviderEndpoint(provider) {
|
|
4460
|
+
return isCodexProvider(provider) ? "codex translation daemon" : provider.baseUrl;
|
|
4461
|
+
}
|
|
4462
|
+
var ProviderKindMismatchError = class extends UsageError {
|
|
4463
|
+
constructor(message) {
|
|
4464
|
+
super(message);
|
|
4465
|
+
this.name = "ProviderKindMismatchError";
|
|
4466
|
+
}
|
|
4467
|
+
};
|
|
4468
|
+
function isEmptyCodexConfig(config) {
|
|
4469
|
+
return config === void 0 || config.defaultModel === void 0 && config.effort === void 0 && (config.models === void 0 || Object.keys(config.models).length === 0);
|
|
4470
|
+
}
|
|
4471
|
+
function addProvider(paths, name, input) {
|
|
4472
|
+
if (providerExists(paths, name)) {
|
|
4473
|
+
throw new ProviderAlreadyExistsError(name);
|
|
4474
|
+
}
|
|
4475
|
+
if (!PROVIDER_NAME_RE.test(name)) {
|
|
4476
|
+
throw new InvalidProviderNameError(name);
|
|
4477
|
+
}
|
|
4478
|
+
const kind = input.kind ?? "http";
|
|
4479
|
+
if (kind === "codex" && input.baseUrl !== void 0) {
|
|
4480
|
+
throw new ProviderKindMismatchError("A codex provider has no base URL: the launcher points its sessions at the front-door daemon. Drop --base-url.");
|
|
4481
|
+
}
|
|
4482
|
+
if (kind === "http" && input.baseUrl === void 0) {
|
|
4483
|
+
throw new ProviderKindMismatchError("An http provider needs --base-url.");
|
|
4484
|
+
}
|
|
4485
|
+
if (kind === "http" && !isEmptyCodexConfig(input.codex)) {
|
|
4486
|
+
throw new ProviderKindMismatchError("Codex settings apply only to a codex provider (--kind codex).");
|
|
4487
|
+
}
|
|
4488
|
+
const shared = {
|
|
4489
|
+
displayName: input.displayName,
|
|
4490
|
+
credential: { sources: input.sources, ...input.target === void 0 ? {} : { target: input.target } },
|
|
4491
|
+
...input.env === void 0 || Object.keys(input.env).length === 0 ? {} : { env: input.env }
|
|
4492
|
+
};
|
|
4493
|
+
const parsed = ProviderSchema.safeParse(
|
|
4494
|
+
kind === "codex" ? { kind, ...shared, ...isEmptyCodexConfig(input.codex) ? {} : { codex: input.codex } } : { ...shared, baseUrl: input.baseUrl }
|
|
4495
|
+
);
|
|
4496
|
+
if (!parsed.success) {
|
|
4497
|
+
throw new ConfigValidationError(providerJsonPath(paths, name), parsed.error.issues);
|
|
4498
|
+
}
|
|
4499
|
+
writeJsonAtomic(providerJsonPath(paths, name), parsed.data);
|
|
4500
|
+
return parsed.data;
|
|
4501
|
+
}
|
|
4502
|
+
function updateProvider(paths, name, input) {
|
|
4503
|
+
const existing = readProvider(paths, name);
|
|
4504
|
+
if (existing === void 0) {
|
|
4505
|
+
throw new ProviderNotFoundError(name);
|
|
4506
|
+
}
|
|
4507
|
+
const unset = new Set(input.unsetEnv);
|
|
4508
|
+
const env = Object.fromEntries(Object.entries({ ...existing.env, ...input.env }).filter(([key]) => !unset.has(key)));
|
|
4509
|
+
const target = input.target ?? existing.credential.target;
|
|
4510
|
+
const cache = input.cache === void 0 ? existing.credential.cache : input.cache === false ? void 0 : input.cache;
|
|
4511
|
+
if (isCodexProvider(existing) && input.baseUrl !== void 0) {
|
|
4512
|
+
throw new ProviderKindMismatchError(`Provider "${name}" is a codex provider, which has no base URL.`);
|
|
4513
|
+
}
|
|
4514
|
+
if (!isCodexProvider(existing) && !isEmptyCodexConfig(input.codex)) {
|
|
4515
|
+
throw new ProviderKindMismatchError(`Provider "${name}" is an http provider; codex settings apply only to a codex provider.`);
|
|
4516
|
+
}
|
|
4517
|
+
const shared = {
|
|
4518
|
+
...input.displayName === void 0 ? {} : { displayName: input.displayName },
|
|
4519
|
+
credential: {
|
|
4520
|
+
sources: input.sources ?? existing.credential.sources,
|
|
4521
|
+
...target === void 0 ? {} : { target },
|
|
4522
|
+
...cache === void 0 ? {} : { cache }
|
|
4523
|
+
},
|
|
4524
|
+
env: Object.keys(env).length === 0 ? void 0 : env
|
|
4525
|
+
};
|
|
4526
|
+
let candidate;
|
|
4527
|
+
if (isCodexProvider(existing)) {
|
|
4528
|
+
const codex = {
|
|
4529
|
+
...existing.codex,
|
|
4530
|
+
...input.codex,
|
|
4531
|
+
...existing.codex?.models === void 0 && input.codex?.models === void 0 ? {} : { models: { ...existing.codex?.models, ...input.codex?.models } }
|
|
4532
|
+
};
|
|
4533
|
+
candidate = { ...existing, ...shared, codex: isEmptyCodexConfig(codex) ? void 0 : codex };
|
|
4534
|
+
} else {
|
|
4535
|
+
candidate = { ...existing, ...shared, ...input.baseUrl === void 0 ? {} : { baseUrl: input.baseUrl } };
|
|
4536
|
+
}
|
|
4537
|
+
const parsed = ProviderSchema.safeParse(candidate);
|
|
4538
|
+
if (!parsed.success) {
|
|
4539
|
+
throw new ConfigValidationError(providerJsonPath(paths, name), parsed.error.issues);
|
|
4540
|
+
}
|
|
4541
|
+
writeJsonAtomic(providerJsonPath(paths, name), parsed.data);
|
|
4542
|
+
return parsed.data;
|
|
4543
|
+
}
|
|
4544
|
+
function removeProvider(paths, name) {
|
|
4545
|
+
if (!providerExists(paths, name)) {
|
|
4546
|
+
throw new ProviderNotFoundError(name);
|
|
4547
|
+
}
|
|
4548
|
+
import_node_fs5.default.rmSync(providerJsonPath(paths, name));
|
|
4549
|
+
}
|
|
4550
|
+
|
|
4551
|
+
// src/directoryRulesStore.ts
|
|
4552
|
+
var DirectoryRuleNotFoundError = class extends CliError {
|
|
4553
|
+
constructor(rulePath) {
|
|
4554
|
+
super(`No directory rule found for path "${rulePath}".`);
|
|
4555
|
+
this.rulePath = rulePath;
|
|
4556
|
+
this.name = "DirectoryRuleNotFoundError";
|
|
4557
|
+
}
|
|
4558
|
+
rulePath;
|
|
4559
|
+
};
|
|
4560
|
+
var DirectoryRuleMissingTargetError = class extends CliError {
|
|
4561
|
+
constructor() {
|
|
4562
|
+
super("A directory rule must set at least one of --config-profile or --identity.");
|
|
4563
|
+
this.name = "DirectoryRuleMissingTargetError";
|
|
4564
|
+
}
|
|
4565
|
+
};
|
|
4566
|
+
var DirectoryRuleAlreadyExistsError = class extends CliError {
|
|
4567
|
+
constructor(rulePath) {
|
|
4568
|
+
super(`A directory rule for path "${rulePath}" already exists. Use \`agent-shim rule set\` to change it.`);
|
|
4569
|
+
this.rulePath = rulePath;
|
|
4570
|
+
this.name = "DirectoryRuleAlreadyExistsError";
|
|
4571
|
+
}
|
|
4572
|
+
rulePath;
|
|
4573
|
+
};
|
|
4574
|
+
function readDirectoryRules(paths) {
|
|
4575
|
+
return readJson(paths.directoryRulesFile, DirectoryRulesSchema) ?? { rules: [] };
|
|
4576
|
+
}
|
|
4577
|
+
function writeDirectoryRules(paths, rules) {
|
|
4578
|
+
const parsed = DirectoryRulesSchema.safeParse(rules);
|
|
4579
|
+
if (!parsed.success) {
|
|
4580
|
+
throw new ConfigValidationError(paths.directoryRulesFile, parsed.error.issues);
|
|
4581
|
+
}
|
|
4582
|
+
writeJsonAtomic(paths.directoryRulesFile, parsed.data);
|
|
4583
|
+
}
|
|
4584
|
+
function listDirectoryRules(paths) {
|
|
4585
|
+
return readDirectoryRules(paths).rules;
|
|
4586
|
+
}
|
|
4587
|
+
function addDirectoryRule(paths, rulePath, options) {
|
|
4588
|
+
if (options.configProfile === void 0 && options.identity === void 0) {
|
|
4589
|
+
throw new DirectoryRuleMissingTargetError();
|
|
4590
|
+
}
|
|
4591
|
+
const current = readDirectoryRules(paths);
|
|
4592
|
+
if (current.rules.some((rule) => rule.path === rulePath)) {
|
|
4593
|
+
throw new DirectoryRuleAlreadyExistsError(rulePath);
|
|
4594
|
+
}
|
|
4595
|
+
const created = buildNewRule(rulePath, options);
|
|
4596
|
+
writeDirectoryRules(paths, { ...current, rules: [...current.rules, created] });
|
|
4597
|
+
return created;
|
|
4598
|
+
}
|
|
4599
|
+
function ruleHasEffect(rule) {
|
|
4600
|
+
return rule.configProfile !== void 0 || rule.identity !== void 0 || rule.categories !== void 0 || rule.entries !== void 0 || rule.launch !== void 0;
|
|
4601
|
+
}
|
|
4602
|
+
function updateDirectoryRule(paths, rulePath, options) {
|
|
4603
|
+
const current = readDirectoryRules(paths);
|
|
4604
|
+
const index = current.rules.findIndex((rule) => rule.path === rulePath);
|
|
4605
|
+
const existing = index === -1 ? void 0 : current.rules[index];
|
|
4606
|
+
if (existing === void 0) {
|
|
4607
|
+
throw new DirectoryRuleNotFoundError(rulePath);
|
|
4608
|
+
}
|
|
4609
|
+
const { configProfile, identity, ...rest } = existing;
|
|
4610
|
+
const nextConfigProfile = options.configProfile === void 0 ? configProfile : options.configProfile === false ? void 0 : options.configProfile;
|
|
4611
|
+
const nextIdentity = options.identity === void 0 ? identity : options.identity === false ? void 0 : options.identity;
|
|
4612
|
+
const updated = {
|
|
4613
|
+
...rest,
|
|
4614
|
+
...nextConfigProfile === void 0 ? {} : { configProfile: nextConfigProfile },
|
|
4615
|
+
...nextIdentity === void 0 ? {} : { identity: nextIdentity }
|
|
4616
|
+
};
|
|
4617
|
+
if (!ruleHasEffect(updated)) {
|
|
4618
|
+
throw new DirectoryRuleMissingTargetError();
|
|
4619
|
+
}
|
|
4620
|
+
const nextRules = [...current.rules];
|
|
4621
|
+
nextRules[index] = updated;
|
|
4622
|
+
writeDirectoryRules(paths, { ...current, rules: nextRules });
|
|
4623
|
+
return updated;
|
|
4624
|
+
}
|
|
4625
|
+
function buildNewRule(rulePath, options) {
|
|
4626
|
+
return {
|
|
4627
|
+
path: rulePath,
|
|
4628
|
+
...options.configProfile !== void 0 ? { configProfile: options.configProfile } : {},
|
|
4629
|
+
...options.identity !== void 0 ? { identity: options.identity } : {}
|
|
4630
|
+
};
|
|
4631
|
+
}
|
|
4632
|
+
function removeDirectoryRule(paths, rulePath) {
|
|
4633
|
+
const current = readDirectoryRules(paths);
|
|
4634
|
+
const nextRules = current.rules.filter((rule) => rule.path !== rulePath);
|
|
4635
|
+
if (nextRules.length === current.rules.length) {
|
|
4636
|
+
throw new DirectoryRuleNotFoundError(rulePath);
|
|
4637
|
+
}
|
|
4638
|
+
writeDirectoryRules(paths, { ...current, rules: nextRules });
|
|
4639
|
+
}
|
|
3816
4640
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3817
4641
|
0 && (module.exports = {
|
|
3818
4642
|
AMBIENT_CREDENTIAL_VARS,
|
|
@@ -3827,6 +4651,9 @@ function resolveLayoutPaths() {
|
|
|
3827
4651
|
CredentialCacheSchema,
|
|
3828
4652
|
CredentialSchema,
|
|
3829
4653
|
CredentialSourceSchema,
|
|
4654
|
+
DirectoryRuleAlreadyExistsError,
|
|
4655
|
+
DirectoryRuleMissingTargetError,
|
|
4656
|
+
DirectoryRuleNotFoundError,
|
|
3830
4657
|
DirectoryRuleSchema,
|
|
3831
4658
|
DirectoryRulesSchema,
|
|
3832
4659
|
EXIT_FAILURE,
|
|
@@ -3836,20 +4663,38 @@ function resolveLayoutPaths() {
|
|
|
3836
4663
|
FrontDoorStartError,
|
|
3837
4664
|
GlobalConfigSchema,
|
|
3838
4665
|
HeadroomStartError,
|
|
4666
|
+
IdentityAlreadyExistsError,
|
|
4667
|
+
IdentityNotFoundError,
|
|
3839
4668
|
IdentitySchema,
|
|
4669
|
+
InvalidCategoryNameError,
|
|
4670
|
+
InvalidIdentityNameError,
|
|
4671
|
+
InvalidProviderNameError,
|
|
4672
|
+
LegacyProviderFileError,
|
|
3840
4673
|
PoolNameSchema,
|
|
4674
|
+
PoolNotFoundError,
|
|
3841
4675
|
PoolSchema,
|
|
3842
4676
|
PortableConfigSchema,
|
|
4677
|
+
ProfileAlreadyExistsError,
|
|
4678
|
+
ProfileNotFoundError,
|
|
4679
|
+
ProviderAlreadyExistsError,
|
|
4680
|
+
ProviderKindMismatchError,
|
|
4681
|
+
ProviderNotFoundError,
|
|
3843
4682
|
ProviderSchema,
|
|
3844
4683
|
ROUTED_PATH_PREFIX,
|
|
3845
4684
|
UsageError,
|
|
3846
4685
|
UsageSnapshotError,
|
|
3847
4686
|
UsageSnapshotSchema,
|
|
3848
4687
|
WhenSchema,
|
|
4688
|
+
addDirectoryRule,
|
|
4689
|
+
addIdentity,
|
|
4690
|
+
addPool,
|
|
4691
|
+
addProvider,
|
|
3849
4692
|
buildEntryFacts,
|
|
3850
4693
|
buildLayoutPaths,
|
|
3851
4694
|
carryOver,
|
|
3852
4695
|
createLeafCache,
|
|
4696
|
+
createProfile,
|
|
4697
|
+
describeProviderEndpoint,
|
|
3853
4698
|
detectAmbientCredential,
|
|
3854
4699
|
ensureCa,
|
|
3855
4700
|
ensureFrontDoor,
|
|
@@ -3858,16 +4703,37 @@ function resolveLayoutPaths() {
|
|
|
3858
4703
|
formatAmbientCredentialGuardMessage,
|
|
3859
4704
|
forwardableHeaders,
|
|
3860
4705
|
generateCa,
|
|
4706
|
+
identityExists,
|
|
4707
|
+
isIdentityDirectoryName,
|
|
3861
4708
|
isInterceptedHost,
|
|
4709
|
+
listDirectoryRules,
|
|
4710
|
+
listIdentities,
|
|
4711
|
+
listProfiles,
|
|
4712
|
+
listProviders,
|
|
3862
4713
|
listUsageSnapshots,
|
|
3863
4714
|
mintLeaf,
|
|
3864
4715
|
parseConnectTarget,
|
|
4716
|
+
profileExists,
|
|
4717
|
+
providerExists,
|
|
4718
|
+
readActiveIdentity,
|
|
4719
|
+
readDirectoryRules,
|
|
3865
4720
|
readFarmManifest,
|
|
4721
|
+
readGlobalConfig,
|
|
4722
|
+
readIdentity,
|
|
4723
|
+
readPools,
|
|
4724
|
+
readProfile,
|
|
4725
|
+
readProvider,
|
|
3866
4726
|
readUsageSnapshot,
|
|
3867
4727
|
realConnectCertStore,
|
|
3868
4728
|
realConnectEffects,
|
|
3869
4729
|
recoverFarm,
|
|
3870
4730
|
recoveryDiagnostics,
|
|
4731
|
+
removeDirectoryRule,
|
|
4732
|
+
removeIdentity,
|
|
4733
|
+
removePool,
|
|
4734
|
+
removeProfile,
|
|
4735
|
+
removeProvider,
|
|
4736
|
+
requirePool,
|
|
3871
4737
|
resolveAgentShimHome,
|
|
3872
4738
|
resolveClaudeHome,
|
|
3873
4739
|
resolveDecisions,
|
|
@@ -3877,7 +4743,20 @@ function resolveLayoutPaths() {
|
|
|
3877
4743
|
runFrontDoorSupervisor,
|
|
3878
4744
|
runSupervisor,
|
|
3879
4745
|
servedByPipeline,
|
|
4746
|
+
setAllowAmbientCredential,
|
|
4747
|
+
setDefaultConfigProfile,
|
|
4748
|
+
setGlobalDefaultProfile,
|
|
4749
|
+
setIdentityCredential,
|
|
4750
|
+
setPool,
|
|
4751
|
+
setProfileCategories,
|
|
4752
|
+
setProfileEntries,
|
|
4753
|
+
setProfileLaunchFlags,
|
|
4754
|
+
setProfileMetadata,
|
|
3880
4755
|
snapshotPath,
|
|
3881
4756
|
startConnectServer,
|
|
3882
|
-
topLevelNames
|
|
4757
|
+
topLevelNames,
|
|
4758
|
+
updateDirectoryRule,
|
|
4759
|
+
updateProvider,
|
|
4760
|
+
useIdentity,
|
|
4761
|
+
writeDirectoryRules
|
|
3883
4762
|
});
|