@brainmcp/brainmcp 0.1.18 → 0.1.19
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 +5 -4
- package/dist/api-client.js +177 -0
- package/dist/commands/auth.js +8 -4
- package/dist/commands/auth.js.map +1 -1
- package/dist/lib/api-client.d.ts +10 -0
- package/dist/lib/api-client.js +30 -4
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/cli-contracts.d.ts +1 -1
- package/dist/lib/credentials.d.ts +11 -0
- package/dist/lib/credentials.js.map +1 -1
- package/dist/lib/oauth-client.d.ts +5 -0
- package/dist/lib/oauth-client.js +32 -0
- package/dist/lib/oauth-client.js.map +1 -1
- package/dist/runtime/brainmcp-hook-runtime.mjs +302 -219
- package/dist/runtime/doctor-checks.js +24 -4
- package/dist/runtime/doctor-checks.js.map +1 -1
- package/dist/runtime/flush.js +2 -1
- package/dist/runtime/flush.js.map +1 -1
- package/dist/runtime/orient.d.ts +12 -0
- package/dist/runtime/orient.js +65 -7
- package/dist/runtime/orient.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-client.js","sourceRoot":"","sources":["../../src/lib/oauth-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-client.js","sourceRoot":"","sources":["../../src/lib/oauth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -598,6 +598,12 @@ function removeQueueItem(digestId, baseDir) {
|
|
|
598
598
|
return false;
|
|
599
599
|
}
|
|
600
600
|
|
|
601
|
+
// ../api-client/src/index.ts
|
|
602
|
+
function apiPathSegment(value) {
|
|
603
|
+
const encoded = encodeURIComponent(value);
|
|
604
|
+
return /^\.+$/.test(encoded) ? encoded.replaceAll(".", "%2E") : encoded;
|
|
605
|
+
}
|
|
606
|
+
|
|
601
607
|
// src/runtime/diagnostics.ts
|
|
602
608
|
import fs3 from "node:fs";
|
|
603
609
|
import path3 from "node:path";
|
|
@@ -809,7 +815,7 @@ function canEnqueueCapture(baseDir) {
|
|
|
809
815
|
}
|
|
810
816
|
async function postDigest(apiClient, item, signal, beforeSend) {
|
|
811
817
|
try {
|
|
812
|
-
await apiClient.request(`/api/workspaces/${item.workspaceId}/digests`, {
|
|
818
|
+
await apiClient.request(`/api/workspaces/${apiPathSegment(item.workspaceId)}/digests`, {
|
|
813
819
|
method: "POST",
|
|
814
820
|
body: {
|
|
815
821
|
clientDigestId: item.digestId,
|
|
@@ -1921,6 +1927,9 @@ function isCaptureEligible(event, prefs, projectPolicy) {
|
|
|
1921
1927
|
import fs9 from "node:fs";
|
|
1922
1928
|
import path9 from "node:path";
|
|
1923
1929
|
|
|
1930
|
+
// src/lib/api-client.ts
|
|
1931
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
1932
|
+
|
|
1924
1933
|
// src/lib/endpoints.ts
|
|
1925
1934
|
var COMPANION_WORKSPACES_PATH = "/api/mcp/workspaces";
|
|
1926
1935
|
var MCP_REST_HOSTS = /* @__PURE__ */ new Set(["mcp.brainmcp.ai", "dash.brainmcp.ai"]);
|
|
@@ -1946,220 +1955,6 @@ function describeMisdirectedCompanionApi(apiUrl) {
|
|
|
1946
1955
|
return `Companion REST must use ${BRAIN_API_ORIGIN}, not ${apiUrl}. Unset BRAINMCP_API_URL or point it at the API origin.`;
|
|
1947
1956
|
}
|
|
1948
1957
|
|
|
1949
|
-
// src/runtime/orient.ts
|
|
1950
|
-
var ORIENT_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
1951
|
-
var ORIENT_CONTEXT_MAX_CHARS = 2400;
|
|
1952
|
-
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1953
|
-
var SESSION_START_EVENTS = /* @__PURE__ */ new Set([
|
|
1954
|
-
"SessionStart",
|
|
1955
|
-
"sessionStart",
|
|
1956
|
-
"session_start",
|
|
1957
|
-
"startup"
|
|
1958
|
-
]);
|
|
1959
|
-
function isSessionStartEvent(event) {
|
|
1960
|
-
return SESSION_START_EVENTS.has(event);
|
|
1961
|
-
}
|
|
1962
|
-
function isUserPromptEvent(event) {
|
|
1963
|
-
return event === "UserPromptSubmit" || event === "UserPrompt" || event === "prompt" || event === "beforeSubmitPrompt";
|
|
1964
|
-
}
|
|
1965
|
-
function resolveOrientWorkspaceId(creds, listed) {
|
|
1966
|
-
if (!creds || creds.authType !== "oauth" || !creds.accessToken) {
|
|
1967
|
-
return { workspaceId: null, reason: "login" };
|
|
1968
|
-
}
|
|
1969
|
-
if (creds.defaultWorkspaceId && UUID_RE2.test(creds.defaultWorkspaceId)) {
|
|
1970
|
-
return { workspaceId: creds.defaultWorkspaceId, reason: "ok" };
|
|
1971
|
-
}
|
|
1972
|
-
const fromCreds = (creds.workspaces ?? []).filter((id) => UUID_RE2.test(id));
|
|
1973
|
-
if (fromCreds.length === 1) {
|
|
1974
|
-
return { workspaceId: fromCreds[0], reason: "ok" };
|
|
1975
|
-
}
|
|
1976
|
-
if (listed) {
|
|
1977
|
-
const defaults = listed.filter((ws) => ws.isDefault);
|
|
1978
|
-
if (defaults.length === 1 && UUID_RE2.test(defaults[0].id)) {
|
|
1979
|
-
return { workspaceId: defaults[0].id, reason: "ok" };
|
|
1980
|
-
}
|
|
1981
|
-
if (listed.length === 1 && UUID_RE2.test(listed[0].id)) {
|
|
1982
|
-
return { workspaceId: listed[0].id, reason: "ok" };
|
|
1983
|
-
}
|
|
1984
|
-
if (listed.length !== 1) {
|
|
1985
|
-
return { workspaceId: null, reason: "select" };
|
|
1986
|
-
}
|
|
1987
|
-
}
|
|
1988
|
-
if (fromCreds.length !== 1) {
|
|
1989
|
-
return { workspaceId: null, reason: fromCreds.length === 0 ? "select" : "select" };
|
|
1990
|
-
}
|
|
1991
|
-
return { workspaceId: null, reason: "select" };
|
|
1992
|
-
}
|
|
1993
|
-
var ORIENT_PACKET_HEADER = [
|
|
1994
|
-
"BrainMCP orientation (no user prompt was sent).",
|
|
1995
|
-
ANSWER_GROUNDING_BRIEF_GUIDANCE,
|
|
1996
|
-
"This hook packet is bounded; call brain_workspace_overview for full Rules and current project context before dependent work. Clipped or omitted workspace details are incomplete."
|
|
1997
|
-
].join("\n");
|
|
1998
|
-
function isRecord(value) {
|
|
1999
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2000
|
-
}
|
|
2001
|
-
function clipContext(text, maxChars) {
|
|
2002
|
-
if (text.length <= maxChars) return text;
|
|
2003
|
-
return `${text.slice(0, maxChars - 1).replace(/[\uD800-\uDBFF]$/, "")}\u2026`;
|
|
2004
|
-
}
|
|
2005
|
-
function formatOrientDetails(payload, expectedWorkspaceId) {
|
|
2006
|
-
const workspace = isRecord(payload) && isRecord(payload.workspace) ? payload.workspace : void 0;
|
|
2007
|
-
if (!workspace || typeof workspace.id !== "string" || !workspace.id.trim() || typeof workspace.name !== "string" || !workspace.name.trim() || expectedWorkspaceId && workspace.id !== expectedWorkspaceId) {
|
|
2008
|
-
return `${expectedWorkspaceId ? `Workspace ${expectedWorkspaceId}: ` : ""}BrainMCP orientation returned no usable context. Call brain_workspace_overview for this workspace before dependent work.`;
|
|
2009
|
-
}
|
|
2010
|
-
const data = payload;
|
|
2011
|
-
const lines = [`Workspace ${clipContext(workspace.id, 80)}: ${clipContext(workspace.name.trim(), 120)}`];
|
|
2012
|
-
const activeRef = isRecord(data.activeRef) ? data.activeRef : void 0;
|
|
2013
|
-
if (activeRef?.type === "live") lines.push("Active ref: live.");
|
|
2014
|
-
if (activeRef?.type === "branch" && typeof activeRef.branchId === "string") {
|
|
2015
|
-
lines.push(`Active ref: branch ${clipContext(activeRef.branchId, 80)}.`);
|
|
2016
|
-
}
|
|
2017
|
-
const authorization = isRecord(data.authorization) ? data.authorization : void 0;
|
|
2018
|
-
const scopes = Array.isArray(authorization?.scopes) && authorization.scopes.every((scope) => typeof scope === "string") ? authorization.scopes : void 0;
|
|
2019
|
-
const canWrite = scopes?.some((scope) => scope === "*" || scope === "changes:write") === true;
|
|
2020
|
-
if (!canWrite) {
|
|
2021
|
-
lines.push(scopes ? "Companion authorization lacks changes:write. Host MCP permissions are independent; check its overview before proposing changes." : "Companion write access is unknown. Check host MCP permissions in overview before proposing changes.");
|
|
2022
|
-
}
|
|
2023
|
-
const review = isRecord(data.review) ? data.review : void 0;
|
|
2024
|
-
if (canWrite && typeof review?.writePath === "string") {
|
|
2025
|
-
lines.push(`Write path: ${clipContext(review.writePath, 80)}`);
|
|
2026
|
-
}
|
|
2027
|
-
if (review?.humanReviewRequired === true) {
|
|
2028
|
-
lines.push("Human review is required before graph writes apply.");
|
|
2029
|
-
}
|
|
2030
|
-
for (const [field, label] of [["pendingProposalCount", "Pending proposals"], ["dueWorkflowCount", "Due workflows"]]) {
|
|
2031
|
-
const count = data[field];
|
|
2032
|
-
if (typeof count === "number" && Number.isSafeInteger(count) && count > 0) lines.push(`${label}: ${count}`);
|
|
2033
|
-
}
|
|
2034
|
-
const rules = isRecord(data.rules) ? data.rules : void 0;
|
|
2035
|
-
const items = Array.isArray(rules?.items) ? rules.items : [];
|
|
2036
|
-
const validRules = items.filter((rule) => isRecord(rule) && typeof rule.body === "string" && Boolean(rule.body.trim()));
|
|
2037
|
-
const responseCap = isRecord(data.responseCap) ? data.responseCap : void 0;
|
|
2038
|
-
if (!rules || !Array.isArray(rules.items) || validRules.length !== items.length || items.length > 3 || rules.truncated === true || Array.isArray(rules.omittedRules) && rules.omittedRules.length > 0 || responseCap?.applied === true) {
|
|
2039
|
-
lines.push("Rules or other context are incomplete; recover omitted content through brain_workspace_overview and exact reads.");
|
|
2040
|
-
}
|
|
2041
|
-
for (const rule of validRules.slice(0, 3)) {
|
|
2042
|
-
const body = rule.body.trim();
|
|
2043
|
-
lines.push(body.length > 280 ? `Rule excerpt (incomplete): ${clipContext(body, 281)}` : `Rule: ${body}`);
|
|
2044
|
-
}
|
|
2045
|
-
if (canWrite) {
|
|
2046
|
-
lines.push(typeof data.writeBackHint === "string" && data.writeBackHint.trim() ? data.writeBackHint.trim() : "During authorized project work, propose only new durable knowledge through available Brain tools. Honor read-only requests and workspace permissions.");
|
|
2047
|
-
}
|
|
2048
|
-
return lines.join("\n");
|
|
2049
|
-
}
|
|
2050
|
-
function loginOrientationMessage() {
|
|
2051
|
-
return "BrainMCP CLI is not signed in. No remote request was made. Host MCP access is independent: use the host brain_* tools to orient if connected. Run `brainmcp login` to enable companion orientation.";
|
|
2052
|
-
}
|
|
2053
|
-
function selectWorkspaceOrientationMessage() {
|
|
2054
|
-
return `Companion orientation has no resolved workspace. Continue through the host brain_* tools. ${WORKSPACE_INFERENCE_GUIDANCE}`;
|
|
2055
|
-
}
|
|
2056
|
-
function readProjectWorkspaceId(startDir) {
|
|
2057
|
-
if (!startDir) return { kind: "none" };
|
|
2058
|
-
let dir = path9.resolve(startDir);
|
|
2059
|
-
for (let depth = 0; depth < 16; depth += 1) {
|
|
2060
|
-
const configPath = path9.join(dir, ".brainmcp.json");
|
|
2061
|
-
if (fs9.existsSync(configPath)) {
|
|
2062
|
-
try {
|
|
2063
|
-
const stat = fs9.lstatSync(configPath);
|
|
2064
|
-
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 64 * 1024) {
|
|
2065
|
-
return { kind: "invalid", configPath };
|
|
2066
|
-
}
|
|
2067
|
-
const parsed = JSON.parse(fs9.readFileSync(configPath, "utf8"));
|
|
2068
|
-
const workspaceId = typeof parsed.workspaceId === "string" ? parsed.workspaceId.trim() : "";
|
|
2069
|
-
return UUID_RE2.test(workspaceId) ? { kind: "workspace", configPath, workspaceId } : { kind: "invalid", configPath };
|
|
2070
|
-
} catch {
|
|
2071
|
-
return { kind: "invalid", configPath };
|
|
2072
|
-
}
|
|
2073
|
-
}
|
|
2074
|
-
const parent = path9.dirname(dir);
|
|
2075
|
-
if (parent === dir) break;
|
|
2076
|
-
dir = parent;
|
|
2077
|
-
}
|
|
2078
|
-
return { kind: "none" };
|
|
2079
|
-
}
|
|
2080
|
-
function invalidProjectWorkspaceMessage() {
|
|
2081
|
-
return "BrainMCP found an invalid nearest `.brainmcp.json` workspaceId and did not guess another workspace. Fix or remove that project policy file.";
|
|
2082
|
-
}
|
|
2083
|
-
async function fetchSessionStartOrientation(input) {
|
|
2084
|
-
const initial = resolveOrientWorkspaceId(input.creds);
|
|
2085
|
-
if (initial.reason === "login") {
|
|
2086
|
-
return loginOrientationMessage();
|
|
2087
|
-
}
|
|
2088
|
-
const roots = (input.workspaceRoots?.length ? input.workspaceRoots : input.cwd ? [input.cwd] : []).filter((root, index, all) => Boolean(root) && all.indexOf(root) === index);
|
|
2089
|
-
const projectResolutions = roots.map((root) => readProjectWorkspaceId(root));
|
|
2090
|
-
if (projectResolutions.some((resolution) => resolution.kind === "invalid")) {
|
|
2091
|
-
return invalidProjectWorkspaceMessage();
|
|
2092
|
-
}
|
|
2093
|
-
const projectWorkspaceIds = projectResolutions.filter((resolution) => resolution.kind === "workspace").map((resolution) => resolution.workspaceId);
|
|
2094
|
-
const hasUnboundRoot = roots.length === 0 || projectResolutions.some((resolution) => resolution.kind === "none");
|
|
2095
|
-
let fallbackWorkspaceId = initial.workspaceId;
|
|
2096
|
-
if (hasUnboundRoot && !fallbackWorkspaceId) {
|
|
2097
|
-
try {
|
|
2098
|
-
const listed = await input.apiClient.request(
|
|
2099
|
-
COMPANION_WORKSPACES_PATH,
|
|
2100
|
-
{ timeoutMs: 800, signal: input.signal }
|
|
2101
|
-
);
|
|
2102
|
-
const next = resolveOrientWorkspaceId(input.creds, listed.workspaces ?? []);
|
|
2103
|
-
fallbackWorkspaceId = next.workspaceId;
|
|
2104
|
-
} catch {
|
|
2105
|
-
fallbackWorkspaceId = null;
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2108
|
-
const workspaceIds = [.../* @__PURE__ */ new Set([
|
|
2109
|
-
...projectWorkspaceIds,
|
|
2110
|
-
...hasUnboundRoot && fallbackWorkspaceId ? [fallbackWorkspaceId] : []
|
|
2111
|
-
])];
|
|
2112
|
-
if (workspaceIds.length === 0) return selectWorkspaceOrientationMessage();
|
|
2113
|
-
const results = await Promise.allSettled(
|
|
2114
|
-
workspaceIds.map(async (workspaceId) => {
|
|
2115
|
-
const payload = await input.apiClient.request(
|
|
2116
|
-
`/api/workspaces/${workspaceId}/orient`,
|
|
2117
|
-
{ timeoutMs: 800, signal: input.signal }
|
|
2118
|
-
);
|
|
2119
|
-
return formatOrientDetails(payload, workspaceId);
|
|
2120
|
-
})
|
|
2121
|
-
);
|
|
2122
|
-
const failedCount = results.filter((result) => result.status === "rejected").length;
|
|
2123
|
-
if (failedCount === results.length) {
|
|
2124
|
-
throw new Error("No project workspace orientation request succeeded.");
|
|
2125
|
-
}
|
|
2126
|
-
const header = [ORIENT_PACKET_HEADER];
|
|
2127
|
-
if (failedCount > 0) header.push(`${failedCount} workspace request(s) failed; their Brain context was not loaded. Retry those workspaces through host MCP; do not substitute another workspace.`);
|
|
2128
|
-
if (hasUnboundRoot && !fallbackWorkspaceId) header.push(selectWorkspaceOrientationMessage());
|
|
2129
|
-
const visibleResults = results.slice(0, 8);
|
|
2130
|
-
if (results.length > visibleResults.length) {
|
|
2131
|
-
header.push(`${results.length - visibleResults.length} additional workspace results omitted. Orient those projects separately through host MCP.`);
|
|
2132
|
-
}
|
|
2133
|
-
const prefix = header.join("\n");
|
|
2134
|
-
const separator = "\n\n---\n\n";
|
|
2135
|
-
const perWorkspaceBudget = Math.floor((ORIENT_CONTEXT_MAX_CHARS - prefix.length - 1 - separator.length * (visibleResults.length - 1)) / visibleResults.length);
|
|
2136
|
-
const contexts = visibleResults.map((result, index) => clipContext(
|
|
2137
|
-
result.status === "fulfilled" ? result.value : `Workspace ${workspaceIds[index]}: orientation unavailable. Call brain_workspace_overview with this workspaceId before dependent work.`,
|
|
2138
|
-
perWorkspaceBudget
|
|
2139
|
-
));
|
|
2140
|
-
return `${prefix}
|
|
2141
|
-
${contexts.join(separator)}`;
|
|
2142
|
-
}
|
|
2143
|
-
async function safeSessionStartOrientation(input) {
|
|
2144
|
-
if (!input.apiClient) {
|
|
2145
|
-
return input.creds?.authType === "oauth" ? selectWorkspaceOrientationMessage() : loginOrientationMessage();
|
|
2146
|
-
}
|
|
2147
|
-
try {
|
|
2148
|
-
return await fetchSessionStartOrientation(input);
|
|
2149
|
-
} catch (error) {
|
|
2150
|
-
logRuntimeEvent(
|
|
2151
|
-
"warn",
|
|
2152
|
-
"orient_fetch_failed",
|
|
2153
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
2154
|
-
input.baseDir
|
|
2155
|
-
);
|
|
2156
|
-
return "BrainMCP orientation is temporarily unavailable. Continue locally and retry brain_workspace_overview when possible.";
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
|
|
2160
|
-
// src/lib/api-client.ts
|
|
2161
|
-
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
2162
|
-
|
|
2163
1958
|
// src/lib/oauth-client.ts
|
|
2164
1959
|
function grantedCliScopes(requested, tokenScope) {
|
|
2165
1960
|
const allowed = new Set(BRAINMCP_CLI_ALLOWED_SCOPES);
|
|
@@ -2180,6 +1975,26 @@ function validateTokenResponse(value) {
|
|
|
2180
1975
|
}
|
|
2181
1976
|
return token;
|
|
2182
1977
|
}
|
|
1978
|
+
var DEFINITIVE_GRANT_ERRORS = /* @__PURE__ */ new Set(["invalid_grant", "invalid_client", "unauthorized_client"]);
|
|
1979
|
+
var OAuthGrantRejectedError = class extends Error {
|
|
1980
|
+
status;
|
|
1981
|
+
oauthError;
|
|
1982
|
+
constructor(status, oauthError) {
|
|
1983
|
+
super(`Token refresh rejected (status ${status}, ${oauthError}).`);
|
|
1984
|
+
this.name = "OAuthGrantRejectedError";
|
|
1985
|
+
this.status = status;
|
|
1986
|
+
this.oauthError = oauthError;
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
async function readOAuthErrorCode(res) {
|
|
1990
|
+
try {
|
|
1991
|
+
const body = await res.json();
|
|
1992
|
+
const code = body?.error;
|
|
1993
|
+
return typeof code === "string" && /^[a-z_]{1,64}$/.test(code) ? code : null;
|
|
1994
|
+
} catch {
|
|
1995
|
+
return null;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
2183
1998
|
var OAuthClient = class {
|
|
2184
1999
|
issuer;
|
|
2185
2000
|
clientId;
|
|
@@ -2280,6 +2095,10 @@ var OAuthClient = class {
|
|
|
2280
2095
|
body: body.toString()
|
|
2281
2096
|
});
|
|
2282
2097
|
if (!res.ok) {
|
|
2098
|
+
if (res.status === 400 || res.status === 401) {
|
|
2099
|
+
const code = await readOAuthErrorCode(res);
|
|
2100
|
+
if (code && DEFINITIVE_GRANT_ERRORS.has(code)) throw new OAuthGrantRejectedError(res.status, code);
|
|
2101
|
+
}
|
|
2283
2102
|
throw new Error(`Token refresh failed (status ${res.status}).`);
|
|
2284
2103
|
}
|
|
2285
2104
|
return validateTokenResponse(await res.json());
|
|
@@ -2307,6 +2126,14 @@ var OAuthClient = class {
|
|
|
2307
2126
|
};
|
|
2308
2127
|
|
|
2309
2128
|
// src/lib/api-client.ts
|
|
2129
|
+
var CompanionReauthRequiredError = class extends Error {
|
|
2130
|
+
status = 401;
|
|
2131
|
+
code = "reauth_required";
|
|
2132
|
+
constructor() {
|
|
2133
|
+
super("BrainMCP CLI sign-in expired or was revoked. Run `brainmcp login` to sign in again.");
|
|
2134
|
+
this.name = "CompanionReauthRequiredError";
|
|
2135
|
+
}
|
|
2136
|
+
};
|
|
2310
2137
|
var ApiClient = class {
|
|
2311
2138
|
apiUrl;
|
|
2312
2139
|
store;
|
|
@@ -2347,6 +2174,9 @@ var ApiClient = class {
|
|
|
2347
2174
|
if (options.expectedAuthorizationId && creds?.authorizationId !== options.expectedAuthorizationId) {
|
|
2348
2175
|
throw new Error("Companion authorization changed before the request.");
|
|
2349
2176
|
}
|
|
2177
|
+
if (creds?.authType === "oauth" && creds.reauthRequired) {
|
|
2178
|
+
throw new CompanionReauthRequiredError();
|
|
2179
|
+
}
|
|
2350
2180
|
const url = new URL(path12, `${this.apiUrl}/`);
|
|
2351
2181
|
if (url.origin !== new URL(this.apiUrl).origin || url.username || url.password) {
|
|
2352
2182
|
throw new Error("API requests must use the configured API origin.");
|
|
@@ -2446,13 +2276,12 @@ var ApiClient = class {
|
|
|
2446
2276
|
if (!refreshToken) return null;
|
|
2447
2277
|
try {
|
|
2448
2278
|
const endpoints = await this.oauthClient.discoverEndpoints(signal);
|
|
2279
|
+
signal.throwIfAborted();
|
|
2449
2280
|
const tokenResponse = await this.oauthClient.refreshAccessToken({
|
|
2450
2281
|
tokenEndpoint: endpoints.tokenEndpoint,
|
|
2451
|
-
refreshToken
|
|
2452
|
-
signal
|
|
2282
|
+
refreshToken
|
|
2453
2283
|
});
|
|
2454
2284
|
return await this.store.withRefreshLock(async (current) => {
|
|
2455
|
-
signal.throwIfAborted();
|
|
2456
2285
|
if (!current || current.authType !== "oauth" || current.authorizationId !== original.authorizationId || current.userId !== original.userId) return null;
|
|
2457
2286
|
if (current.refreshLease?.leaseHolder !== leaseHolder) {
|
|
2458
2287
|
return current.accessToken !== failedAccessToken ? current : null;
|
|
@@ -2477,20 +2306,274 @@ var ApiClient = class {
|
|
|
2477
2306
|
return updated;
|
|
2478
2307
|
});
|
|
2479
2308
|
} catch (error) {
|
|
2309
|
+
const rejection = error instanceof OAuthGrantRejectedError ? error : null;
|
|
2480
2310
|
await this.store.withRefreshLock(async (current) => {
|
|
2481
2311
|
if (current?.authType === "oauth" && current.refreshLease?.leaseHolder === leaseHolder) {
|
|
2482
2312
|
await this.store.set({
|
|
2483
2313
|
...current,
|
|
2484
2314
|
refreshLease: void 0,
|
|
2315
|
+
// Mark the grant dead only if no other process rotated it meanwhile.
|
|
2316
|
+
...rejection && current.refreshToken === refreshToken ? { reauthRequired: { reason: "refresh_rejected", oauthError: rejection.oauthError, detectedAt: (/* @__PURE__ */ new Date()).toISOString() } } : {},
|
|
2485
2317
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2486
2318
|
});
|
|
2487
2319
|
}
|
|
2488
2320
|
});
|
|
2489
|
-
throw error;
|
|
2321
|
+
throw rejection ? new CompanionReauthRequiredError() : error;
|
|
2490
2322
|
}
|
|
2491
2323
|
}
|
|
2492
2324
|
};
|
|
2493
2325
|
|
|
2326
|
+
// src/runtime/orient.ts
|
|
2327
|
+
var ORIENT_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
2328
|
+
var ORIENT_CONTEXT_MAX_CHARS = 2400;
|
|
2329
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2330
|
+
var SESSION_START_EVENTS = /* @__PURE__ */ new Set([
|
|
2331
|
+
"SessionStart",
|
|
2332
|
+
"sessionStart",
|
|
2333
|
+
"session_start",
|
|
2334
|
+
"startup"
|
|
2335
|
+
]);
|
|
2336
|
+
function isSessionStartEvent(event) {
|
|
2337
|
+
return SESSION_START_EVENTS.has(event);
|
|
2338
|
+
}
|
|
2339
|
+
function isUserPromptEvent(event) {
|
|
2340
|
+
return event === "UserPromptSubmit" || event === "UserPrompt" || event === "prompt" || event === "beforeSubmitPrompt";
|
|
2341
|
+
}
|
|
2342
|
+
function resolveOrientWorkspaceId(creds, listed) {
|
|
2343
|
+
if (!creds || creds.authType !== "oauth" || !creds.accessToken) {
|
|
2344
|
+
return { workspaceId: null, reason: "login" };
|
|
2345
|
+
}
|
|
2346
|
+
if (creds.defaultWorkspaceId && UUID_RE2.test(creds.defaultWorkspaceId)) {
|
|
2347
|
+
return { workspaceId: creds.defaultWorkspaceId, reason: "ok" };
|
|
2348
|
+
}
|
|
2349
|
+
const fromCreds = (creds.workspaces ?? []).filter((id) => UUID_RE2.test(id));
|
|
2350
|
+
if (fromCreds.length === 1) {
|
|
2351
|
+
return { workspaceId: fromCreds[0], reason: "ok" };
|
|
2352
|
+
}
|
|
2353
|
+
if (listed) {
|
|
2354
|
+
const defaults = listed.filter((ws) => ws.isDefault);
|
|
2355
|
+
if (defaults.length === 1 && UUID_RE2.test(defaults[0].id)) {
|
|
2356
|
+
return { workspaceId: defaults[0].id, reason: "ok" };
|
|
2357
|
+
}
|
|
2358
|
+
if (listed.length === 1 && UUID_RE2.test(listed[0].id)) {
|
|
2359
|
+
return { workspaceId: listed[0].id, reason: "ok" };
|
|
2360
|
+
}
|
|
2361
|
+
if (listed.length !== 1) {
|
|
2362
|
+
return { workspaceId: null, reason: "select" };
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
if (fromCreds.length !== 1) {
|
|
2366
|
+
return { workspaceId: null, reason: fromCreds.length === 0 ? "select" : "select" };
|
|
2367
|
+
}
|
|
2368
|
+
return { workspaceId: null, reason: "select" };
|
|
2369
|
+
}
|
|
2370
|
+
var ORIENT_PACKET_HEADER = [
|
|
2371
|
+
"BrainMCP orientation (no user prompt was sent).",
|
|
2372
|
+
ANSWER_GROUNDING_BRIEF_GUIDANCE,
|
|
2373
|
+
"This hook packet is bounded; call brain_workspace_overview for full Rules and current project context before dependent work. Clipped or omitted workspace details are incomplete."
|
|
2374
|
+
].join("\n");
|
|
2375
|
+
function isRecord(value) {
|
|
2376
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2377
|
+
}
|
|
2378
|
+
function clipContext(text, maxChars) {
|
|
2379
|
+
if (text.length <= maxChars) return text;
|
|
2380
|
+
return `${text.slice(0, maxChars - 1).replace(/[\uD800-\uDBFF]$/, "")}\u2026`;
|
|
2381
|
+
}
|
|
2382
|
+
function formatOrientDetails(payload, expectedWorkspaceId) {
|
|
2383
|
+
const workspace = isRecord(payload) && isRecord(payload.workspace) ? payload.workspace : void 0;
|
|
2384
|
+
if (!workspace || typeof workspace.id !== "string" || !workspace.id.trim() || typeof workspace.name !== "string" || !workspace.name.trim() || expectedWorkspaceId && workspace.id !== expectedWorkspaceId) {
|
|
2385
|
+
return `${expectedWorkspaceId ? `Workspace ${expectedWorkspaceId}: ` : ""}BrainMCP orientation returned no usable context. Call brain_workspace_overview for this workspace before dependent work.`;
|
|
2386
|
+
}
|
|
2387
|
+
const data = payload;
|
|
2388
|
+
const lines = [`Workspace ${clipContext(workspace.id, 80)}: ${clipContext(workspace.name.trim(), 120)}`];
|
|
2389
|
+
const activeRef = isRecord(data.activeRef) ? data.activeRef : void 0;
|
|
2390
|
+
if (activeRef?.type === "live") lines.push("Active ref: live.");
|
|
2391
|
+
if (activeRef?.type === "branch" && typeof activeRef.branchId === "string") {
|
|
2392
|
+
lines.push(`Active ref: branch ${clipContext(activeRef.branchId, 80)}.`);
|
|
2393
|
+
}
|
|
2394
|
+
const authorization = isRecord(data.authorization) ? data.authorization : void 0;
|
|
2395
|
+
const scopes = Array.isArray(authorization?.scopes) && authorization.scopes.every((scope) => typeof scope === "string") ? authorization.scopes : void 0;
|
|
2396
|
+
const canWrite = scopes?.some((scope) => scope === "*" || scope === "changes:write") === true;
|
|
2397
|
+
if (!canWrite) {
|
|
2398
|
+
lines.push(scopes ? "Companion authorization lacks changes:write. Host MCP permissions are independent; check its overview before proposing changes." : "Companion write access is unknown. Check host MCP permissions in overview before proposing changes.");
|
|
2399
|
+
}
|
|
2400
|
+
const review = isRecord(data.review) ? data.review : void 0;
|
|
2401
|
+
if (canWrite && typeof review?.writePath === "string") {
|
|
2402
|
+
lines.push(`Write path: ${clipContext(review.writePath, 80)}`);
|
|
2403
|
+
}
|
|
2404
|
+
if (review?.humanReviewRequired === true) {
|
|
2405
|
+
lines.push("Human review is required before graph writes apply.");
|
|
2406
|
+
}
|
|
2407
|
+
for (const [field, label] of [["pendingProposalCount", "Pending proposals"], ["dueWorkflowCount", "Due workflows"]]) {
|
|
2408
|
+
const count = data[field];
|
|
2409
|
+
if (typeof count === "number" && Number.isSafeInteger(count) && count > 0) lines.push(`${label}: ${count}`);
|
|
2410
|
+
}
|
|
2411
|
+
const rules = isRecord(data.rules) ? data.rules : void 0;
|
|
2412
|
+
const items = Array.isArray(rules?.items) ? rules.items : [];
|
|
2413
|
+
const validRules = items.filter((rule) => isRecord(rule) && typeof rule.body === "string" && Boolean(rule.body.trim()));
|
|
2414
|
+
const responseCap = isRecord(data.responseCap) ? data.responseCap : void 0;
|
|
2415
|
+
if (!rules || !Array.isArray(rules.items) || validRules.length !== items.length || items.length > 3 || rules.truncated === true || Array.isArray(rules.omittedRules) && rules.omittedRules.length > 0 || responseCap?.applied === true) {
|
|
2416
|
+
lines.push("Rules or other context are incomplete; recover omitted content through brain_workspace_overview and exact reads.");
|
|
2417
|
+
}
|
|
2418
|
+
for (const rule of validRules.slice(0, 3)) {
|
|
2419
|
+
const body = rule.body.trim();
|
|
2420
|
+
lines.push(body.length > 280 ? `Rule excerpt (incomplete): ${clipContext(body, 281)}` : `Rule: ${body}`);
|
|
2421
|
+
}
|
|
2422
|
+
if (canWrite) {
|
|
2423
|
+
lines.push(typeof data.writeBackHint === "string" && data.writeBackHint.trim() ? data.writeBackHint.trim() : "During authorized project work, propose only new durable knowledge through available Brain tools. Honor read-only requests and workspace permissions.");
|
|
2424
|
+
}
|
|
2425
|
+
return lines.join("\n");
|
|
2426
|
+
}
|
|
2427
|
+
function loginOrientationMessage() {
|
|
2428
|
+
return "BrainMCP CLI is not signed in. No remote request was made. Host MCP access is independent: use the host brain_* tools to orient if connected. Run `brainmcp login` to enable companion orientation.";
|
|
2429
|
+
}
|
|
2430
|
+
function reauthOrientationMessage() {
|
|
2431
|
+
return "BrainMCP CLI sign-in expired or was revoked, so companion orientation is off. Only the brainmcp hook is affected: host MCP access is independent, so orient through the host brain_* tools (brain_workspace_overview) before saying Brain is unavailable. Tell the user to run `brainmcp login` to restore companion orientation.";
|
|
2432
|
+
}
|
|
2433
|
+
function companionOrientationFailedMessage(kinds) {
|
|
2434
|
+
const reasons = [...new Set(kinds)].join(", ");
|
|
2435
|
+
return `BrainMCP companion orientation failed (${reasons}). Only the brainmcp hook is affected: host MCP access is independent, so orient through the host brain_* tools (brain_workspace_overview) before saying Brain is unavailable.`;
|
|
2436
|
+
}
|
|
2437
|
+
function classifyOrientFailure(error) {
|
|
2438
|
+
if (error instanceof CompanionReauthRequiredError) return { kind: "reauth_required", status: 401 };
|
|
2439
|
+
const status = error && typeof error === "object" && "status" in error && typeof error.status === "number" ? error.status : void 0;
|
|
2440
|
+
if (status === 401) return { kind: "unauthorized", status };
|
|
2441
|
+
if (status === 403) return { kind: "forbidden", status };
|
|
2442
|
+
if (status !== void 0) return { kind: `http_${status}`, status };
|
|
2443
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2444
|
+
if (/timed out|cancelled/i.test(message)) return { kind: "timeout" };
|
|
2445
|
+
return { kind: "network" };
|
|
2446
|
+
}
|
|
2447
|
+
function needsLogin(failure) {
|
|
2448
|
+
return failure.kind === "reauth_required" || failure.kind === "unauthorized";
|
|
2449
|
+
}
|
|
2450
|
+
var OrientRequestsFailedError = class extends Error {
|
|
2451
|
+
failures;
|
|
2452
|
+
constructor(failures) {
|
|
2453
|
+
super("No project workspace orientation request succeeded.");
|
|
2454
|
+
this.name = "OrientRequestsFailedError";
|
|
2455
|
+
this.failures = failures;
|
|
2456
|
+
}
|
|
2457
|
+
};
|
|
2458
|
+
function selectWorkspaceOrientationMessage() {
|
|
2459
|
+
return `Companion orientation has no resolved workspace. Continue through the host brain_* tools. ${WORKSPACE_INFERENCE_GUIDANCE}`;
|
|
2460
|
+
}
|
|
2461
|
+
function readProjectWorkspaceId(startDir) {
|
|
2462
|
+
if (!startDir) return { kind: "none" };
|
|
2463
|
+
let dir = path9.resolve(startDir);
|
|
2464
|
+
for (let depth = 0; depth < 16; depth += 1) {
|
|
2465
|
+
const configPath = path9.join(dir, ".brainmcp.json");
|
|
2466
|
+
if (fs9.existsSync(configPath)) {
|
|
2467
|
+
try {
|
|
2468
|
+
const stat = fs9.lstatSync(configPath);
|
|
2469
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 64 * 1024) {
|
|
2470
|
+
return { kind: "invalid", configPath };
|
|
2471
|
+
}
|
|
2472
|
+
const parsed = JSON.parse(fs9.readFileSync(configPath, "utf8"));
|
|
2473
|
+
const workspaceId = typeof parsed.workspaceId === "string" ? parsed.workspaceId.trim() : "";
|
|
2474
|
+
return UUID_RE2.test(workspaceId) ? { kind: "workspace", configPath, workspaceId } : { kind: "invalid", configPath };
|
|
2475
|
+
} catch {
|
|
2476
|
+
return { kind: "invalid", configPath };
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
const parent = path9.dirname(dir);
|
|
2480
|
+
if (parent === dir) break;
|
|
2481
|
+
dir = parent;
|
|
2482
|
+
}
|
|
2483
|
+
return { kind: "none" };
|
|
2484
|
+
}
|
|
2485
|
+
function invalidProjectWorkspaceMessage() {
|
|
2486
|
+
return "BrainMCP found an invalid nearest `.brainmcp.json` workspaceId and did not guess another workspace. Fix or remove that project policy file.";
|
|
2487
|
+
}
|
|
2488
|
+
async function fetchSessionStartOrientation(input) {
|
|
2489
|
+
const initial = resolveOrientWorkspaceId(input.creds);
|
|
2490
|
+
if (initial.reason === "login") {
|
|
2491
|
+
return loginOrientationMessage();
|
|
2492
|
+
}
|
|
2493
|
+
if (input.creds?.authType === "oauth" && input.creds.reauthRequired) {
|
|
2494
|
+
return reauthOrientationMessage();
|
|
2495
|
+
}
|
|
2496
|
+
const roots = (input.workspaceRoots?.length ? input.workspaceRoots : input.cwd ? [input.cwd] : []).filter((root, index, all) => Boolean(root) && all.indexOf(root) === index);
|
|
2497
|
+
const projectResolutions = roots.map((root) => readProjectWorkspaceId(root));
|
|
2498
|
+
if (projectResolutions.some((resolution) => resolution.kind === "invalid")) {
|
|
2499
|
+
return invalidProjectWorkspaceMessage();
|
|
2500
|
+
}
|
|
2501
|
+
const projectWorkspaceIds = projectResolutions.filter((resolution) => resolution.kind === "workspace").map((resolution) => resolution.workspaceId);
|
|
2502
|
+
const hasUnboundRoot = roots.length === 0 || projectResolutions.some((resolution) => resolution.kind === "none");
|
|
2503
|
+
let fallbackWorkspaceId = initial.workspaceId;
|
|
2504
|
+
if (hasUnboundRoot && !fallbackWorkspaceId) {
|
|
2505
|
+
try {
|
|
2506
|
+
const listed = await input.apiClient.request(
|
|
2507
|
+
COMPANION_WORKSPACES_PATH,
|
|
2508
|
+
{ timeoutMs: 800, signal: input.signal }
|
|
2509
|
+
);
|
|
2510
|
+
const next = resolveOrientWorkspaceId(input.creds, listed.workspaces ?? []);
|
|
2511
|
+
fallbackWorkspaceId = next.workspaceId;
|
|
2512
|
+
} catch (error) {
|
|
2513
|
+
const failure = classifyOrientFailure(error);
|
|
2514
|
+
if (needsLogin(failure)) throw new OrientRequestsFailedError([failure]);
|
|
2515
|
+
fallbackWorkspaceId = null;
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
const workspaceIds = [.../* @__PURE__ */ new Set([
|
|
2519
|
+
...projectWorkspaceIds,
|
|
2520
|
+
...hasUnboundRoot && fallbackWorkspaceId ? [fallbackWorkspaceId] : []
|
|
2521
|
+
])];
|
|
2522
|
+
if (workspaceIds.length === 0) return selectWorkspaceOrientationMessage();
|
|
2523
|
+
const results = await Promise.allSettled(
|
|
2524
|
+
workspaceIds.map(async (workspaceId) => {
|
|
2525
|
+
const payload = await input.apiClient.request(
|
|
2526
|
+
`/api/workspaces/${apiPathSegment(workspaceId)}/orient`,
|
|
2527
|
+
{ timeoutMs: 800, signal: input.signal }
|
|
2528
|
+
);
|
|
2529
|
+
return formatOrientDetails(payload, workspaceId);
|
|
2530
|
+
})
|
|
2531
|
+
);
|
|
2532
|
+
const failures = results.map((result) => result.status === "rejected" ? classifyOrientFailure(result.reason) : null);
|
|
2533
|
+
const failedCount = failures.filter(Boolean).length;
|
|
2534
|
+
if (failedCount === results.length) {
|
|
2535
|
+
throw new OrientRequestsFailedError(failures);
|
|
2536
|
+
}
|
|
2537
|
+
if (failedCount > 0) {
|
|
2538
|
+
logRuntimeEvent("warn", "orient_partial_failure", {
|
|
2539
|
+
failures: failures.filter((failure) => failure !== null)
|
|
2540
|
+
}, input.baseDir);
|
|
2541
|
+
}
|
|
2542
|
+
const header = [ORIENT_PACKET_HEADER];
|
|
2543
|
+
if (failedCount > 0) header.push(`${failedCount} workspace request(s) failed; their Brain context was not loaded. Retry those workspaces through host MCP; do not substitute another workspace.`);
|
|
2544
|
+
if (hasUnboundRoot && !fallbackWorkspaceId) header.push(selectWorkspaceOrientationMessage());
|
|
2545
|
+
const visibleResults = results.slice(0, 8);
|
|
2546
|
+
if (results.length > visibleResults.length) {
|
|
2547
|
+
header.push(`${results.length - visibleResults.length} additional workspace results omitted. Orient those projects separately through host MCP.`);
|
|
2548
|
+
}
|
|
2549
|
+
const prefix = header.join("\n");
|
|
2550
|
+
const separator = "\n\n---\n\n";
|
|
2551
|
+
const perWorkspaceBudget = Math.floor((ORIENT_CONTEXT_MAX_CHARS - prefix.length - 1 - separator.length * (visibleResults.length - 1)) / visibleResults.length);
|
|
2552
|
+
const contexts = visibleResults.map((result, index) => clipContext(
|
|
2553
|
+
result.status === "fulfilled" ? result.value : `Workspace ${workspaceIds[index]}: orientation unavailable (${failures[index]?.kind ?? "network"}). Call brain_workspace_overview with this workspaceId before dependent work.`,
|
|
2554
|
+
perWorkspaceBudget
|
|
2555
|
+
));
|
|
2556
|
+
return `${prefix}
|
|
2557
|
+
${contexts.join(separator)}`;
|
|
2558
|
+
}
|
|
2559
|
+
async function safeSessionStartOrientation(input) {
|
|
2560
|
+
if (!input.apiClient) {
|
|
2561
|
+
return input.creds?.authType === "oauth" ? selectWorkspaceOrientationMessage() : loginOrientationMessage();
|
|
2562
|
+
}
|
|
2563
|
+
try {
|
|
2564
|
+
return await fetchSessionStartOrientation(input);
|
|
2565
|
+
} catch (error) {
|
|
2566
|
+
const failures = error instanceof OrientRequestsFailedError ? error.failures : [classifyOrientFailure(error)];
|
|
2567
|
+
logRuntimeEvent(
|
|
2568
|
+
"warn",
|
|
2569
|
+
"orient_fetch_failed",
|
|
2570
|
+
{ error: error instanceof Error ? error.message : String(error), failures },
|
|
2571
|
+
input.baseDir
|
|
2572
|
+
);
|
|
2573
|
+
return failures.some(needsLogin) ? reauthOrientationMessage() : companionOrientationFailedMessage(failures.map((failure) => failure.kind));
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2494
2577
|
// src/lib/credentials.ts
|
|
2495
2578
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2496
2579
|
import {
|