agent-trellis 0.14.0 → 0.15.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/dist/adapters/claude-code.js +4 -3
- package/dist/adapters/codex.js +4 -3
- package/dist/adapters/kimi-code.js +4 -3
- package/dist/adapters/kiro.js +5 -4
- package/dist/adapters/pi.js +4 -3
- package/dist/adapters/piMcp.d.ts +6 -3
- package/dist/adapters/piMcp.js +10 -3
- package/dist/adapters/zcode.d.ts +12 -1
- package/dist/adapters/zcode.js +7 -6
- package/dist/cli.js +38 -5
- package/dist/commands/doctor.d.ts +9 -1
- package/dist/commands/doctor.js +43 -6
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +24 -0
- package/dist/commands/mcp.d.ts +44 -1
- package/dist/commands/mcp.js +145 -33
- package/dist/commands/migrate.d.ts +12 -0
- package/dist/commands/migrate.js +8 -4
- package/dist/commands/migrateWorkspace.d.ts +40 -0
- package/dist/commands/migrateWorkspace.js +197 -0
- package/dist/commands/rollback.js +65 -35
- package/dist/commands/skill.d.ts +14 -0
- package/dist/commands/skill.js +71 -0
- package/dist/commands/sync.d.ts +16 -1
- package/dist/commands/sync.js +48 -15
- package/dist/core/adapter.d.ts +14 -0
- package/dist/core/canonical.d.ts +20 -32
- package/dist/core/canonical.js +18 -86
- package/dist/core/mcpServerDef.d.ts +39 -0
- package/dist/core/mcpServerDef.js +93 -0
- package/dist/core/types.d.ts +43 -4
- package/dist/lib/mcpMigrateRead.d.ts +25 -0
- package/dist/lib/mcpMigrateRead.js +9 -2
- package/dist/lib/skillProvider.js +18 -5
- package/dist/lib/workspace.d.ts +39 -0
- package/dist/lib/workspace.js +158 -0
- package/dist/lib/workspaceConfig.d.ts +45 -0
- package/dist/lib/workspaceConfig.js +98 -0
- package/dist/lib/workspaceDoctor.d.ts +44 -0
- package/dist/lib/workspaceDoctor.js +94 -0
- package/dist/lib/workspaceFiles.d.ts +38 -0
- package/dist/lib/workspaceFiles.js +264 -0
- package/dist/lib/workspaceMcp.d.ts +57 -0
- package/dist/lib/workspaceMcp.js +277 -0
- package/dist/lib/workspaceMerge.d.ts +37 -0
- package/dist/lib/workspaceMerge.js +98 -0
- package/dist/lib/workspaceMigrate.d.ts +118 -0
- package/dist/lib/workspaceMigrate.js +423 -0
- package/dist/pi-bridge/bundle.js +262 -96
- package/docs/architecture.md +111 -49
- package/docs/getting-started.md +102 -14
- package/docs/mcp-oauth-matrix.md +12 -1
- package/docs/overview.zh-CN.md +17 -0
- package/docs/research.md +28 -6
- package/docs/roadmap.md +17 -5
- package/package.json +1 -1
- package/docs/implementation-plan.md +0 -341
package/dist/pi-bridge/bundle.js
CHANGED
|
@@ -7463,12 +7463,12 @@ var require_isexe = __commonJS({
|
|
|
7463
7463
|
if (typeof Promise !== "function") {
|
|
7464
7464
|
throw new TypeError("callback not provided");
|
|
7465
7465
|
}
|
|
7466
|
-
return new Promise(function(
|
|
7466
|
+
return new Promise(function(resolve2, reject) {
|
|
7467
7467
|
isexe(path, options || {}, function(er, is) {
|
|
7468
7468
|
if (er) {
|
|
7469
7469
|
reject(er);
|
|
7470
7470
|
} else {
|
|
7471
|
-
|
|
7471
|
+
resolve2(is);
|
|
7472
7472
|
}
|
|
7473
7473
|
});
|
|
7474
7474
|
});
|
|
@@ -7534,27 +7534,27 @@ var require_which = __commonJS({
|
|
|
7534
7534
|
opt = {};
|
|
7535
7535
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
7536
7536
|
const found = [];
|
|
7537
|
-
const step = (i) => new Promise((
|
|
7537
|
+
const step = (i) => new Promise((resolve2, reject) => {
|
|
7538
7538
|
if (i === pathEnv.length)
|
|
7539
|
-
return opt.all && found.length ?
|
|
7539
|
+
return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
|
|
7540
7540
|
const ppRaw = pathEnv[i];
|
|
7541
7541
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
7542
7542
|
const pCmd = path.join(pathPart, cmd);
|
|
7543
7543
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
7544
|
-
|
|
7544
|
+
resolve2(subStep(p, i, 0));
|
|
7545
7545
|
});
|
|
7546
|
-
const subStep = (p, i, ii) => new Promise((
|
|
7546
|
+
const subStep = (p, i, ii) => new Promise((resolve2, reject) => {
|
|
7547
7547
|
if (ii === pathExt.length)
|
|
7548
|
-
return
|
|
7548
|
+
return resolve2(step(i + 1));
|
|
7549
7549
|
const ext = pathExt[ii];
|
|
7550
7550
|
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
7551
7551
|
if (!er && is) {
|
|
7552
7552
|
if (opt.all)
|
|
7553
7553
|
found.push(p + ext);
|
|
7554
7554
|
else
|
|
7555
|
-
return
|
|
7555
|
+
return resolve2(p + ext);
|
|
7556
7556
|
}
|
|
7557
|
-
return
|
|
7557
|
+
return resolve2(subStep(p, i, ii + 1));
|
|
7558
7558
|
});
|
|
7559
7559
|
});
|
|
7560
7560
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -7871,9 +7871,9 @@ import { homedir as homedir2 } from "node:os";
|
|
|
7871
7871
|
|
|
7872
7872
|
// src/core/canonical.ts
|
|
7873
7873
|
var import_yaml = __toESM(require_dist(), 1);
|
|
7874
|
-
import { existsSync as
|
|
7874
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2, writeFileSync } from "node:fs";
|
|
7875
7875
|
import { homedir } from "node:os";
|
|
7876
|
-
import { basename, dirname, join } from "node:path";
|
|
7876
|
+
import { basename, dirname as dirname2, join as join2 } from "node:path";
|
|
7877
7877
|
|
|
7878
7878
|
// src/core/types.ts
|
|
7879
7879
|
function isOAuthAuth(auth2) {
|
|
@@ -7936,65 +7936,224 @@ function resolveSecretEnv(names, policy) {
|
|
|
7936
7936
|
return result;
|
|
7937
7937
|
}
|
|
7938
7938
|
|
|
7939
|
-
// src/core/
|
|
7940
|
-
function fromServerDefYaml(serverName, def) {
|
|
7939
|
+
// src/core/mcpServerDef.ts
|
|
7940
|
+
function fromServerDefYaml(serverName, def, source = "mcp/servers.yaml") {
|
|
7941
7941
|
const { static_env, env_aliases, auth: auth2, ...rest } = def;
|
|
7942
7942
|
const out = { ...rest };
|
|
7943
7943
|
if (static_env) out.staticEnv = static_env;
|
|
7944
7944
|
if (env_aliases) out.envAliases = env_aliases;
|
|
7945
|
-
if (auth2 !== void 0) out.auth = fromAuthYaml(serverName, auth2);
|
|
7945
|
+
if (auth2 !== void 0) out.auth = fromAuthYaml(serverName, auth2, source);
|
|
7946
7946
|
return out;
|
|
7947
7947
|
}
|
|
7948
|
-
function fromAuthYaml(serverName, auth2) {
|
|
7948
|
+
function fromAuthYaml(serverName, auth2, source) {
|
|
7949
7949
|
if (auth2 === "oauth") return "oauth";
|
|
7950
7950
|
if (typeof auth2 !== "object" || auth2 === null) {
|
|
7951
|
-
throw new Error(
|
|
7951
|
+
throw new Error(`${source}: "${serverName}" auth must be the scalar "oauth" or { kind: oauth, client_id?, client_secret_env?, client_name? }`);
|
|
7952
7952
|
}
|
|
7953
|
-
const { kind, owner, client_id, client_secret_env, ...extra } = auth2;
|
|
7953
|
+
const { kind, owner, client_id, client_secret_env, client_name, ...extra } = auth2;
|
|
7954
7954
|
const unknownKey = Object.keys(extra)[0];
|
|
7955
7955
|
if (unknownKey !== void 0) {
|
|
7956
|
-
throw new Error(
|
|
7956
|
+
throw new Error(`${source}: "${serverName}" auth has unrecognized key "${unknownKey}" \u2014 expected kind, owner, client_id, client_secret_env, client_name`);
|
|
7957
7957
|
}
|
|
7958
7958
|
if (kind !== "oauth") {
|
|
7959
|
-
throw new Error(
|
|
7959
|
+
throw new Error(`${source}: "${serverName}" auth.kind must be "oauth" \u2014 kind is the only recognized discriminator`);
|
|
7960
7960
|
}
|
|
7961
7961
|
if (client_id !== void 0 && typeof client_id !== "string") {
|
|
7962
|
-
throw new Error(
|
|
7962
|
+
throw new Error(`${source}: "${serverName}" auth.client_id must be a string`);
|
|
7963
7963
|
}
|
|
7964
7964
|
if (client_secret_env !== void 0 && (typeof client_secret_env !== "string" || !isValidSecretVarName(client_secret_env))) {
|
|
7965
|
-
throw new Error(
|
|
7965
|
+
throw new Error(`${source}: "${serverName}" auth.client_secret_env must be a variable NAME (e.g. FIGMA_CLIENT_SECRET), never a secret value`);
|
|
7966
|
+
}
|
|
7967
|
+
if (client_name !== void 0 && typeof client_name !== "string") {
|
|
7968
|
+
throw new Error(`${source}: "${serverName}" auth.client_name must be a string`);
|
|
7966
7969
|
}
|
|
7967
7970
|
const out = { kind: "oauth" };
|
|
7968
|
-
if (owner !== void 0 && owner !== "agent" && owner !== "trellis") throw new Error(
|
|
7971
|
+
if (owner !== void 0 && owner !== "agent" && owner !== "trellis") throw new Error(`${source}: "${serverName}" auth.owner must be agent or trellis`);
|
|
7969
7972
|
if (owner !== void 0) out.owner = owner;
|
|
7970
7973
|
if (typeof client_id === "string") out.clientId = client_id;
|
|
7971
7974
|
if (typeof client_secret_env === "string") out.clientSecretEnv = client_secret_env;
|
|
7975
|
+
if (typeof client_name === "string") out.clientName = client_name;
|
|
7972
7976
|
return out;
|
|
7973
7977
|
}
|
|
7978
|
+
|
|
7979
|
+
// src/lib/workspace.ts
|
|
7980
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "node:fs";
|
|
7981
|
+
import { dirname, join, resolve } from "node:path";
|
|
7982
|
+
var WORKSPACE_DIR_NAME = ".agents";
|
|
7983
|
+
var WORKSPACE_CONFIG_VERSION = 1;
|
|
7984
|
+
var CONFIG_SOURCE_LABEL = ".agents/config.json";
|
|
7985
|
+
function isTombstone(def) {
|
|
7986
|
+
return def.enabled === false && def.transport === void 0;
|
|
7987
|
+
}
|
|
7988
|
+
function loadWorkspaceLayer(workspaceDir, policy) {
|
|
7989
|
+
const layerRoot = join(workspaceDir, WORKSPACE_DIR_NAME);
|
|
7990
|
+
const diagnostics = [];
|
|
7991
|
+
const layer = { root: workspaceDir, servers: {}, tombstones: [], skills: [], diagnostics };
|
|
7992
|
+
const configPath = join(layerRoot, "config.json");
|
|
7993
|
+
if (existsSync2(configPath)) {
|
|
7994
|
+
let parsed;
|
|
7995
|
+
try {
|
|
7996
|
+
parsed = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
7997
|
+
} catch (err) {
|
|
7998
|
+
throw new Error(`${CONFIG_SOURCE_LABEL}: invalid JSON \u2014 ${err.message}`);
|
|
7999
|
+
}
|
|
8000
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
8001
|
+
throw new Error(`${CONFIG_SOURCE_LABEL}: top level must be an object { "version", "mcp" }`);
|
|
8002
|
+
}
|
|
8003
|
+
const { version: version2, mcp, ...extra } = parsed;
|
|
8004
|
+
const configVersion = version2 === void 0 ? WORKSPACE_CONFIG_VERSION : version2;
|
|
8005
|
+
if (typeof configVersion !== "number" || !Number.isInteger(configVersion) || configVersion < 1) {
|
|
8006
|
+
throw new Error(`${CONFIG_SOURCE_LABEL}: "version" must be a positive integer, got ${JSON.stringify(version2)}`);
|
|
8007
|
+
}
|
|
8008
|
+
if (configVersion > WORKSPACE_CONFIG_VERSION) {
|
|
8009
|
+
throw new Error(
|
|
8010
|
+
`${CONFIG_SOURCE_LABEL}: schema version ${configVersion} is newer than this Trellis understands (${WORKSPACE_CONFIG_VERSION}) \u2014 upgrade Trellis`
|
|
8011
|
+
);
|
|
8012
|
+
}
|
|
8013
|
+
for (const key of Object.keys(extra)) {
|
|
8014
|
+
diagnostics.push(`${CONFIG_SOURCE_LABEL}: unrecognized top-level key "${key}" \u2014 ignored`);
|
|
8015
|
+
}
|
|
8016
|
+
if (mcp !== void 0) {
|
|
8017
|
+
if (typeof mcp !== "object" || mcp === null || typeof mcp.servers !== "object" || mcp.servers === null || Array.isArray(mcp.servers)) {
|
|
8018
|
+
throw new Error(`${CONFIG_SOURCE_LABEL}: "mcp.servers" must be an object mapping server names to definitions`);
|
|
8019
|
+
}
|
|
8020
|
+
for (const [name, rawDef] of Object.entries(mcp.servers)) {
|
|
8021
|
+
if (typeof rawDef !== "object" || rawDef === null) {
|
|
8022
|
+
throw new Error(`${CONFIG_SOURCE_LABEL}: "${name}" must be a server definition object or { "enabled": false }`);
|
|
8023
|
+
}
|
|
8024
|
+
if (isTombstone(rawDef)) {
|
|
8025
|
+
layer.tombstones.push(name);
|
|
8026
|
+
continue;
|
|
8027
|
+
}
|
|
8028
|
+
if (rawDef.enabled === false) {
|
|
8029
|
+
layer.tombstones.push(name);
|
|
8030
|
+
continue;
|
|
8031
|
+
}
|
|
8032
|
+
layer.servers[name] = fromServerDefYaml(name, rawDef, CONFIG_SOURCE_LABEL);
|
|
8033
|
+
}
|
|
8034
|
+
}
|
|
8035
|
+
}
|
|
8036
|
+
const instructionsPath = join(layerRoot, "AGENTS.md");
|
|
8037
|
+
if (existsSync2(instructionsPath)) {
|
|
8038
|
+
layer.instructionsFile = instructionsPath;
|
|
8039
|
+
}
|
|
8040
|
+
const skillsRoot = join(layerRoot, "skills");
|
|
8041
|
+
let skillEntries = [];
|
|
8042
|
+
try {
|
|
8043
|
+
skillEntries = readdirSync(skillsRoot);
|
|
8044
|
+
} catch {
|
|
8045
|
+
}
|
|
8046
|
+
for (const name of skillEntries) {
|
|
8047
|
+
const dir = join(skillsRoot, name);
|
|
8048
|
+
try {
|
|
8049
|
+
if (statSync(dir).isDirectory()) layer.skills.push({ name, dir });
|
|
8050
|
+
} catch {
|
|
8051
|
+
}
|
|
8052
|
+
}
|
|
8053
|
+
assertWorkspaceSecretsClean(layer.servers, policy);
|
|
8054
|
+
return layer;
|
|
8055
|
+
}
|
|
8056
|
+
var VAR_REF_RE = /^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/;
|
|
8057
|
+
function assertWorkspaceSecretsClean(servers, policy) {
|
|
8058
|
+
const check2 = (server, field, value) => {
|
|
8059
|
+
if (value === void 0 || VAR_REF_RE.test(value)) return;
|
|
8060
|
+
for (const pattern of policy.rejectPatterns) {
|
|
8061
|
+
if (pattern.test(value)) {
|
|
8062
|
+
throw new Error(
|
|
8063
|
+
`${CONFIG_SOURCE_LABEL}: "${server}" ${field} matches a secrets.policy.yaml reject pattern \u2014 the project layer is committable and must carry only \${VAR} references; move the value to the global secret store (the offending value is intentionally not printed)`
|
|
8064
|
+
);
|
|
8065
|
+
}
|
|
8066
|
+
}
|
|
8067
|
+
};
|
|
8068
|
+
for (const [name, def] of Object.entries(servers)) {
|
|
8069
|
+
for (const entry of def.env ?? []) check2(name, "env", entry);
|
|
8070
|
+
for (const [key, value] of Object.entries(def.staticEnv ?? {})) check2(name, `static_env.${key}`, value);
|
|
8071
|
+
for (const [key, value] of Object.entries(def.headers ?? {})) check2(name, `headers.${key}`, value);
|
|
8072
|
+
const meta3 = oauthClientMetadata(def.auth);
|
|
8073
|
+
check2(name, "auth.client_id", meta3.clientId);
|
|
8074
|
+
check2(name, "auth.client_secret_env", meta3.clientSecretEnv);
|
|
8075
|
+
}
|
|
8076
|
+
}
|
|
8077
|
+
|
|
8078
|
+
// src/lib/workspaceMerge.ts
|
|
8079
|
+
function mergeWorkspaceLayer(base, layer) {
|
|
8080
|
+
const shadowed = [];
|
|
8081
|
+
const mcpGlobalServers = { ...base.mcp.servers };
|
|
8082
|
+
const servers = { ...base.mcp.servers };
|
|
8083
|
+
const mcpProvenance = Object.fromEntries(
|
|
8084
|
+
Object.keys(base.mcp.servers).map((name) => [name, "global"])
|
|
8085
|
+
);
|
|
8086
|
+
for (const name of layer.tombstones) {
|
|
8087
|
+
if (servers[name] !== void 0) {
|
|
8088
|
+
delete servers[name];
|
|
8089
|
+
delete mcpProvenance[name];
|
|
8090
|
+
shadowed.push(`mcp:${name}`);
|
|
8091
|
+
} else {
|
|
8092
|
+
layer.diagnostics.push(`.agents/config.json: tombstone "${name}" matches no global server \u2014 no-op`);
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
for (const [name, def] of Object.entries(layer.servers)) {
|
|
8096
|
+
if (servers[name] !== void 0) shadowed.push(`mcp:${name}`);
|
|
8097
|
+
servers[name] = def;
|
|
8098
|
+
mcpProvenance[name] = "workspace";
|
|
8099
|
+
}
|
|
8100
|
+
const skills = [...base.skills];
|
|
8101
|
+
const globalSkills = [...base.skills];
|
|
8102
|
+
const skillProvenance = Object.fromEntries(
|
|
8103
|
+
base.skills.map((s) => [s.name, "global"])
|
|
8104
|
+
);
|
|
8105
|
+
for (const wsSkill of layer.skills) {
|
|
8106
|
+
const idx = skills.findIndex((s) => s.name === wsSkill.name);
|
|
8107
|
+
if (idx >= 0) {
|
|
8108
|
+
shadowed.push(`skill:${wsSkill.name}`);
|
|
8109
|
+
skills[idx] = wsSkill;
|
|
8110
|
+
} else {
|
|
8111
|
+
skills.push(wsSkill);
|
|
8112
|
+
}
|
|
8113
|
+
skillProvenance[wsSkill.name] = "workspace";
|
|
8114
|
+
}
|
|
8115
|
+
return {
|
|
8116
|
+
...base,
|
|
8117
|
+
skills,
|
|
8118
|
+
mcp: { ...base.mcp, servers },
|
|
8119
|
+
diagnostics: [...base.diagnostics, ...layer.diagnostics],
|
|
8120
|
+
workspace: {
|
|
8121
|
+
root: layer.root,
|
|
8122
|
+
...layer.instructionsFile !== void 0 ? { instructionsFile: layer.instructionsFile } : {},
|
|
8123
|
+
mcpProvenance,
|
|
8124
|
+
mcpGlobalServers,
|
|
8125
|
+
skillProvenance,
|
|
8126
|
+
globalSkills,
|
|
8127
|
+
shadowed
|
|
8128
|
+
}
|
|
8129
|
+
};
|
|
8130
|
+
}
|
|
8131
|
+
|
|
8132
|
+
// src/core/canonical.ts
|
|
7974
8133
|
function trellisRoot(homeDir) {
|
|
7975
|
-
return
|
|
8134
|
+
return join2(homeDir, ".trellis");
|
|
7976
8135
|
}
|
|
7977
8136
|
function listMarkdownFiles(dir) {
|
|
7978
8137
|
let entries;
|
|
7979
8138
|
try {
|
|
7980
|
-
entries =
|
|
8139
|
+
entries = readdirSync2(dir);
|
|
7981
8140
|
} catch {
|
|
7982
8141
|
return [];
|
|
7983
8142
|
}
|
|
7984
|
-
return entries.filter((name) => name.endsWith(".md")).map((name) => ({ name: basename(name, ".md"), file:
|
|
8143
|
+
return entries.filter((name) => name.endsWith(".md")).map((name) => ({ name: basename(name, ".md"), file: join2(dir, name) }));
|
|
7985
8144
|
}
|
|
7986
8145
|
function listSkillDirs(dir) {
|
|
7987
8146
|
let entries;
|
|
7988
8147
|
try {
|
|
7989
|
-
entries =
|
|
8148
|
+
entries = readdirSync2(dir);
|
|
7990
8149
|
} catch {
|
|
7991
8150
|
return [];
|
|
7992
8151
|
}
|
|
7993
8152
|
const skills = [];
|
|
7994
8153
|
for (const name of entries) {
|
|
7995
|
-
const skillDir =
|
|
8154
|
+
const skillDir = join2(dir, name);
|
|
7996
8155
|
try {
|
|
7997
|
-
if (
|
|
8156
|
+
if (statSync2(skillDir).isDirectory()) {
|
|
7998
8157
|
skills.push({ name, dir: skillDir });
|
|
7999
8158
|
}
|
|
8000
8159
|
} catch {
|
|
@@ -8003,17 +8162,17 @@ function listSkillDirs(dir) {
|
|
|
8003
8162
|
return skills;
|
|
8004
8163
|
}
|
|
8005
8164
|
function loadScopeYaml(path) {
|
|
8006
|
-
if (!
|
|
8165
|
+
if (!existsSync3(path)) {
|
|
8007
8166
|
return {};
|
|
8008
8167
|
}
|
|
8009
|
-
const parsed = (0, import_yaml.parse)(
|
|
8168
|
+
const parsed = (0, import_yaml.parse)(readFileSync3(path, "utf-8"));
|
|
8010
8169
|
return parsed ?? {};
|
|
8011
8170
|
}
|
|
8012
8171
|
function loadServersYaml(path) {
|
|
8013
|
-
if (!
|
|
8172
|
+
if (!existsSync3(path)) {
|
|
8014
8173
|
return { servers: {}, knownHostInjected: [] };
|
|
8015
8174
|
}
|
|
8016
|
-
const parsed = (0, import_yaml.parse)(
|
|
8175
|
+
const parsed = (0, import_yaml.parse)(readFileSync3(path, "utf-8")) ?? {};
|
|
8017
8176
|
const servers = Object.fromEntries(Object.entries(parsed.servers ?? {}).map(([name, def]) => [name, fromServerDefYaml(name, def)]));
|
|
8018
8177
|
return {
|
|
8019
8178
|
servers,
|
|
@@ -8054,10 +8213,10 @@ function fromGatewayYaml(gateway) {
|
|
|
8054
8213
|
return out;
|
|
8055
8214
|
}
|
|
8056
8215
|
function loadSecretsPolicyYaml(path, homeDir) {
|
|
8057
|
-
if (!
|
|
8216
|
+
if (!existsSync3(path)) {
|
|
8058
8217
|
return { allowedVars: [], rejectPatterns: [] };
|
|
8059
8218
|
}
|
|
8060
|
-
const parsed = (0, import_yaml.parse)(
|
|
8219
|
+
const parsed = (0, import_yaml.parse)(readFileSync3(path, "utf-8")) ?? {};
|
|
8061
8220
|
return {
|
|
8062
8221
|
allowedVars: parsed.allowed_vars ?? [],
|
|
8063
8222
|
rejectPatterns: (parsed.reject_patterns ?? []).map((pattern) => new RegExp(pattern)),
|
|
@@ -8065,10 +8224,10 @@ function loadSecretsPolicyYaml(path, homeDir) {
|
|
|
8065
8224
|
};
|
|
8066
8225
|
}
|
|
8067
8226
|
function loadManagedYaml(path, diagnostics) {
|
|
8068
|
-
if (!
|
|
8227
|
+
if (!existsSync3(path)) {
|
|
8069
8228
|
return [];
|
|
8070
8229
|
}
|
|
8071
|
-
const parsed = (0, import_yaml.parse)(
|
|
8230
|
+
const parsed = (0, import_yaml.parse)(readFileSync3(path, "utf-8")) ?? {};
|
|
8072
8231
|
const raw = parsed.agents ?? [];
|
|
8073
8232
|
const valid = [];
|
|
8074
8233
|
for (const id of raw) {
|
|
@@ -8106,27 +8265,29 @@ function assertAuthMetadataClean(mcp, policy) {
|
|
|
8106
8265
|
}
|
|
8107
8266
|
}
|
|
8108
8267
|
}
|
|
8109
|
-
function loadCanonicalSource(
|
|
8268
|
+
function loadCanonicalSource(arg = {}) {
|
|
8269
|
+
const options = typeof arg === "string" ? { homeDir: arg } : arg;
|
|
8270
|
+
const homeDir = options.homeDir ?? homedir();
|
|
8110
8271
|
const root = trellisRoot(homeDir);
|
|
8111
|
-
if (!
|
|
8272
|
+
if (!existsSync3(root)) {
|
|
8112
8273
|
throw new Error(
|
|
8113
8274
|
`No canonical source at ${root}. Run trellis init before trellis sync.`
|
|
8114
8275
|
);
|
|
8115
8276
|
}
|
|
8116
8277
|
const diagnostics = [];
|
|
8117
|
-
const managedAgents = loadManagedYaml(
|
|
8118
|
-
const scopeYaml = loadScopeYaml(
|
|
8119
|
-
const skillDirs = listSkillDirs(
|
|
8278
|
+
const managedAgents = loadManagedYaml(join2(root, "managed.yaml"), diagnostics);
|
|
8279
|
+
const scopeYaml = loadScopeYaml(join2(root, "scope.yaml"));
|
|
8280
|
+
const skillDirs = listSkillDirs(join2(root, "skills"));
|
|
8120
8281
|
const knownSkillNames = new Set(skillDirs.map((s) => s.name));
|
|
8121
8282
|
const skills = skillDirs.map(({ name, dir }) => ({ name, dir, scope: scopeFor(scopeYaml.skills, name) }));
|
|
8122
|
-
const agentFiles = listMarkdownFiles(
|
|
8283
|
+
const agentFiles = listMarkdownFiles(join2(root, "agents"));
|
|
8123
8284
|
const knownAgentProfileNames = new Set(agentFiles.map((a) => a.name));
|
|
8124
8285
|
const agents = agentFiles.map(({ name, file: file2 }) => ({
|
|
8125
8286
|
name,
|
|
8126
8287
|
file: file2,
|
|
8127
8288
|
scope: scopeFor(scopeYaml.agents, name)
|
|
8128
8289
|
}));
|
|
8129
|
-
const memoryFiles = listMarkdownFiles(
|
|
8290
|
+
const memoryFiles = listMarkdownFiles(join2(root, "memories"));
|
|
8130
8291
|
const knownMemoryNames = new Set(memoryFiles.map((m) => m.name));
|
|
8131
8292
|
const memories = memoryFiles.map(({ name, file: file2 }) => ({
|
|
8132
8293
|
name,
|
|
@@ -8147,11 +8308,11 @@ function loadCanonicalSource(homeDir = homedir()) {
|
|
|
8147
8308
|
}
|
|
8148
8309
|
}
|
|
8149
8310
|
}
|
|
8150
|
-
const mcp = loadServersYaml(
|
|
8151
|
-
const secretsPolicy = loadSecretsPolicyYaml(
|
|
8311
|
+
const mcp = loadServersYaml(join2(root, "mcp", "servers.yaml"));
|
|
8312
|
+
const secretsPolicy = loadSecretsPolicyYaml(join2(root, "secrets.policy.yaml"), homeDir);
|
|
8152
8313
|
assertAuthMetadataClean(mcp, secretsPolicy);
|
|
8153
|
-
|
|
8154
|
-
instructionsFile:
|
|
8314
|
+
const source = {
|
|
8315
|
+
instructionsFile: join2(root, "agents.md"),
|
|
8155
8316
|
managedAgents,
|
|
8156
8317
|
skills,
|
|
8157
8318
|
agents,
|
|
@@ -8160,6 +8321,11 @@ function loadCanonicalSource(homeDir = homedir()) {
|
|
|
8160
8321
|
secretsPolicy,
|
|
8161
8322
|
diagnostics
|
|
8162
8323
|
};
|
|
8324
|
+
if (options.workspaceDir) {
|
|
8325
|
+
const layer = loadWorkspaceLayer(options.workspaceDir, secretsPolicy);
|
|
8326
|
+
return mergeWorkspaceLayer(source, layer);
|
|
8327
|
+
}
|
|
8328
|
+
return source;
|
|
8163
8329
|
}
|
|
8164
8330
|
|
|
8165
8331
|
// src/core/adapter.ts
|
|
@@ -13464,7 +13630,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
13464
13630
|
var NONE = 0;
|
|
13465
13631
|
var ASSUMED = 1;
|
|
13466
13632
|
var PROVEN = 2;
|
|
13467
|
-
function isRecursive(inst, stack,
|
|
13633
|
+
function isRecursive(inst, stack, resolve2) {
|
|
13468
13634
|
const cached2 = recursive.get(inst);
|
|
13469
13635
|
if (cached2 !== void 0)
|
|
13470
13636
|
return cached2 ? PROVEN : NONE;
|
|
@@ -13474,7 +13640,7 @@ function isRecursive(inst, stack, resolve) {
|
|
|
13474
13640
|
let result = NONE;
|
|
13475
13641
|
const check2 = (child) => {
|
|
13476
13642
|
if (result !== PROVEN && child?._zod) {
|
|
13477
|
-
const answer = isRecursive(child, stack,
|
|
13643
|
+
const answer = isRecursive(child, stack, resolve2);
|
|
13478
13644
|
if (answer > result)
|
|
13479
13645
|
result = answer;
|
|
13480
13646
|
}
|
|
@@ -13485,7 +13651,7 @@ function isRecursive(inst, stack, resolve) {
|
|
|
13485
13651
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
13486
13652
|
if (spread && !desc.enumerable)
|
|
13487
13653
|
continue;
|
|
13488
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
13654
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve2) : NONE;
|
|
13489
13655
|
if (child > answer)
|
|
13490
13656
|
answer = child;
|
|
13491
13657
|
}
|
|
@@ -13549,7 +13715,7 @@ function isRecursive(inst, stack, resolve) {
|
|
|
13549
13715
|
break;
|
|
13550
13716
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
13551
13717
|
case "lazy": {
|
|
13552
|
-
const inner = def._cachedInner ?? (
|
|
13718
|
+
const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
|
|
13553
13719
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
13554
13720
|
break;
|
|
13555
13721
|
}
|
|
@@ -32471,14 +32637,14 @@ function inputRequiredRoundsExceededMessage(method, maxRounds) {
|
|
|
32471
32637
|
return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
|
|
32472
32638
|
}
|
|
32473
32639
|
function sleep(ms, signal) {
|
|
32474
|
-
return new Promise((
|
|
32640
|
+
return new Promise((resolve2, reject) => {
|
|
32475
32641
|
if (signal?.aborted) {
|
|
32476
32642
|
reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
|
|
32477
32643
|
return;
|
|
32478
32644
|
}
|
|
32479
32645
|
const timer = setTimeout(() => {
|
|
32480
32646
|
signal?.removeEventListener("abort", onAbort);
|
|
32481
|
-
|
|
32647
|
+
resolve2();
|
|
32482
32648
|
}, ms);
|
|
32483
32649
|
const onAbort = () => {
|
|
32484
32650
|
clearTimeout(timer);
|
|
@@ -33322,7 +33488,7 @@ var Protocol = class {
|
|
|
33322
33488
|
const flowStartedAt = Date.now();
|
|
33323
33489
|
let onAbort;
|
|
33324
33490
|
let cleanupMessageId;
|
|
33325
|
-
return new Promise((
|
|
33491
|
+
return new Promise((resolve2, reject) => {
|
|
33326
33492
|
const earlyReject = (error62) => {
|
|
33327
33493
|
reject(error62);
|
|
33328
33494
|
};
|
|
@@ -33391,7 +33557,7 @@ var Protocol = class {
|
|
|
33391
33557
|
}
|
|
33392
33558
|
if (decoded.kind === "invalid") return reject(decoded.error);
|
|
33393
33559
|
if (decoded.kind === "input_required") {
|
|
33394
|
-
if (options?.allowInputRequired === true) return
|
|
33560
|
+
if (options?.allowInputRequired === true) return resolve2(manualInputRequiredValue(decoded));
|
|
33395
33561
|
const flow = {
|
|
33396
33562
|
codec: codec2,
|
|
33397
33563
|
request,
|
|
@@ -33403,11 +33569,11 @@ var Protocol = class {
|
|
|
33403
33569
|
params
|
|
33404
33570
|
}, resultSchema, legOptions)
|
|
33405
33571
|
};
|
|
33406
|
-
return
|
|
33572
|
+
return resolve2(this._resolveNonCompleteResult(decoded, flow));
|
|
33407
33573
|
}
|
|
33408
33574
|
const result = decoded.result;
|
|
33409
33575
|
validateStandardSchema(resultSchema, result).then((parseResult) => {
|
|
33410
|
-
if (parseResult.success)
|
|
33576
|
+
if (parseResult.success) resolve2(parseResult.data);
|
|
33411
33577
|
else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
|
|
33412
33578
|
}, reject);
|
|
33413
33579
|
});
|
|
@@ -36424,7 +36590,7 @@ var require_compile = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
36424
36590
|
ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
|
|
36425
36591
|
const schOrFunc = root.refs[ref];
|
|
36426
36592
|
if (schOrFunc) return schOrFunc;
|
|
36427
|
-
let _sch =
|
|
36593
|
+
let _sch = resolve2.call(this, root, ref);
|
|
36428
36594
|
if (_sch === void 0) {
|
|
36429
36595
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
36430
36596
|
const { schemaId } = this.opts;
|
|
@@ -36450,7 +36616,7 @@ var require_compile = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
36450
36616
|
function sameSchemaEnv(s1, s2) {
|
|
36451
36617
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
36452
36618
|
}
|
|
36453
|
-
function
|
|
36619
|
+
function resolve2(root, ref) {
|
|
36454
36620
|
let sch;
|
|
36455
36621
|
while (typeof (sch = this.refs[ref]) == "string") ref = sch;
|
|
36456
36622
|
return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
|
|
@@ -36900,7 +37066,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
36900
37066
|
else if (typeof uri === "object") uri = parse3(serialize(uri, options), options);
|
|
36901
37067
|
return uri;
|
|
36902
37068
|
}
|
|
36903
|
-
function
|
|
37069
|
+
function resolve2(baseURI, relativeURI, options) {
|
|
36904
37070
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
36905
37071
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
36906
37072
|
schemelessOptions.skipEscape = true;
|
|
@@ -37074,7 +37240,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
37074
37240
|
const fastUri = {
|
|
37075
37241
|
SCHEMES,
|
|
37076
37242
|
normalize,
|
|
37077
|
-
resolve,
|
|
37243
|
+
resolve: resolve2,
|
|
37078
37244
|
resolveComponent,
|
|
37079
37245
|
equal,
|
|
37080
37246
|
serialize,
|
|
@@ -42939,14 +43105,14 @@ var ProbeWindow = class ProbeWindow2 {
|
|
|
42939
43105
|
*/
|
|
42940
43106
|
async exchange(buildRequest, timeoutMs) {
|
|
42941
43107
|
const id = `server-discover-probe-${++this._probeCounter}`;
|
|
42942
|
-
return new Promise((
|
|
43108
|
+
return new Promise((resolve2) => {
|
|
42943
43109
|
let settled = false;
|
|
42944
43110
|
const settle2 = (reply) => {
|
|
42945
43111
|
if (settled) return;
|
|
42946
43112
|
settled = true;
|
|
42947
43113
|
clearTimeout(timer);
|
|
42948
43114
|
if (this._pending?.id === id) this._pending = void 0;
|
|
42949
|
-
|
|
43115
|
+
resolve2(reply);
|
|
42950
43116
|
};
|
|
42951
43117
|
const timer = setTimeout(() => settle2({ kind: "timeout" }), timeoutMs);
|
|
42952
43118
|
this._pending = {
|
|
@@ -44160,13 +44326,13 @@ var Client = class extends Protocol {
|
|
|
44160
44326
|
let onCallerAbort;
|
|
44161
44327
|
let resolveOpening;
|
|
44162
44328
|
let rejectOpening;
|
|
44163
|
-
const opening = new Promise((
|
|
44164
|
-
resolveOpening =
|
|
44329
|
+
const opening = new Promise((resolve2, reject) => {
|
|
44330
|
+
resolveOpening = resolve2;
|
|
44165
44331
|
rejectOpening = reject;
|
|
44166
44332
|
});
|
|
44167
44333
|
let resolveClosed;
|
|
44168
|
-
const closed = new Promise((
|
|
44169
|
-
resolveClosed =
|
|
44334
|
+
const closed = new Promise((resolve2) => {
|
|
44335
|
+
resolveClosed = resolve2;
|
|
44170
44336
|
});
|
|
44171
44337
|
const settle2 = (outcome) => {
|
|
44172
44338
|
if (state === "closed") return;
|
|
@@ -44722,7 +44888,7 @@ var SSEClientTransport = class {
|
|
|
44722
44888
|
const eventSourceFetch = this._eventSourceInit?.fetch;
|
|
44723
44889
|
const fetchImpl = this._redirects(eventSourceFetch ? this._dpop?.(eventSourceFetch) ?? eventSourceFetch : this._fetch ?? fetch);
|
|
44724
44890
|
let redirect;
|
|
44725
|
-
return new Promise((
|
|
44891
|
+
return new Promise((resolve2, reject) => {
|
|
44726
44892
|
this._eventSource = new EventSource(this._url.href, {
|
|
44727
44893
|
...this._eventSourceInit,
|
|
44728
44894
|
fetch: async (url2, init) => {
|
|
@@ -44756,7 +44922,7 @@ var SSEClientTransport = class {
|
|
|
44756
44922
|
response,
|
|
44757
44923
|
serverUrl: this._url,
|
|
44758
44924
|
fetchFn: this._fetchWithInit
|
|
44759
|
-
}).then(() => this._startOrAuth().then(
|
|
44925
|
+
}).then(() => this._startOrAuth().then(resolve2, reject), (error$2) => {
|
|
44760
44926
|
this._connectAuthRetried = false;
|
|
44761
44927
|
markAuthSeamEscape(error$2);
|
|
44762
44928
|
this.onerror?.(error$2);
|
|
@@ -44794,7 +44960,7 @@ var SSEClientTransport = class {
|
|
|
44794
44960
|
this.close();
|
|
44795
44961
|
return;
|
|
44796
44962
|
}
|
|
44797
|
-
|
|
44963
|
+
resolve2();
|
|
44798
44964
|
});
|
|
44799
44965
|
this._eventSource.onmessage = (event) => {
|
|
44800
44966
|
const messageEvent = event;
|
|
@@ -45539,7 +45705,7 @@ var StdioClientTransport = class {
|
|
|
45539
45705
|
*/
|
|
45540
45706
|
async start() {
|
|
45541
45707
|
if (this._process) throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
|
45542
|
-
return new Promise((
|
|
45708
|
+
return new Promise((resolve2, reject) => {
|
|
45543
45709
|
this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
|
|
45544
45710
|
env: {
|
|
45545
45711
|
...getDefaultEnvironment(),
|
|
@@ -45559,7 +45725,7 @@ var StdioClientTransport = class {
|
|
|
45559
45725
|
this.onerror?.(error62);
|
|
45560
45726
|
});
|
|
45561
45727
|
this._process.on("spawn", () => {
|
|
45562
|
-
|
|
45728
|
+
resolve2();
|
|
45563
45729
|
});
|
|
45564
45730
|
this._process.on("close", (_code) => {
|
|
45565
45731
|
this._process = void 0;
|
|
@@ -45624,7 +45790,7 @@ var StdioClientTransport = class {
|
|
|
45624
45790
|
const proc = this._process;
|
|
45625
45791
|
this._process = void 0;
|
|
45626
45792
|
if (proc && proc.exitCode === null && proc.signalCode === null) {
|
|
45627
|
-
const exited = new Promise((
|
|
45793
|
+
const exited = new Promise((resolve2) => proc.once("exit", () => resolve2()));
|
|
45628
45794
|
try {
|
|
45629
45795
|
proc.stdin?.end();
|
|
45630
45796
|
} catch {
|
|
@@ -45633,7 +45799,7 @@ var StdioClientTransport = class {
|
|
|
45633
45799
|
proc.kill("SIGTERM");
|
|
45634
45800
|
} catch {
|
|
45635
45801
|
}
|
|
45636
|
-
await Promise.race([exited, new Promise((
|
|
45802
|
+
await Promise.race([exited, new Promise((resolve2) => setTimeout(resolve2, 1e3).unref())]);
|
|
45637
45803
|
if (proc.exitCode === null && proc.signalCode === null) try {
|
|
45638
45804
|
proc.kill("SIGKILL");
|
|
45639
45805
|
} catch {
|
|
@@ -45658,22 +45824,22 @@ var StdioClientTransport = class {
|
|
|
45658
45824
|
if (this._process) {
|
|
45659
45825
|
const processToClose = this._process;
|
|
45660
45826
|
this._process = void 0;
|
|
45661
|
-
const closePromise = new Promise((
|
|
45827
|
+
const closePromise = new Promise((resolve2) => {
|
|
45662
45828
|
processToClose.once("close", () => {
|
|
45663
|
-
|
|
45829
|
+
resolve2();
|
|
45664
45830
|
});
|
|
45665
45831
|
});
|
|
45666
45832
|
try {
|
|
45667
45833
|
processToClose.stdin?.end();
|
|
45668
45834
|
} catch {
|
|
45669
45835
|
}
|
|
45670
|
-
await Promise.race([closePromise, new Promise((
|
|
45836
|
+
await Promise.race([closePromise, new Promise((resolve2) => setTimeout(resolve2, 2e3).unref())]);
|
|
45671
45837
|
if (processToClose.exitCode === null) {
|
|
45672
45838
|
try {
|
|
45673
45839
|
processToClose.kill("SIGTERM");
|
|
45674
45840
|
} catch {
|
|
45675
45841
|
}
|
|
45676
|
-
await Promise.race([closePromise, new Promise((
|
|
45842
|
+
await Promise.race([closePromise, new Promise((resolve2) => setTimeout(resolve2, 2e3).unref())]);
|
|
45677
45843
|
}
|
|
45678
45844
|
if (processToClose.exitCode === null) try {
|
|
45679
45845
|
processToClose.kill("SIGKILL");
|
|
@@ -45683,11 +45849,11 @@ var StdioClientTransport = class {
|
|
|
45683
45849
|
this._readBuffer.clear();
|
|
45684
45850
|
}
|
|
45685
45851
|
send(message) {
|
|
45686
|
-
return new Promise((
|
|
45852
|
+
return new Promise((resolve2) => {
|
|
45687
45853
|
if (!this._process?.stdin) throw new SdkError(SdkErrorCode.NotConnected, "Not connected");
|
|
45688
45854
|
const json2 = serializeMessage(message);
|
|
45689
|
-
if (this._process.stdin.write(json2))
|
|
45690
|
-
else this._process.stdin.once("drain",
|
|
45855
|
+
if (this._process.stdin.write(json2)) resolve2();
|
|
45856
|
+
else this._process.stdin.once("drain", resolve2);
|
|
45691
45857
|
});
|
|
45692
45858
|
}
|
|
45693
45859
|
};
|
|
@@ -45702,12 +45868,12 @@ function extractTemplateVarNames(value) {
|
|
|
45702
45868
|
var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
|
|
45703
45869
|
var FAILED_TRANSPORT_CLEANUP_TIMEOUT_MS = 1e3;
|
|
45704
45870
|
function withTimeout(promise2, timeoutMs, message) {
|
|
45705
|
-
return new Promise((
|
|
45871
|
+
return new Promise((resolve2, reject) => {
|
|
45706
45872
|
const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
45707
45873
|
promise2.then(
|
|
45708
45874
|
(value) => {
|
|
45709
45875
|
clearTimeout(timer);
|
|
45710
|
-
|
|
45876
|
+
resolve2(value);
|
|
45711
45877
|
},
|
|
45712
45878
|
(err) => {
|
|
45713
45879
|
clearTimeout(timer);
|
|
@@ -45930,18 +46096,18 @@ var McpToolRegistry = class {
|
|
|
45930
46096
|
};
|
|
45931
46097
|
|
|
45932
46098
|
// src/lib/oauth/store.ts
|
|
45933
|
-
import { chmodSync, existsSync as
|
|
45934
|
-
import { join as
|
|
46099
|
+
import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
46100
|
+
import { join as join3 } from "node:path";
|
|
45935
46101
|
function oauthDir(homeDir) {
|
|
45936
|
-
return
|
|
46102
|
+
return join3(homeDir, ".trellis", "mcp", "oauth");
|
|
45937
46103
|
}
|
|
45938
46104
|
function tokenPath(homeDir, serverName) {
|
|
45939
46105
|
assertSafeServerName(serverName);
|
|
45940
|
-
return
|
|
46106
|
+
return join3(oauthDir(homeDir), `${serverName}.json`);
|
|
45941
46107
|
}
|
|
45942
46108
|
function lockPath(homeDir, serverName) {
|
|
45943
46109
|
assertSafeServerName(serverName);
|
|
45944
|
-
return
|
|
46110
|
+
return join3(oauthDir(homeDir), `${serverName}.lock`);
|
|
45945
46111
|
}
|
|
45946
46112
|
function assertSafeServerName(serverName) {
|
|
45947
46113
|
if (serverName === "" || serverName === "." || serverName === ".." || /[/\\]/.test(serverName) || serverName.startsWith(".")) {
|
|
@@ -45950,9 +46116,9 @@ function assertSafeServerName(serverName) {
|
|
|
45950
46116
|
}
|
|
45951
46117
|
function readToken(homeDir, serverName) {
|
|
45952
46118
|
const path = tokenPath(homeDir, serverName);
|
|
45953
|
-
if (!
|
|
46119
|
+
if (!existsSync4(path)) return void 0;
|
|
45954
46120
|
try {
|
|
45955
|
-
return JSON.parse(
|
|
46121
|
+
return JSON.parse(readFileSync4(path, "utf-8"));
|
|
45956
46122
|
} catch {
|
|
45957
46123
|
return void 0;
|
|
45958
46124
|
}
|
|
@@ -45974,8 +46140,8 @@ function isExpired(token, skewMs = 6e4, now = Date.now()) {
|
|
|
45974
46140
|
}
|
|
45975
46141
|
|
|
45976
46142
|
// src/lib/oauth/lock.ts
|
|
45977
|
-
import { existsSync as
|
|
45978
|
-
import { dirname as
|
|
46143
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, openSync, closeSync, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
46144
|
+
import { dirname as dirname3 } from "node:path";
|
|
45979
46145
|
var STALE_AFTER_MS = 6e4;
|
|
45980
46146
|
var POLL_INTERVAL_MS = 50;
|
|
45981
46147
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -45990,7 +46156,7 @@ function processAlive(pid) {
|
|
|
45990
46156
|
function isStale(path, now) {
|
|
45991
46157
|
let contents;
|
|
45992
46158
|
try {
|
|
45993
|
-
contents = JSON.parse(
|
|
46159
|
+
contents = JSON.parse(readFileSync5(path, "utf-8"));
|
|
45994
46160
|
} catch {
|
|
45995
46161
|
return true;
|
|
45996
46162
|
}
|
|
@@ -46003,7 +46169,7 @@ async function withServerLock(homeDir, serverName, fn, opts = {}) {
|
|
|
46003
46169
|
const now = opts.now ?? Date.now;
|
|
46004
46170
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
46005
46171
|
const deadline = now() + timeoutMs;
|
|
46006
|
-
mkdirSync4(
|
|
46172
|
+
mkdirSync4(dirname3(path), { recursive: true, mode: 448 });
|
|
46007
46173
|
for (; ; ) {
|
|
46008
46174
|
try {
|
|
46009
46175
|
const fd = openSync(path, "wx", 384);
|
|
@@ -46015,14 +46181,14 @@ async function withServerLock(homeDir, serverName, fn, opts = {}) {
|
|
|
46015
46181
|
break;
|
|
46016
46182
|
} catch (err) {
|
|
46017
46183
|
if (err.code !== "EEXIST") throw err;
|
|
46018
|
-
if (
|
|
46184
|
+
if (existsSync5(path) && isStale(path, now())) {
|
|
46019
46185
|
rmSync2(path, { force: true });
|
|
46020
46186
|
continue;
|
|
46021
46187
|
}
|
|
46022
46188
|
if (now() >= deadline) {
|
|
46023
46189
|
throw new Error(`timed out waiting for the OAuth refresh lock on "${serverName}" (${path})`);
|
|
46024
46190
|
}
|
|
46025
|
-
await new Promise((
|
|
46191
|
+
await new Promise((resolve2) => setTimeout(resolve2, POLL_INTERVAL_MS));
|
|
46026
46192
|
}
|
|
46027
46193
|
}
|
|
46028
46194
|
try {
|