@burtson-labs/host-kit 0.3.1

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.
Files changed (79) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +55 -0
  3. package/dist/backgroundTasks.d.ts +113 -0
  4. package/dist/backgroundTasks.d.ts.map +1 -0
  5. package/dist/backgroundTasks.js +137 -0
  6. package/dist/backgroundTasks.js.map +1 -0
  7. package/dist/checkpoints.d.ts +99 -0
  8. package/dist/checkpoints.d.ts.map +1 -0
  9. package/dist/checkpoints.js +227 -0
  10. package/dist/checkpoints.js.map +1 -0
  11. package/dist/hooks.d.ts +51 -0
  12. package/dist/hooks.d.ts.map +1 -0
  13. package/dist/hooks.js +152 -0
  14. package/dist/hooks.js.map +1 -0
  15. package/dist/index.d.ts +19 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +95 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/insights.d.ts +398 -0
  20. package/dist/insights.d.ts.map +1 -0
  21. package/dist/insights.js +1933 -0
  22. package/dist/insights.js.map +1 -0
  23. package/dist/mcp.d.ts +60 -0
  24. package/dist/mcp.d.ts.map +1 -0
  25. package/dist/mcp.js +281 -0
  26. package/dist/mcp.js.map +1 -0
  27. package/dist/mcpConnectors.d.ts +108 -0
  28. package/dist/mcpConnectors.d.ts.map +1 -0
  29. package/dist/mcpConnectors.js +217 -0
  30. package/dist/mcpConnectors.js.map +1 -0
  31. package/dist/mcpToolCache.d.ts +43 -0
  32. package/dist/mcpToolCache.d.ts.map +1 -0
  33. package/dist/mcpToolCache.js +150 -0
  34. package/dist/mcpToolCache.js.map +1 -0
  35. package/dist/mcpTrust.d.ts +22 -0
  36. package/dist/mcpTrust.d.ts.map +1 -0
  37. package/dist/mcpTrust.js +104 -0
  38. package/dist/mcpTrust.js.map +1 -0
  39. package/dist/memory.d.ts +38 -0
  40. package/dist/memory.d.ts.map +1 -0
  41. package/dist/memory.js +151 -0
  42. package/dist/memory.js.map +1 -0
  43. package/dist/memoryIndex.d.ts +38 -0
  44. package/dist/memoryIndex.d.ts.map +1 -0
  45. package/dist/memoryIndex.js +142 -0
  46. package/dist/memoryIndex.js.map +1 -0
  47. package/dist/mentions.d.ts +33 -0
  48. package/dist/mentions.d.ts.map +1 -0
  49. package/dist/mentions.js +126 -0
  50. package/dist/mentions.js.map +1 -0
  51. package/dist/ollamaModels.d.ts +36 -0
  52. package/dist/ollamaModels.d.ts.map +1 -0
  53. package/dist/ollamaModels.js +83 -0
  54. package/dist/ollamaModels.js.map +1 -0
  55. package/dist/permissions.d.ts +72 -0
  56. package/dist/permissions.d.ts.map +1 -0
  57. package/dist/permissions.js +271 -0
  58. package/dist/permissions.js.map +1 -0
  59. package/dist/tools/extraTools.d.ts +80 -0
  60. package/dist/tools/extraTools.d.ts.map +1 -0
  61. package/dist/tools/extraTools.js +471 -0
  62. package/dist/tools/extraTools.js.map +1 -0
  63. package/dist/tools/readMemoryTool.d.ts +3 -0
  64. package/dist/tools/readMemoryTool.d.ts.map +1 -0
  65. package/dist/tools/readMemoryTool.js +115 -0
  66. package/dist/tools/readMemoryTool.js.map +1 -0
  67. package/dist/tools/taskTool.d.ts +119 -0
  68. package/dist/tools/taskTool.d.ts.map +1 -0
  69. package/dist/tools/taskTool.js +466 -0
  70. package/dist/tools/taskTool.js.map +1 -0
  71. package/dist/tools/testRunTool.d.ts +59 -0
  72. package/dist/tools/testRunTool.d.ts.map +1 -0
  73. package/dist/tools/testRunTool.js +308 -0
  74. package/dist/tools/testRunTool.js.map +1 -0
  75. package/dist/turnLog.d.ts +89 -0
  76. package/dist/turnLog.d.ts.map +1 -0
  77. package/dist/turnLog.js +469 -0
  78. package/dist/turnLog.js.map +1 -0
  79. package/package.json +35 -0
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ /**
3
+ * Connector wizards — convenience helpers that turn a single user
4
+ * input (a token, a credential, etc.) into a fully-formed McpServerConfig
5
+ * for a well-known provider's official MCP server. Each wizard is a
6
+ * small, single-purpose function; the surfaces (CLI slash command,
7
+ * extension Connections panel) call into these to avoid duplicating
8
+ * the spawn-command shape across surfaces.
9
+ *
10
+ * Phase 3 starts with GitHub — it's the simplest viable wizard
11
+ * (single PAT, no OAuth callback). Slack / Google / Microsoft follow
12
+ * as they each ship.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.buildGitHubServerConfig = buildGitHubServerConfig;
16
+ exports.looksLikeGitHubToken = looksLikeGitHubToken;
17
+ exports.buildSlackServerConfig = buildSlackServerConfig;
18
+ exports.looksLikeSlackToken = looksLikeSlackToken;
19
+ exports.looksLikeSlackTeamId = looksLikeSlackTeamId;
20
+ exports.buildGitLabServerConfig = buildGitLabServerConfig;
21
+ exports.looksLikeGitLabToken = looksLikeGitLabToken;
22
+ exports.buildGmailServerConfig = buildGmailServerConfig;
23
+ exports.looksLikeGmailCredentialsPath = looksLikeGmailCredentialsPath;
24
+ exports.buildCustomServerConfig = buildCustomServerConfig;
25
+ /**
26
+ * Build a server config that runs `@modelcontextprotocol/server-github`
27
+ * via npx with the user's PAT. The token never lands in the config
28
+ * file's `args` (those are sometimes logged by editors); it goes into
29
+ * the env block which Bandit explicitly excludes from the trust
30
+ * fingerprint and from any UI surfaces that echo configs back.
31
+ *
32
+ * Activation defaults to "on-mention" with the standard github
33
+ * triggers so the GitHub server's tools only land in the prompt
34
+ * budget when the user actually mentions GitHub-y things.
35
+ */
36
+ function buildGitHubServerConfig(token) {
37
+ const trimmed = token.trim();
38
+ if (!trimmed)
39
+ throw new Error('GitHub PAT is required');
40
+ return {
41
+ command: 'npx',
42
+ args: ['-y', '@modelcontextprotocol/server-github'],
43
+ env: { GITHUB_PERSONAL_ACCESS_TOKEN: trimmed },
44
+ activation: 'on-mention'
45
+ };
46
+ }
47
+ /**
48
+ * Reasonable token-shape sanity check. GitHub PATs come in three
49
+ * flavors: classic (`ghp_…`, ~40 chars), fine-grained (`github_pat_…`,
50
+ * ~93 chars), and OAuth (`gho_…`). All start with a known prefix.
51
+ * We're not validating against the API here — just catching the
52
+ * fat-finger "I pasted my SSH key" failure mode before the user
53
+ * gets a confusing 401 from the server.
54
+ */
55
+ function looksLikeGitHubToken(token) {
56
+ const t = token.trim();
57
+ return /^(ghp_|gho_|ghs_|ghu_|github_pat_)/.test(t);
58
+ }
59
+ /**
60
+ * Build a server config that runs `@modelcontextprotocol/server-slack`
61
+ * via npx. Slack's MCP server requires two env vars: a Bot User OAuth
62
+ * Token (`xoxb-…`) and the workspace's Team ID (`T…`). We ship the
63
+ * wizard with `activation: 'on-mention'` so Slack tools only land in
64
+ * the prompt budget when the user actually mentions slack/channel/
65
+ * message — the standard auto-derived triggers from activation.ts.
66
+ */
67
+ function buildSlackServerConfig(botToken, teamId) {
68
+ const tk = botToken.trim();
69
+ const team = teamId.trim();
70
+ if (!tk)
71
+ throw new Error('Slack bot token (xoxb-…) is required');
72
+ if (!team)
73
+ throw new Error('Slack team ID (T…) is required');
74
+ return {
75
+ command: 'npx',
76
+ args: ['-y', '@modelcontextprotocol/server-slack'],
77
+ env: { SLACK_BOT_TOKEN: tk, SLACK_TEAM_ID: team },
78
+ activation: 'on-mention'
79
+ };
80
+ }
81
+ /** Slack Bot User OAuth tokens always start with "xoxb-". User tokens
82
+ * are "xoxp-"; we deliberately accept both since the MCP server
83
+ * works with either, but the docs recommend bot tokens. */
84
+ function looksLikeSlackToken(token) {
85
+ return /^xox[bp]-/.test(token.trim());
86
+ }
87
+ /** Slack workspace IDs start with "T" followed by alphanumerics. We
88
+ * accept any non-empty string starting with T to allow for future
89
+ * changes in Slack's ID format. */
90
+ function looksLikeSlackTeamId(teamId) {
91
+ return /^T[A-Z0-9]+$/i.test(teamId.trim());
92
+ }
93
+ /**
94
+ * Build a server config that runs `@modelcontextprotocol/server-gitlab`
95
+ * via npx. Defaults to GitLab.com's API; users with self-hosted
96
+ * GitLab can pass the API base URL through GITLAB_API_URL.
97
+ */
98
+ function buildGitLabServerConfig(token, apiUrl) {
99
+ const trimmed = token.trim();
100
+ if (!trimmed)
101
+ throw new Error('GitLab personal access token is required');
102
+ const env = {
103
+ GITLAB_PERSONAL_ACCESS_TOKEN: trimmed
104
+ };
105
+ const trimmedUrl = (apiUrl ?? '').trim();
106
+ if (trimmedUrl)
107
+ env.GITLAB_API_URL = trimmedUrl;
108
+ return {
109
+ command: 'npx',
110
+ args: ['-y', '@modelcontextprotocol/server-gitlab'],
111
+ env,
112
+ activation: 'on-mention'
113
+ };
114
+ }
115
+ /** GitLab PATs are typically 20 chars of base64-ish content with a
116
+ * `glpat-` prefix on newer tokens (since GitLab 14.5). We accept
117
+ * any non-empty string ≥ 20 chars to support older tokens too. */
118
+ function looksLikeGitLabToken(token) {
119
+ const t = token.trim();
120
+ if (t.startsWith('glpat-'))
121
+ return true;
122
+ return t.length >= 20 && /^[A-Za-z0-9_-]+$/.test(t);
123
+ }
124
+ /**
125
+ * Build a server config that runs `@gongrzhe/server-gmail-autoauth-mcp`
126
+ * via npx with the user's downloaded Google Cloud OAuth credentials.
127
+ * the first Phase 3 Google-flavor wizard, closing the gap
128
+ * memo'd in the 2026-04-29 MCP roadmap (Office 365 / Google / Slack
129
+ * / GitHub all named as Phase 3 targets; GitHub + Slack + GitLab
130
+ * shipped, Google was the last hold-out).
131
+ *
132
+ * Why this server: it's the most-cited community Gmail MCP server,
133
+ * speaks the standard stdio MCP shape, and handles the OAuth dance
134
+ * (browser popup → save refresh token) automatically on first spawn.
135
+ * Anthropic doesn't ship a `server-gmail` from the official MCP repo,
136
+ * so picking a community implementation is unavoidable — gongrzhe is
137
+ * well-maintained as of this writing.
138
+ *
139
+ * Setup the user has to do first (we can't):
140
+ * 1. Create an OAuth 2.0 client in https://console.cloud.google.com/
141
+ * Type: Desktop app. Enable the Gmail API on the project first.
142
+ * 2. Download the credentials JSON (the "OAuth client" download).
143
+ * 3. Pass that file path to this wizard.
144
+ *
145
+ * The first Bandit turn that touches Gmail will open a browser for the
146
+ * Google consent screen. After that the server caches a refresh token
147
+ * to `~/.gmail-mcp/credentials.json` and runs unattended.
148
+ */
149
+ function buildGmailServerConfig(credentialsPath) {
150
+ const trimmed = credentialsPath.trim();
151
+ if (!trimmed)
152
+ throw new Error('Path to Google OAuth credentials JSON is required');
153
+ return {
154
+ command: 'npx',
155
+ args: ['-y', '@gongrzhe/server-gmail-autoauth-mcp'],
156
+ env: {
157
+ // The gongrzhe server reads GMAIL_OAUTH_PATH if set, otherwise
158
+ // defaults to ~/.gmail-mcp/gcp-oauth.keys.json. Pinning the env
159
+ // var so the wizard doesn't depend on the user pre-creating
160
+ // that directory or copying the credentials there manually.
161
+ GMAIL_OAUTH_PATH: trimmed
162
+ },
163
+ activation: 'on-mention'
164
+ };
165
+ }
166
+ /** Light shape check: the user pointed at a path that looks like a
167
+ * Google OAuth credentials JSON. We don't open the file here (host-
168
+ * kit stays filesystem-agnostic for testability); the wizard layer
169
+ * does the actual fs check before calling this. */
170
+ function looksLikeGmailCredentialsPath(p) {
171
+ const t = p.trim();
172
+ if (!t)
173
+ return false;
174
+ // Must look like a real path AND end in .json. Reject obvious garbage
175
+ // (URLs, single words) so users don't paste a token by mistake.
176
+ if (!/\.json$/i.test(t))
177
+ return false;
178
+ return t.includes('/') || t.includes('\\') || t.startsWith('~');
179
+ }
180
+ /**
181
+ * Build a fully-custom server config from raw inputs. Used by the
182
+ * "+ Custom" wizard tile so users can register any MCP server (Linear,
183
+ * Jira, Bitbucket, Sentry, Postgres, an internal one they wrote) without
184
+ * waiting for Bandit to ship a dedicated wizard for that provider.
185
+ *
186
+ * `envInput` accepts the standard `KEY=VALUE` shape one-per-line, the
187
+ * format every CLI / dotfile uses, so users can paste from a `.env`.
188
+ */
189
+ function buildCustomServerConfig(params) {
190
+ const cmd = params.command.trim();
191
+ if (!cmd)
192
+ throw new Error('Command is required');
193
+ const env = {};
194
+ if (params.envInput) {
195
+ for (const rawLine of params.envInput.split(/\r?\n/)) {
196
+ const line = rawLine.trim();
197
+ if (!line || line.startsWith('#'))
198
+ continue;
199
+ const eq = line.indexOf('=');
200
+ if (eq <= 0)
201
+ continue; // require a non-empty key before =
202
+ const key = line.slice(0, eq).trim();
203
+ const value = line.slice(eq + 1).trim();
204
+ // Strip surrounding quotes (matches dotenv loader semantics) so
205
+ // copy-paste from a .env file Just Works™.
206
+ const unquoted = value.replace(/^["']|["']$/g, '');
207
+ env[key] = unquoted;
208
+ }
209
+ }
210
+ return {
211
+ command: cmd,
212
+ args: params.args && params.args.length > 0 ? params.args : undefined,
213
+ env: Object.keys(env).length > 0 ? env : undefined,
214
+ activation: params.activation ?? 'on-mention'
215
+ };
216
+ }
217
+ //# sourceMappingURL=mcpConnectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpConnectors.js","sourceRoot":"","sources":["../src/mcpConnectors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * MCP tool-list cache — persists each server's discovered tool list
3
+ * keyed by config fingerprint so subsequent Bandit sessions don't have
4
+ * to spawn the server just to enumerate. The agent's per-turn registry
5
+ * build calls `discoverTools` for every registered server; when the
6
+ * cache primes the pool's in-memory copy, that call returns instantly
7
+ * without touching the child process — which is what fires the trust
8
+ * gate even on prompts that never use any MCP tool.
9
+ *
10
+ * Stored at `~/.bandit/mcp-tool-cache.json`. The file is non-sensitive
11
+ * (just tool metadata), so it's written with normal permissions —
12
+ * unlike `mcp-trust.json` which carries a security decision and lives
13
+ * at 0600. If the cache file is missing, corrupted, or stale (config
14
+ * fingerprint no longer matches), the pool falls back to a live spawn
15
+ * + listTools — same path as a fresh install. No correctness risk.
16
+ */
17
+ import type { McpRemoteToolDef } from '@burtson-labs/agent-core';
18
+ /**
19
+ * Load every cached tool list as a Map keyed by fingerprint. Callers
20
+ * iterate registered servers and prime the pool when a fingerprint
21
+ * match exists. Missing-file / malformed-file paths return an empty
22
+ * map silently — Bandit must boot even when the cache is broken.
23
+ */
24
+ export declare function loadMcpToolCache(): Promise<Map<string, McpRemoteToolDef[]>>;
25
+ /**
26
+ * Persist one server's tool list. Replaces the entry that shares the
27
+ * same fingerprint; never grows unbounded because fingerprint changes
28
+ * map to fresh entries and the old fingerprint's entry is dropped
29
+ * (covered by `pruneStale` when the host knows the current fingerprints).
30
+ *
31
+ * Failures are swallowed so a write-permission issue on `~/.bandit/`
32
+ * doesn't crash the turn — the pool will just re-discover next session.
33
+ */
34
+ export declare function saveMcpToolEntry(name: string, fingerprint: string, tools: McpRemoteToolDef[]): Promise<void>;
35
+ /**
36
+ * Drop cache entries whose fingerprints aren't in the currently-active
37
+ * set. Called on boot after the pool registers every server so stale
38
+ * entries from removed or reconfigured servers don't accumulate.
39
+ */
40
+ export declare function pruneMcpToolCache(activeFingerprints: Set<string>): Promise<void>;
41
+ /** Path to the cache file — exposed for /mcp tools-cache commands. */
42
+ export declare function mcpToolCachePath(): string;
43
+ //# sourceMappingURL=mcpToolCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpToolCache.d.ts","sourceRoot":"","sources":["../src/mcpToolCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA2DjE;;;;;GAKG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAOjF;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,gBAAgB,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAStF;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ /**
3
+ * MCP tool-list cache — persists each server's discovered tool list
4
+ * keyed by config fingerprint so subsequent Bandit sessions don't have
5
+ * to spawn the server just to enumerate. The agent's per-turn registry
6
+ * build calls `discoverTools` for every registered server; when the
7
+ * cache primes the pool's in-memory copy, that call returns instantly
8
+ * without touching the child process — which is what fires the trust
9
+ * gate even on prompts that never use any MCP tool.
10
+ *
11
+ * Stored at `~/.bandit/mcp-tool-cache.json`. The file is non-sensitive
12
+ * (just tool metadata), so it's written with normal permissions —
13
+ * unlike `mcp-trust.json` which carries a security decision and lives
14
+ * at 0600. If the cache file is missing, corrupted, or stale (config
15
+ * fingerprint no longer matches), the pool falls back to a live spawn
16
+ * + listTools — same path as a fresh install. No correctness risk.
17
+ */
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
30
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
31
+ }) : function(o, v) {
32
+ o["default"] = v;
33
+ });
34
+ var __importStar = (this && this.__importStar) || (function () {
35
+ var ownKeys = function(o) {
36
+ ownKeys = Object.getOwnPropertyNames || function (o) {
37
+ var ar = [];
38
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
39
+ return ar;
40
+ };
41
+ return ownKeys(o);
42
+ };
43
+ return function (mod) {
44
+ if (mod && mod.__esModule) return mod;
45
+ var result = {};
46
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
47
+ __setModuleDefault(result, mod);
48
+ return result;
49
+ };
50
+ })();
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.loadMcpToolCache = loadMcpToolCache;
53
+ exports.saveMcpToolEntry = saveMcpToolEntry;
54
+ exports.pruneMcpToolCache = pruneMcpToolCache;
55
+ exports.mcpToolCachePath = mcpToolCachePath;
56
+ const fs = __importStar(require("fs"));
57
+ const os = __importStar(require("os"));
58
+ const path = __importStar(require("path"));
59
+ /**
60
+ * Resolved per-call rather than cached at module load so tests that
61
+ * mutate `process.env.HOME` actually hit the tmp directory they set
62
+ * up — and so a long-running host that's had HOME re-pointed for any
63
+ * reason doesn't go on writing to a stale path.
64
+ */
65
+ function cacheFilePath() {
66
+ return path.join(os.homedir(), '.bandit', 'mcp-tool-cache.json');
67
+ }
68
+ async function readCacheFile() {
69
+ try {
70
+ const raw = await fs.promises.readFile(cacheFilePath(), 'utf-8');
71
+ const parsed = JSON.parse(raw);
72
+ if (parsed.version === 1 && Array.isArray(parsed.entries)) {
73
+ return {
74
+ version: 1,
75
+ entries: parsed.entries.filter((e) => typeof e === 'object' && e !== null &&
76
+ typeof e.fingerprint === 'string' &&
77
+ Array.isArray(e.tools))
78
+ };
79
+ }
80
+ }
81
+ catch {
82
+ // Missing or malformed — return empty. The pool will re-spawn on
83
+ // first discoverTools and we'll repopulate from there.
84
+ }
85
+ return { version: 1, entries: [] };
86
+ }
87
+ async function writeCacheFile(file) {
88
+ const dir = path.dirname(cacheFilePath());
89
+ try {
90
+ await fs.promises.mkdir(dir, { recursive: true });
91
+ }
92
+ catch { /* exists */ }
93
+ await fs.promises.writeFile(cacheFilePath(), JSON.stringify(file, null, 2), 'utf-8');
94
+ }
95
+ /**
96
+ * Load every cached tool list as a Map keyed by fingerprint. Callers
97
+ * iterate registered servers and prime the pool when a fingerprint
98
+ * match exists. Missing-file / malformed-file paths return an empty
99
+ * map silently — Bandit must boot even when the cache is broken.
100
+ */
101
+ async function loadMcpToolCache() {
102
+ const file = await readCacheFile();
103
+ const map = new Map();
104
+ for (const entry of file.entries) {
105
+ map.set(entry.fingerprint, entry.tools);
106
+ }
107
+ return map;
108
+ }
109
+ /**
110
+ * Persist one server's tool list. Replaces the entry that shares the
111
+ * same fingerprint; never grows unbounded because fingerprint changes
112
+ * map to fresh entries and the old fingerprint's entry is dropped
113
+ * (covered by `pruneStale` when the host knows the current fingerprints).
114
+ *
115
+ * Failures are swallowed so a write-permission issue on `~/.bandit/`
116
+ * doesn't crash the turn — the pool will just re-discover next session.
117
+ */
118
+ async function saveMcpToolEntry(name, fingerprint, tools) {
119
+ try {
120
+ const file = await readCacheFile();
121
+ const next = file.entries.filter((e) => e.fingerprint !== fingerprint);
122
+ next.push({ name, fingerprint, tools, updatedAt: new Date().toISOString() });
123
+ await writeCacheFile({ version: 1, entries: next });
124
+ }
125
+ catch {
126
+ // Best-effort cache — agent loop continues regardless.
127
+ }
128
+ }
129
+ /**
130
+ * Drop cache entries whose fingerprints aren't in the currently-active
131
+ * set. Called on boot after the pool registers every server so stale
132
+ * entries from removed or reconfigured servers don't accumulate.
133
+ */
134
+ async function pruneMcpToolCache(activeFingerprints) {
135
+ try {
136
+ const file = await readCacheFile();
137
+ const kept = file.entries.filter((e) => activeFingerprints.has(e.fingerprint));
138
+ if (kept.length === file.entries.length)
139
+ return;
140
+ await writeCacheFile({ version: 1, entries: kept });
141
+ }
142
+ catch {
143
+ // Best-effort cleanup.
144
+ }
145
+ }
146
+ /** Path to the cache file — exposed for /mcp tools-cache commands. */
147
+ function mcpToolCachePath() {
148
+ return cacheFilePath();
149
+ }
150
+ //# sourceMappingURL=mcpToolCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpToolCache.js","sourceRoot":"","sources":["../src/mcpToolCache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * MCP trust store — remembers which server-config fingerprints the user
3
+ * has approved across Bandit sessions. Spawning an MCP server is a
4
+ * code-execution boundary; the first time we encounter a config we
5
+ * haven't seen, the host asks the user. The answer (allow once / allow
6
+ * always / deny) is the host's responsibility to surface; this module
7
+ * is the persistence layer for "allow always".
8
+ *
9
+ * Stored at `~/.bandit/mcp-trust.json` as a flat array of fingerprints
10
+ * — file is written 0600 since it represents a security decision the
11
+ * user shouldn't have casually edited by another process.
12
+ */
13
+ /** Read the set of fingerprints the user has previously approved. */
14
+ export declare function loadApprovedMcpFingerprints(): Promise<Set<string>>;
15
+ /** Persist a fingerprint as "always allowed". Idempotent — duplicates are dropped. */
16
+ export declare function approveMcpFingerprint(fingerprint: string): Promise<void>;
17
+ /** Remove a fingerprint from the approved list (used by a future revoke flow). */
18
+ export declare function revokeMcpFingerprint(fingerprint: string): Promise<void>;
19
+ /** Path to the trust file — exposed so error messages and CLI helpers
20
+ * can echo the location for the user. */
21
+ export declare function mcpTrustPath(): string;
22
+ //# sourceMappingURL=mcpTrust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpTrust.d.ts","sourceRoot":"","sources":["../src/mcpTrust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAsCH,qEAAqE;AACrE,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAGxE;AAED,sFAAsF;AACtF,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9E;AAED,kFAAkF;AAClF,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AAED;0CAC0C;AAC1C,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ /**
3
+ * MCP trust store — remembers which server-config fingerprints the user
4
+ * has approved across Bandit sessions. Spawning an MCP server is a
5
+ * code-execution boundary; the first time we encounter a config we
6
+ * haven't seen, the host asks the user. The answer (allow once / allow
7
+ * always / deny) is the host's responsibility to surface; this module
8
+ * is the persistence layer for "allow always".
9
+ *
10
+ * Stored at `~/.bandit/mcp-trust.json` as a flat array of fingerprints
11
+ * — file is written 0600 since it represents a security decision the
12
+ * user shouldn't have casually edited by another process.
13
+ */
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.loadApprovedMcpFingerprints = loadApprovedMcpFingerprints;
49
+ exports.approveMcpFingerprint = approveMcpFingerprint;
50
+ exports.revokeMcpFingerprint = revokeMcpFingerprint;
51
+ exports.mcpTrustPath = mcpTrustPath;
52
+ const fs = __importStar(require("fs"));
53
+ const os = __importStar(require("os"));
54
+ const path = __importStar(require("path"));
55
+ const TRUST_FILE = path.join(os.homedir(), '.bandit', 'mcp-trust.json');
56
+ async function readTrustFile() {
57
+ try {
58
+ const raw = await fs.promises.readFile(TRUST_FILE, 'utf-8');
59
+ const parsed = JSON.parse(raw);
60
+ if (Array.isArray(parsed.approved)) {
61
+ return { approved: parsed.approved.filter((s) => typeof s === 'string') };
62
+ }
63
+ }
64
+ catch {
65
+ // Missing or malformed — return empty. Trust is opt-in; absence
66
+ // of the file means no fingerprints have been approved yet.
67
+ }
68
+ return { approved: [] };
69
+ }
70
+ async function writeTrustFile(file) {
71
+ const dir = path.dirname(TRUST_FILE);
72
+ try {
73
+ await fs.promises.mkdir(dir, { recursive: true });
74
+ }
75
+ catch { /* exists */ }
76
+ await fs.promises.writeFile(TRUST_FILE, JSON.stringify(file, null, 2), { encoding: 'utf-8', mode: 0o600 });
77
+ }
78
+ /** Read the set of fingerprints the user has previously approved. */
79
+ async function loadApprovedMcpFingerprints() {
80
+ const file = await readTrustFile();
81
+ return new Set(file.approved);
82
+ }
83
+ /** Persist a fingerprint as "always allowed". Idempotent — duplicates are dropped. */
84
+ async function approveMcpFingerprint(fingerprint) {
85
+ const file = await readTrustFile();
86
+ if (!file.approved.includes(fingerprint)) {
87
+ file.approved.push(fingerprint);
88
+ await writeTrustFile(file);
89
+ }
90
+ }
91
+ /** Remove a fingerprint from the approved list (used by a future revoke flow). */
92
+ async function revokeMcpFingerprint(fingerprint) {
93
+ const file = await readTrustFile();
94
+ const next = file.approved.filter((f) => f !== fingerprint);
95
+ if (next.length !== file.approved.length) {
96
+ await writeTrustFile({ approved: next });
97
+ }
98
+ }
99
+ /** Path to the trust file — exposed so error messages and CLI helpers
100
+ * can echo the location for the user. */
101
+ function mcpTrustPath() {
102
+ return TRUST_FILE;
103
+ }
104
+ //# sourceMappingURL=mcpTrust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpTrust.js","sourceRoot":"","sources":["../src/mcpTrust.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCH,kEAGC;AAGD,sDAMC;AAGD,oDAMC;AAID,oCAEC;AAhED,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAQxE,KAAK,UAAU,aAAa;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC5E,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;QAChE,4DAA4D;IAC9D,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAe;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,CAAC;QAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACjF,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CACzB,UAAU,EACV,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAC7B,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;AACJ,CAAC;AAED,qEAAqE;AAC9D,KAAK,UAAU,2BAA2B;IAC/C,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;IACnC,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,sFAAsF;AAC/E,KAAK,UAAU,qBAAqB,CAAC,WAAmB;IAC7D,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChC,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,kFAAkF;AAC3E,KAAK,UAAU,oBAAoB,CAAC,WAAmB;IAC5D,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC;IAC5D,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED;0CAC0C;AAC1C,SAAgB,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Memory — auto-load workspace-local context files (BANDIT.md / CLAUDE.md)
3
+ * and inline them into the system prompt so the agent follows project rules
4
+ * without being re-told on every turn.
5
+ */
6
+ import { type MemoryWarnFn } from './memoryIndex';
7
+ export interface MemoryBundle {
8
+ /** Combined text ready for injection. Empty string if nothing found. */
9
+ content: string;
10
+ sources: string[];
11
+ }
12
+ /**
13
+ * loadMemory + MEMORY.md index, fused into a single bundle the host can
14
+ * inject as the system-prompt memory block. Always-loaded files come
15
+ * first; the index follows under its own source marker so the model
16
+ * knows which entries are full content vs. on-demand topic pointers.
17
+ *
18
+ * Returns sources from BOTH passes when present — callers use this for
19
+ * the `/memory` slash command and boot-status output.
20
+ */
21
+ export declare function loadCombinedMemory(cwd: string, warn?: MemoryWarnFn): Promise<MemoryBundle>;
22
+ export declare function loadMemory(cwd: string): Promise<MemoryBundle>;
23
+ /**
24
+ * Append a single fact to project memory so it survives across sessions.
25
+ *
26
+ * Persists to `BANDIT.md` at the workspace root (creates the file with a
27
+ * minimal frontmatter-free header when it doesn't exist). Bullets are
28
+ * appended under a `## Notes` heading so multiple `/remember` calls
29
+ * accumulate without scattering. CLAUDE.md-only repos still get found
30
+ * by loadMemory, but new facts always land in BANDIT.md to keep one
31
+ * canonical write target.
32
+ *
33
+ * Returns the absolute path written so the caller can echo it back to
34
+ * the user — visibility matters because the user typed "remember X"
35
+ * and needs to see WHERE the fact landed.
36
+ */
37
+ export declare function appendMemory(cwd: string, fact: string): Promise<string>;
38
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAWvB,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAUhG;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAsBnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkC7E"}