@contextstream/mcp-server 0.4.16 → 0.4.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +526 -280
- package/dist/test-server.js +16 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4050,6 +4050,131 @@ var coerce = {
|
|
|
4050
4050
|
};
|
|
4051
4051
|
var NEVER = INVALID;
|
|
4052
4052
|
|
|
4053
|
+
// src/version.ts
|
|
4054
|
+
import { createRequire } from "module";
|
|
4055
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
4056
|
+
import { homedir } from "os";
|
|
4057
|
+
import { join } from "path";
|
|
4058
|
+
var UPGRADE_COMMAND = "npm update -g @contextstream/mcp-server";
|
|
4059
|
+
var NPM_LATEST_URL = "https://registry.npmjs.org/@contextstream/mcp-server/latest";
|
|
4060
|
+
function getVersion() {
|
|
4061
|
+
try {
|
|
4062
|
+
const require2 = createRequire(import.meta.url);
|
|
4063
|
+
const pkg = require2("../package.json");
|
|
4064
|
+
const version = pkg?.version;
|
|
4065
|
+
if (typeof version === "string" && version.trim()) return version.trim();
|
|
4066
|
+
} catch {
|
|
4067
|
+
}
|
|
4068
|
+
return "unknown";
|
|
4069
|
+
}
|
|
4070
|
+
var VERSION = getVersion();
|
|
4071
|
+
function compareVersions(v1, v2) {
|
|
4072
|
+
const parts1 = v1.split(".").map(Number);
|
|
4073
|
+
const parts2 = v2.split(".").map(Number);
|
|
4074
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
4075
|
+
const p1 = parts1[i] ?? 0;
|
|
4076
|
+
const p2 = parts2[i] ?? 0;
|
|
4077
|
+
if (p1 < p2) return -1;
|
|
4078
|
+
if (p1 > p2) return 1;
|
|
4079
|
+
}
|
|
4080
|
+
return 0;
|
|
4081
|
+
}
|
|
4082
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4083
|
+
var latestVersionPromise = null;
|
|
4084
|
+
function getCacheFilePath() {
|
|
4085
|
+
return join(homedir(), ".contextstream", "version-cache.json");
|
|
4086
|
+
}
|
|
4087
|
+
function readCache() {
|
|
4088
|
+
try {
|
|
4089
|
+
const cacheFile = getCacheFilePath();
|
|
4090
|
+
if (!existsSync(cacheFile)) return null;
|
|
4091
|
+
const data = JSON.parse(readFileSync(cacheFile, "utf-8"));
|
|
4092
|
+
if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
|
|
4093
|
+
return data;
|
|
4094
|
+
} catch {
|
|
4095
|
+
return null;
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
function writeCache(latestVersion) {
|
|
4099
|
+
try {
|
|
4100
|
+
const configDir = join(homedir(), ".contextstream");
|
|
4101
|
+
if (!existsSync(configDir)) {
|
|
4102
|
+
mkdirSync(configDir, { recursive: true });
|
|
4103
|
+
}
|
|
4104
|
+
const cacheFile = getCacheFilePath();
|
|
4105
|
+
writeFileSync(cacheFile, JSON.stringify({
|
|
4106
|
+
latestVersion,
|
|
4107
|
+
checkedAt: Date.now()
|
|
4108
|
+
}));
|
|
4109
|
+
} catch {
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
async function fetchLatestVersion() {
|
|
4113
|
+
try {
|
|
4114
|
+
const controller = new AbortController();
|
|
4115
|
+
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
4116
|
+
const response = await fetch(NPM_LATEST_URL, {
|
|
4117
|
+
signal: controller.signal,
|
|
4118
|
+
headers: { "Accept": "application/json" }
|
|
4119
|
+
});
|
|
4120
|
+
clearTimeout(timeout);
|
|
4121
|
+
if (!response.ok) return null;
|
|
4122
|
+
const data = await response.json();
|
|
4123
|
+
return typeof data.version === "string" ? data.version : null;
|
|
4124
|
+
} catch {
|
|
4125
|
+
return null;
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
async function resolveLatestVersion() {
|
|
4129
|
+
const cached = readCache();
|
|
4130
|
+
if (cached) return cached.latestVersion;
|
|
4131
|
+
if (!latestVersionPromise) {
|
|
4132
|
+
latestVersionPromise = fetchLatestVersion().finally(() => {
|
|
4133
|
+
latestVersionPromise = null;
|
|
4134
|
+
});
|
|
4135
|
+
}
|
|
4136
|
+
const latestVersion = await latestVersionPromise;
|
|
4137
|
+
if (latestVersion) {
|
|
4138
|
+
writeCache(latestVersion);
|
|
4139
|
+
}
|
|
4140
|
+
return latestVersion;
|
|
4141
|
+
}
|
|
4142
|
+
async function checkForUpdates() {
|
|
4143
|
+
const notice = await getUpdateNotice();
|
|
4144
|
+
if (notice?.behind) {
|
|
4145
|
+
showUpdateWarning(notice.current, notice.latest);
|
|
4146
|
+
}
|
|
4147
|
+
}
|
|
4148
|
+
function showUpdateWarning(currentVersion, latestVersion) {
|
|
4149
|
+
console.error("");
|
|
4150
|
+
console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
4151
|
+
console.error(`\u26A0\uFE0F Update available: v${currentVersion} \u2192 v${latestVersion}`);
|
|
4152
|
+
console.error("");
|
|
4153
|
+
console.error(` Run: ${UPGRADE_COMMAND}`);
|
|
4154
|
+
console.error("");
|
|
4155
|
+
console.error(" Then restart your AI tool to use the new version.");
|
|
4156
|
+
console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
4157
|
+
console.error("");
|
|
4158
|
+
}
|
|
4159
|
+
async function getUpdateNotice() {
|
|
4160
|
+
const currentVersion = VERSION;
|
|
4161
|
+
if (currentVersion === "unknown") return null;
|
|
4162
|
+
try {
|
|
4163
|
+
const latestVersion = await resolveLatestVersion();
|
|
4164
|
+
if (!latestVersion) return null;
|
|
4165
|
+
if (compareVersions(currentVersion, latestVersion) < 0) {
|
|
4166
|
+
return {
|
|
4167
|
+
current: currentVersion,
|
|
4168
|
+
latest: latestVersion,
|
|
4169
|
+
behind: true,
|
|
4170
|
+
upgrade_command: UPGRADE_COMMAND
|
|
4171
|
+
};
|
|
4172
|
+
}
|
|
4173
|
+
} catch {
|
|
4174
|
+
}
|
|
4175
|
+
return null;
|
|
4176
|
+
}
|
|
4177
|
+
|
|
4053
4178
|
// src/config.ts
|
|
4054
4179
|
var DEFAULT_API_URL = "https://api.contextstream.io";
|
|
4055
4180
|
function parseBooleanEnv(value) {
|
|
@@ -4065,7 +4190,7 @@ var configSchema = external_exports.object({
|
|
|
4065
4190
|
jwt: external_exports.string().min(1).optional(),
|
|
4066
4191
|
defaultWorkspaceId: external_exports.string().uuid().optional(),
|
|
4067
4192
|
defaultProjectId: external_exports.string().uuid().optional(),
|
|
4068
|
-
userAgent: external_exports.string().default(
|
|
4193
|
+
userAgent: external_exports.string().default(`contextstream-mcp/${VERSION}`),
|
|
4069
4194
|
allowHeaderAuth: external_exports.boolean().optional(),
|
|
4070
4195
|
contextPackEnabled: external_exports.boolean().default(true)
|
|
4071
4196
|
});
|
|
@@ -4732,131 +4857,6 @@ var CacheKeys = {
|
|
|
4732
4857
|
};
|
|
4733
4858
|
var globalCache = new MemoryCache();
|
|
4734
4859
|
|
|
4735
|
-
// src/version.ts
|
|
4736
|
-
import { createRequire } from "module";
|
|
4737
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
4738
|
-
import { homedir } from "os";
|
|
4739
|
-
import { join as join3 } from "path";
|
|
4740
|
-
var UPGRADE_COMMAND = "npm update -g @contextstream/mcp-server";
|
|
4741
|
-
var NPM_LATEST_URL = "https://registry.npmjs.org/@contextstream/mcp-server/latest";
|
|
4742
|
-
function getVersion() {
|
|
4743
|
-
try {
|
|
4744
|
-
const require2 = createRequire(import.meta.url);
|
|
4745
|
-
const pkg = require2("../package.json");
|
|
4746
|
-
const version = pkg?.version;
|
|
4747
|
-
if (typeof version === "string" && version.trim()) return version.trim();
|
|
4748
|
-
} catch {
|
|
4749
|
-
}
|
|
4750
|
-
return "unknown";
|
|
4751
|
-
}
|
|
4752
|
-
var VERSION = getVersion();
|
|
4753
|
-
function compareVersions(v1, v2) {
|
|
4754
|
-
const parts1 = v1.split(".").map(Number);
|
|
4755
|
-
const parts2 = v2.split(".").map(Number);
|
|
4756
|
-
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
4757
|
-
const p1 = parts1[i] ?? 0;
|
|
4758
|
-
const p2 = parts2[i] ?? 0;
|
|
4759
|
-
if (p1 < p2) return -1;
|
|
4760
|
-
if (p1 > p2) return 1;
|
|
4761
|
-
}
|
|
4762
|
-
return 0;
|
|
4763
|
-
}
|
|
4764
|
-
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4765
|
-
var latestVersionPromise = null;
|
|
4766
|
-
function getCacheFilePath() {
|
|
4767
|
-
return join3(homedir(), ".contextstream", "version-cache.json");
|
|
4768
|
-
}
|
|
4769
|
-
function readCache() {
|
|
4770
|
-
try {
|
|
4771
|
-
const cacheFile = getCacheFilePath();
|
|
4772
|
-
if (!existsSync2(cacheFile)) return null;
|
|
4773
|
-
const data = JSON.parse(readFileSync2(cacheFile, "utf-8"));
|
|
4774
|
-
if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
|
|
4775
|
-
return data;
|
|
4776
|
-
} catch {
|
|
4777
|
-
return null;
|
|
4778
|
-
}
|
|
4779
|
-
}
|
|
4780
|
-
function writeCache(latestVersion) {
|
|
4781
|
-
try {
|
|
4782
|
-
const configDir = join3(homedir(), ".contextstream");
|
|
4783
|
-
if (!existsSync2(configDir)) {
|
|
4784
|
-
mkdirSync2(configDir, { recursive: true });
|
|
4785
|
-
}
|
|
4786
|
-
const cacheFile = getCacheFilePath();
|
|
4787
|
-
writeFileSync2(cacheFile, JSON.stringify({
|
|
4788
|
-
latestVersion,
|
|
4789
|
-
checkedAt: Date.now()
|
|
4790
|
-
}));
|
|
4791
|
-
} catch {
|
|
4792
|
-
}
|
|
4793
|
-
}
|
|
4794
|
-
async function fetchLatestVersion() {
|
|
4795
|
-
try {
|
|
4796
|
-
const controller = new AbortController();
|
|
4797
|
-
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
4798
|
-
const response = await fetch(NPM_LATEST_URL, {
|
|
4799
|
-
signal: controller.signal,
|
|
4800
|
-
headers: { "Accept": "application/json" }
|
|
4801
|
-
});
|
|
4802
|
-
clearTimeout(timeout);
|
|
4803
|
-
if (!response.ok) return null;
|
|
4804
|
-
const data = await response.json();
|
|
4805
|
-
return typeof data.version === "string" ? data.version : null;
|
|
4806
|
-
} catch {
|
|
4807
|
-
return null;
|
|
4808
|
-
}
|
|
4809
|
-
}
|
|
4810
|
-
async function resolveLatestVersion() {
|
|
4811
|
-
const cached = readCache();
|
|
4812
|
-
if (cached) return cached.latestVersion;
|
|
4813
|
-
if (!latestVersionPromise) {
|
|
4814
|
-
latestVersionPromise = fetchLatestVersion().finally(() => {
|
|
4815
|
-
latestVersionPromise = null;
|
|
4816
|
-
});
|
|
4817
|
-
}
|
|
4818
|
-
const latestVersion = await latestVersionPromise;
|
|
4819
|
-
if (latestVersion) {
|
|
4820
|
-
writeCache(latestVersion);
|
|
4821
|
-
}
|
|
4822
|
-
return latestVersion;
|
|
4823
|
-
}
|
|
4824
|
-
async function checkForUpdates() {
|
|
4825
|
-
const notice = await getUpdateNotice();
|
|
4826
|
-
if (notice?.behind) {
|
|
4827
|
-
showUpdateWarning(notice.current, notice.latest);
|
|
4828
|
-
}
|
|
4829
|
-
}
|
|
4830
|
-
function showUpdateWarning(currentVersion, latestVersion) {
|
|
4831
|
-
console.error("");
|
|
4832
|
-
console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
4833
|
-
console.error(`\u26A0\uFE0F Update available: v${currentVersion} \u2192 v${latestVersion}`);
|
|
4834
|
-
console.error("");
|
|
4835
|
-
console.error(` Run: ${UPGRADE_COMMAND}`);
|
|
4836
|
-
console.error("");
|
|
4837
|
-
console.error(" Then restart your AI tool to use the new version.");
|
|
4838
|
-
console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
4839
|
-
console.error("");
|
|
4840
|
-
}
|
|
4841
|
-
async function getUpdateNotice() {
|
|
4842
|
-
const currentVersion = VERSION;
|
|
4843
|
-
if (currentVersion === "unknown") return null;
|
|
4844
|
-
try {
|
|
4845
|
-
const latestVersion = await resolveLatestVersion();
|
|
4846
|
-
if (!latestVersion) return null;
|
|
4847
|
-
if (compareVersions(currentVersion, latestVersion) < 0) {
|
|
4848
|
-
return {
|
|
4849
|
-
current: currentVersion,
|
|
4850
|
-
latest: latestVersion,
|
|
4851
|
-
behind: true,
|
|
4852
|
-
upgrade_command: UPGRADE_COMMAND
|
|
4853
|
-
};
|
|
4854
|
-
}
|
|
4855
|
-
} catch {
|
|
4856
|
-
}
|
|
4857
|
-
return null;
|
|
4858
|
-
}
|
|
4859
|
-
|
|
4860
4860
|
// src/client.ts
|
|
4861
4861
|
var uuidSchema = external_exports.string().uuid();
|
|
4862
4862
|
function unwrapApiResponse(result) {
|
|
@@ -6587,7 +6587,10 @@ var ContextStreamClient = class {
|
|
|
6587
6587
|
max_tokens: maxTokens,
|
|
6588
6588
|
format,
|
|
6589
6589
|
mode,
|
|
6590
|
-
distill: params.distill
|
|
6590
|
+
distill: params.distill,
|
|
6591
|
+
client_version: VERSION,
|
|
6592
|
+
rules_version: VERSION,
|
|
6593
|
+
notice_inline: false
|
|
6591
6594
|
}
|
|
6592
6595
|
});
|
|
6593
6596
|
const data = unwrapApiResponse(apiResult);
|
|
@@ -7469,9 +7472,11 @@ W:${wsHint}
|
|
|
7469
7472
|
// src/tools.ts
|
|
7470
7473
|
import * as fs3 from "node:fs";
|
|
7471
7474
|
import * as path4 from "node:path";
|
|
7475
|
+
import { homedir as homedir2 } from "node:os";
|
|
7472
7476
|
|
|
7473
7477
|
// src/rules-templates.ts
|
|
7474
7478
|
var DEFAULT_CLAUDE_MCP_SERVER_NAME = "contextstream";
|
|
7479
|
+
var RULES_VERSION = VERSION === "unknown" ? "0.0.0" : VERSION;
|
|
7475
7480
|
var CONTEXTSTREAM_TOOL_NAMES = [
|
|
7476
7481
|
// Standalone tools (always present)
|
|
7477
7482
|
"session_init",
|
|
@@ -7507,6 +7512,7 @@ var CONTEXTSTREAM_RULES_FULL = `
|
|
|
7507
7512
|
|
|
7508
7513
|
You have access to ContextStream MCP tools for persistent memory and context.
|
|
7509
7514
|
v0.4.x uses **~11 consolidated domain tools** for ~75% token reduction vs previous versions.
|
|
7515
|
+
Rules Version: ${RULES_VERSION}
|
|
7510
7516
|
|
|
7511
7517
|
## TL;DR - REQUIRED EVERY MESSAGE
|
|
7512
7518
|
|
|
@@ -7578,6 +7584,13 @@ If context still feels missing, use \`session(action="recall", query="...")\` fo
|
|
|
7578
7584
|
|
|
7579
7585
|
---
|
|
7580
7586
|
|
|
7587
|
+
### Rules Update Notices
|
|
7588
|
+
|
|
7589
|
+
- If you see **[RULES_NOTICE]**, update rules via \`generate_editor_rules(folder_path="<cwd>")\` (or rerun setup).
|
|
7590
|
+
- If you see **[VERSION_NOTICE]**, tell the user to update MCP using the provided command.
|
|
7591
|
+
|
|
7592
|
+
---
|
|
7593
|
+
|
|
7581
7594
|
### Preferences & Lessons (Use Early)
|
|
7582
7595
|
|
|
7583
7596
|
- If preferences/style matter: \`session(action="user_context")\`
|
|
@@ -7595,6 +7608,7 @@ Before searching files or code, confirm the project is indexed and the graph is
|
|
|
7595
7608
|
- Local repo: \`project(action="ingest_local", path="<cwd>")\`
|
|
7596
7609
|
- Otherwise: \`project(action="index")\`
|
|
7597
7610
|
3. If graph queries are empty/unavailable: \`graph(action="ingest")\`
|
|
7611
|
+
4. If indexing is in progress, tell the user and wait; do not fall back to local scans.
|
|
7598
7612
|
|
|
7599
7613
|
Only after this preflight, proceed with search/analysis below.
|
|
7600
7614
|
|
|
@@ -7602,9 +7616,12 @@ Only after this preflight, proceed with search/analysis below.
|
|
|
7602
7616
|
|
|
7603
7617
|
**Search order:**
|
|
7604
7618
|
1. \`session(action="smart_search", query="...")\` - context-enriched
|
|
7605
|
-
2. \`search(mode="hybrid", query="...")\`
|
|
7606
|
-
3. \`
|
|
7607
|
-
4.
|
|
7619
|
+
2. \`search(mode="hybrid", query="...")\` or \`search(mode="keyword", query="<filename>")\`
|
|
7620
|
+
3. \`project(action="files")\` - file tree/list (only when needed)
|
|
7621
|
+
4. \`graph(action="dependencies", ...)\` - code structure
|
|
7622
|
+
5. Local repo scans (rg/ls/find) - only if ContextStream returns no results or is unavailable
|
|
7623
|
+
|
|
7624
|
+
Use ContextStream results directly; only open files if you need exact code.
|
|
7608
7625
|
|
|
7609
7626
|
**Code Analysis:**
|
|
7610
7627
|
- Dependencies: \`graph(action="dependencies", file_path="...")\`
|
|
@@ -7684,6 +7701,7 @@ var CONTEXTSTREAM_RULES_MINIMAL = `
|
|
|
7684
7701
|
## ContextStream v0.4.x (Consolidated Domain Tools)
|
|
7685
7702
|
|
|
7686
7703
|
v0.4.x uses ~11 consolidated domain tools for ~75% token reduction vs previous versions.
|
|
7704
|
+
Rules Version: ${RULES_VERSION}
|
|
7687
7705
|
|
|
7688
7706
|
### Required Every Message
|
|
7689
7707
|
|
|
@@ -7705,7 +7723,7 @@ v0.4.x uses ~11 consolidated domain tools for ~75% token reduction vs previous v
|
|
|
7705
7723
|
| \`session\` | \`session(action="capture", ...)\` \u2014 actions: capture, capture_lesson, get_lessons, recall, remember, user_context, summary, compress, delta, smart_search |
|
|
7706
7724
|
| \`memory\` | \`memory(action="list_events", ...)\` \u2014 CRUD for events/nodes, search, decisions, timeline, summary |
|
|
7707
7725
|
| \`graph\` | \`graph(action="dependencies", ...)\` \u2014 dependencies, impact, call_path, related, ingest |
|
|
7708
|
-
| \`project\` | \`project(action="list", ...)\`
|
|
7726
|
+
| \`project\` | \`project(action="list", ...)\` - list, get, create, update, index, overview, statistics, files, index_status, ingest_local |
|
|
7709
7727
|
| \`workspace\` | \`workspace(action="list", ...)\` \u2014 list, get, associate, bootstrap |
|
|
7710
7728
|
| \`integration\` | \`integration(provider="github", action="search", ...)\` \u2014 GitHub/Slack integration |
|
|
7711
7729
|
| \`help\` | \`help(action="tools")\` \u2014 tools, auth, version, editor_rules |
|
|
@@ -7715,8 +7733,10 @@ v0.4.x uses ~11 consolidated domain tools for ~75% token reduction vs previous v
|
|
|
7715
7733
|
- **First message**: Always call \`session_init\` with context_hint
|
|
7716
7734
|
- **Every message after**: Always call \`context_smart\` BEFORE responding (semantic search for relevant context)
|
|
7717
7735
|
- **Before searching files/code**: Check \`project(action="index_status")\`; if missing/stale run \`project(action="ingest_local", path="<cwd>")\` or \`project(action="index")\`, and use \`graph(action="ingest")\` if needed
|
|
7718
|
-
- **For discovery**: Use \`session(action="smart_search")\` or \`search(mode="hybrid")\` before local repo scans
|
|
7736
|
+
- **For discovery**: Use \`session(action="smart_search")\` or \`search(mode="hybrid")\` before any local repo scans
|
|
7737
|
+
- **For file/function/config lookups**: Use \`search\`/\`graph\` first; only fall back to rg/ls/find if ContextStream returns no results
|
|
7719
7738
|
- **For code analysis**: Use \`graph(action="dependencies")\` or \`graph(action="impact")\` for call/dependency analysis
|
|
7739
|
+
- **On [RULES_NOTICE]**: Use \`generate_editor_rules(folder_path="<cwd>")\` to update rules
|
|
7720
7740
|
- **After completing work**: Always capture decisions/insights with \`session(action="capture")\`
|
|
7721
7741
|
- **On mistakes/corrections**: Immediately capture lessons with \`session(action="capture_lesson")\`
|
|
7722
7742
|
|
|
@@ -8042,6 +8062,235 @@ function normalizeUuid(value) {
|
|
|
8042
8062
|
if (!value) return void 0;
|
|
8043
8063
|
return uuidSchema2.safeParse(value).success ? value : void 0;
|
|
8044
8064
|
}
|
|
8065
|
+
var RULES_NOTICE_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
8066
|
+
var RULES_VERSION_REGEX = /Rules Version:\s*([0-9][0-9A-Za-z.\-]*)/i;
|
|
8067
|
+
var RULES_PROJECT_FILES = {
|
|
8068
|
+
codex: "AGENTS.md",
|
|
8069
|
+
claude: "CLAUDE.md",
|
|
8070
|
+
cursor: ".cursorrules",
|
|
8071
|
+
windsurf: ".windsurfrules",
|
|
8072
|
+
cline: ".clinerules",
|
|
8073
|
+
kilo: path4.join(".kilocode", "rules", "contextstream.md"),
|
|
8074
|
+
roo: path4.join(".roo", "rules", "contextstream.md"),
|
|
8075
|
+
aider: ".aider.conf.yml"
|
|
8076
|
+
};
|
|
8077
|
+
var RULES_GLOBAL_FILES = {
|
|
8078
|
+
codex: [path4.join(homedir2(), ".codex", "AGENTS.md")],
|
|
8079
|
+
windsurf: [path4.join(homedir2(), ".codeium", "windsurf", "memories", "global_rules.md")],
|
|
8080
|
+
kilo: [path4.join(homedir2(), ".kilocode", "rules", "contextstream.md")],
|
|
8081
|
+
roo: [path4.join(homedir2(), ".roo", "rules", "contextstream.md")]
|
|
8082
|
+
};
|
|
8083
|
+
var rulesNoticeCache = /* @__PURE__ */ new Map();
|
|
8084
|
+
function compareVersions2(v1, v2) {
|
|
8085
|
+
const parts1 = v1.split(".").map(Number);
|
|
8086
|
+
const parts2 = v2.split(".").map(Number);
|
|
8087
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
8088
|
+
const p1 = parts1[i] ?? 0;
|
|
8089
|
+
const p2 = parts2[i] ?? 0;
|
|
8090
|
+
if (p1 < p2) return -1;
|
|
8091
|
+
if (p1 > p2) return 1;
|
|
8092
|
+
}
|
|
8093
|
+
return 0;
|
|
8094
|
+
}
|
|
8095
|
+
function extractRulesVersion(content) {
|
|
8096
|
+
const match = content.match(RULES_VERSION_REGEX);
|
|
8097
|
+
return match?.[1]?.trim() ?? null;
|
|
8098
|
+
}
|
|
8099
|
+
function detectEditorFromClientName(clientName) {
|
|
8100
|
+
if (!clientName) return null;
|
|
8101
|
+
const normalized = clientName.toLowerCase().trim();
|
|
8102
|
+
if (normalized.includes("cursor")) return "cursor";
|
|
8103
|
+
if (normalized.includes("windsurf") || normalized.includes("codeium")) return "windsurf";
|
|
8104
|
+
if (normalized.includes("claude")) return "claude";
|
|
8105
|
+
if (normalized.includes("cline")) return "cline";
|
|
8106
|
+
if (normalized.includes("kilo")) return "kilo";
|
|
8107
|
+
if (normalized.includes("roo")) return "roo";
|
|
8108
|
+
if (normalized.includes("codex")) return "codex";
|
|
8109
|
+
if (normalized.includes("aider")) return "aider";
|
|
8110
|
+
return null;
|
|
8111
|
+
}
|
|
8112
|
+
function resolveRulesCandidatePaths(folderPath, editorKey) {
|
|
8113
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
8114
|
+
const addProject = (key) => {
|
|
8115
|
+
if (!folderPath) return;
|
|
8116
|
+
const rel = RULES_PROJECT_FILES[key];
|
|
8117
|
+
if (rel) {
|
|
8118
|
+
candidates.add(path4.join(folderPath, rel));
|
|
8119
|
+
}
|
|
8120
|
+
};
|
|
8121
|
+
const addGlobal = (key) => {
|
|
8122
|
+
const paths = RULES_GLOBAL_FILES[key];
|
|
8123
|
+
if (!paths) return;
|
|
8124
|
+
for (const p of paths) {
|
|
8125
|
+
candidates.add(p);
|
|
8126
|
+
}
|
|
8127
|
+
};
|
|
8128
|
+
if (editorKey) {
|
|
8129
|
+
addProject(editorKey);
|
|
8130
|
+
addGlobal(editorKey);
|
|
8131
|
+
} else {
|
|
8132
|
+
for (const key of Object.keys(RULES_PROJECT_FILES)) {
|
|
8133
|
+
addProject(key);
|
|
8134
|
+
addGlobal(key);
|
|
8135
|
+
}
|
|
8136
|
+
}
|
|
8137
|
+
return Array.from(candidates);
|
|
8138
|
+
}
|
|
8139
|
+
function resolveFolderPath(inputPath, sessionManager) {
|
|
8140
|
+
if (inputPath) return inputPath;
|
|
8141
|
+
const fromSession = sessionManager?.getFolderPath();
|
|
8142
|
+
if (fromSession) return fromSession;
|
|
8143
|
+
const ctxPath = sessionManager?.getContext();
|
|
8144
|
+
const contextFolder = ctxPath && typeof ctxPath.folder_path === "string" ? ctxPath.folder_path : null;
|
|
8145
|
+
if (contextFolder) return contextFolder;
|
|
8146
|
+
const cwd = process.cwd();
|
|
8147
|
+
const indicators = [".git", "package.json", "Cargo.toml", "pyproject.toml", ".contextstream"];
|
|
8148
|
+
const hasIndicator = indicators.some((entry) => {
|
|
8149
|
+
try {
|
|
8150
|
+
return fs3.existsSync(path4.join(cwd, entry));
|
|
8151
|
+
} catch {
|
|
8152
|
+
return false;
|
|
8153
|
+
}
|
|
8154
|
+
});
|
|
8155
|
+
return hasIndicator ? cwd : null;
|
|
8156
|
+
}
|
|
8157
|
+
function getRulesNotice(folderPath, clientName) {
|
|
8158
|
+
if (!RULES_VERSION || RULES_VERSION === "0.0.0") return null;
|
|
8159
|
+
const editorKey = detectEditorFromClientName(clientName);
|
|
8160
|
+
if (!folderPath && !editorKey) {
|
|
8161
|
+
return null;
|
|
8162
|
+
}
|
|
8163
|
+
const cacheKey = `${folderPath ?? "none"}|${editorKey ?? "all"}`;
|
|
8164
|
+
const cached = rulesNoticeCache.get(cacheKey);
|
|
8165
|
+
if (cached && Date.now() - cached.checkedAt < RULES_NOTICE_CACHE_TTL_MS) {
|
|
8166
|
+
return cached.notice;
|
|
8167
|
+
}
|
|
8168
|
+
const candidates = resolveRulesCandidatePaths(folderPath, editorKey);
|
|
8169
|
+
const existing = candidates.filter((filePath) => fs3.existsSync(filePath));
|
|
8170
|
+
if (existing.length === 0) {
|
|
8171
|
+
const updateCommand2 = folderPath ? `generate_editor_rules(folder_path="${folderPath}")` : 'generate_editor_rules(folder_path="<cwd>")';
|
|
8172
|
+
const notice2 = {
|
|
8173
|
+
status: "missing",
|
|
8174
|
+
latest: RULES_VERSION,
|
|
8175
|
+
files_checked: candidates,
|
|
8176
|
+
update_tool: "generate_editor_rules",
|
|
8177
|
+
update_args: {
|
|
8178
|
+
...folderPath ? { folder_path: folderPath } : {},
|
|
8179
|
+
editors: editorKey ? [editorKey] : ["all"]
|
|
8180
|
+
},
|
|
8181
|
+
update_command: updateCommand2
|
|
8182
|
+
};
|
|
8183
|
+
rulesNoticeCache.set(cacheKey, { checkedAt: Date.now(), notice: notice2 });
|
|
8184
|
+
return notice2;
|
|
8185
|
+
}
|
|
8186
|
+
const filesMissingVersion = [];
|
|
8187
|
+
const filesOutdated = [];
|
|
8188
|
+
const versions = [];
|
|
8189
|
+
for (const filePath of existing) {
|
|
8190
|
+
try {
|
|
8191
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8192
|
+
const version = extractRulesVersion(content);
|
|
8193
|
+
if (!version) {
|
|
8194
|
+
filesMissingVersion.push(filePath);
|
|
8195
|
+
continue;
|
|
8196
|
+
}
|
|
8197
|
+
versions.push(version);
|
|
8198
|
+
if (compareVersions2(version, RULES_VERSION) < 0) {
|
|
8199
|
+
filesOutdated.push(filePath);
|
|
8200
|
+
}
|
|
8201
|
+
} catch {
|
|
8202
|
+
filesMissingVersion.push(filePath);
|
|
8203
|
+
}
|
|
8204
|
+
}
|
|
8205
|
+
if (filesOutdated.length === 0 && filesMissingVersion.length === 0) {
|
|
8206
|
+
rulesNoticeCache.set(cacheKey, { checkedAt: Date.now(), notice: null });
|
|
8207
|
+
return null;
|
|
8208
|
+
}
|
|
8209
|
+
const current = versions.sort(compareVersions2).at(-1);
|
|
8210
|
+
const updateCommand = folderPath ? `generate_editor_rules(folder_path="${folderPath}")` : 'generate_editor_rules(folder_path="<cwd>")';
|
|
8211
|
+
const notice = {
|
|
8212
|
+
status: filesOutdated.length > 0 ? "behind" : "unknown",
|
|
8213
|
+
current,
|
|
8214
|
+
latest: RULES_VERSION,
|
|
8215
|
+
files_checked: existing,
|
|
8216
|
+
...filesOutdated.length > 0 ? { files_outdated: filesOutdated } : {},
|
|
8217
|
+
...filesMissingVersion.length > 0 ? { files_missing_version: filesMissingVersion } : {},
|
|
8218
|
+
update_tool: "generate_editor_rules",
|
|
8219
|
+
update_args: {
|
|
8220
|
+
...folderPath ? { folder_path: folderPath } : {},
|
|
8221
|
+
editors: editorKey ? [editorKey] : ["all"]
|
|
8222
|
+
},
|
|
8223
|
+
update_command: updateCommand
|
|
8224
|
+
};
|
|
8225
|
+
rulesNoticeCache.set(cacheKey, { checkedAt: Date.now(), notice });
|
|
8226
|
+
return notice;
|
|
8227
|
+
}
|
|
8228
|
+
var CONTEXTSTREAM_START_MARKER = "<!-- BEGIN ContextStream -->";
|
|
8229
|
+
var CONTEXTSTREAM_END_MARKER = "<!-- END ContextStream -->";
|
|
8230
|
+
function wrapWithMarkers(content) {
|
|
8231
|
+
return `${CONTEXTSTREAM_START_MARKER}
|
|
8232
|
+
${content.trim()}
|
|
8233
|
+
${CONTEXTSTREAM_END_MARKER}`;
|
|
8234
|
+
}
|
|
8235
|
+
async function upsertRuleFile(filePath, content) {
|
|
8236
|
+
await fs3.promises.mkdir(path4.dirname(filePath), { recursive: true });
|
|
8237
|
+
const wrappedContent = wrapWithMarkers(content);
|
|
8238
|
+
let existing = "";
|
|
8239
|
+
try {
|
|
8240
|
+
existing = await fs3.promises.readFile(filePath, "utf8");
|
|
8241
|
+
} catch {
|
|
8242
|
+
}
|
|
8243
|
+
if (!existing) {
|
|
8244
|
+
await fs3.promises.writeFile(filePath, wrappedContent + "\n", "utf8");
|
|
8245
|
+
return "created";
|
|
8246
|
+
}
|
|
8247
|
+
const startIdx = existing.indexOf(CONTEXTSTREAM_START_MARKER);
|
|
8248
|
+
const endIdx = existing.indexOf(CONTEXTSTREAM_END_MARKER);
|
|
8249
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
8250
|
+
const before = existing.substring(0, startIdx);
|
|
8251
|
+
const after = existing.substring(endIdx + CONTEXTSTREAM_END_MARKER.length);
|
|
8252
|
+
const updated = before.trimEnd() + "\n\n" + wrappedContent + "\n" + after.trimStart();
|
|
8253
|
+
await fs3.promises.writeFile(filePath, updated.trim() + "\n", "utf8");
|
|
8254
|
+
return "updated";
|
|
8255
|
+
}
|
|
8256
|
+
const joined = existing.trimEnd() + "\n\n" + wrappedContent + "\n";
|
|
8257
|
+
await fs3.promises.writeFile(filePath, joined, "utf8");
|
|
8258
|
+
return "appended";
|
|
8259
|
+
}
|
|
8260
|
+
async function writeEditorRules(options) {
|
|
8261
|
+
const editors = options.editors && options.editors.length > 0 ? options.editors : getAvailableEditors();
|
|
8262
|
+
const results = [];
|
|
8263
|
+
for (const editor of editors) {
|
|
8264
|
+
const rule = generateRuleContent(editor, {
|
|
8265
|
+
workspaceName: options.workspaceName,
|
|
8266
|
+
workspaceId: options.workspaceId,
|
|
8267
|
+
projectName: options.projectName,
|
|
8268
|
+
additionalRules: options.additionalRules,
|
|
8269
|
+
mode: options.mode
|
|
8270
|
+
});
|
|
8271
|
+
if (!rule) {
|
|
8272
|
+
results.push({ editor, filename: "", status: "unknown editor" });
|
|
8273
|
+
continue;
|
|
8274
|
+
}
|
|
8275
|
+
const filePath = path4.join(options.folderPath, rule.filename);
|
|
8276
|
+
try {
|
|
8277
|
+
const status = await upsertRuleFile(filePath, rule.content);
|
|
8278
|
+
results.push({ editor, filename: rule.filename, status });
|
|
8279
|
+
} catch (err) {
|
|
8280
|
+
results.push({
|
|
8281
|
+
editor,
|
|
8282
|
+
filename: rule.filename,
|
|
8283
|
+
status: `error: ${err.message}`
|
|
8284
|
+
});
|
|
8285
|
+
}
|
|
8286
|
+
}
|
|
8287
|
+
for (const key of rulesNoticeCache.keys()) {
|
|
8288
|
+
if (key.startsWith(`${options.folderPath}|`)) {
|
|
8289
|
+
rulesNoticeCache.delete(key);
|
|
8290
|
+
}
|
|
8291
|
+
}
|
|
8292
|
+
return results;
|
|
8293
|
+
}
|
|
8045
8294
|
var WRITE_VERBS = /* @__PURE__ */ new Set([
|
|
8046
8295
|
"create",
|
|
8047
8296
|
"update",
|
|
@@ -9766,30 +10015,13 @@ Access: Free`,
|
|
|
9766
10015
|
};
|
|
9767
10016
|
fs3.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
9768
10017
|
if (input.generate_editor_rules) {
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
try {
|
|
9777
|
-
let existingContent = "";
|
|
9778
|
-
try {
|
|
9779
|
-
existingContent = fs3.readFileSync(filePath, "utf-8");
|
|
9780
|
-
} catch {
|
|
9781
|
-
}
|
|
9782
|
-
if (!existingContent) {
|
|
9783
|
-
fs3.writeFileSync(filePath, rule.content);
|
|
9784
|
-
rulesGenerated.push(rule.filename);
|
|
9785
|
-
} else if (!existingContent.includes("ContextStream")) {
|
|
9786
|
-
fs3.writeFileSync(filePath, existingContent + "\n\n" + rule.content);
|
|
9787
|
-
rulesGenerated.push(rule.filename + " (appended)");
|
|
9788
|
-
}
|
|
9789
|
-
} catch {
|
|
9790
|
-
}
|
|
9791
|
-
}
|
|
9792
|
-
}
|
|
10018
|
+
const ruleResults = await writeEditorRules({
|
|
10019
|
+
folderPath: input.folder_path,
|
|
10020
|
+
editors: getAvailableEditors(),
|
|
10021
|
+
workspaceId,
|
|
10022
|
+
projectName: input.name
|
|
10023
|
+
});
|
|
10024
|
+
rulesGenerated = ruleResults.filter((r) => r.status === "created" || r.status === "updated" || r.status === "appended").map((r) => r.status === "created" ? r.filename : `${r.filename} (${r.status})`);
|
|
9793
10025
|
}
|
|
9794
10026
|
} catch (err) {
|
|
9795
10027
|
console.error("[ContextStream] Failed to write project config:", err);
|
|
@@ -10738,6 +10970,25 @@ This does semantic search on the first message. You only need context_smart on s
|
|
|
10738
10970
|
if (sessionManager) {
|
|
10739
10971
|
sessionManager.markInitialized(result);
|
|
10740
10972
|
}
|
|
10973
|
+
const folderPathForRules = input.folder_path || ideRoots[0] || resolveFolderPath(void 0, sessionManager);
|
|
10974
|
+
if (sessionManager && folderPathForRules) {
|
|
10975
|
+
sessionManager.setFolderPath(folderPathForRules);
|
|
10976
|
+
}
|
|
10977
|
+
let rulesNotice = null;
|
|
10978
|
+
if (folderPathForRules || detectedClientInfo?.name) {
|
|
10979
|
+
rulesNotice = getRulesNotice(folderPathForRules, detectedClientInfo?.name);
|
|
10980
|
+
if (rulesNotice) {
|
|
10981
|
+
result.rules_notice = rulesNotice;
|
|
10982
|
+
}
|
|
10983
|
+
}
|
|
10984
|
+
let versionNotice = null;
|
|
10985
|
+
try {
|
|
10986
|
+
versionNotice = await getUpdateNotice();
|
|
10987
|
+
} catch {
|
|
10988
|
+
}
|
|
10989
|
+
if (versionNotice) {
|
|
10990
|
+
result.version_notice = versionNotice;
|
|
10991
|
+
}
|
|
10741
10992
|
const workspaceId = typeof result.workspace_id === "string" ? result.workspace_id : void 0;
|
|
10742
10993
|
if (workspaceId && AUTO_HIDE_INTEGRATIONS) {
|
|
10743
10994
|
try {
|
|
@@ -10809,6 +11060,19 @@ This does semantic search on the first message. You only need context_smart on s
|
|
|
10809
11060
|
} else if (workspaceWarning) {
|
|
10810
11061
|
text = [`Warning: ${workspaceWarning}`, "", formatContent(result)].join("\n");
|
|
10811
11062
|
}
|
|
11063
|
+
const noticeLines = [];
|
|
11064
|
+
if (rulesNotice) {
|
|
11065
|
+
const current = rulesNotice.current ?? "unknown";
|
|
11066
|
+
noticeLines.push(`[RULES_NOTICE] status=${rulesNotice.status} current=${current} latest=${rulesNotice.latest} update="${rulesNotice.update_command}"`);
|
|
11067
|
+
}
|
|
11068
|
+
if (versionNotice?.behind) {
|
|
11069
|
+
noticeLines.push(`[VERSION_NOTICE] current=${versionNotice.current} latest=${versionNotice.latest} upgrade="${versionNotice.upgrade_command}"`);
|
|
11070
|
+
}
|
|
11071
|
+
if (noticeLines.length > 0) {
|
|
11072
|
+
text = `${text}
|
|
11073
|
+
|
|
11074
|
+
${noticeLines.join("\n")}`;
|
|
11075
|
+
}
|
|
10812
11076
|
return { content: [{ type: "text", text }], structuredContent: toStructured(result) };
|
|
10813
11077
|
}
|
|
10814
11078
|
);
|
|
@@ -10898,32 +11162,13 @@ Optionally generates AI editor rules for automatic ContextStream usage.`,
|
|
|
10898
11162
|
const result = await client.associateWorkspace(input);
|
|
10899
11163
|
let rulesGenerated = [];
|
|
10900
11164
|
if (input.generate_editor_rules) {
|
|
10901
|
-
const
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
if (rule) {
|
|
10909
|
-
const filePath = path7.join(input.folder_path, rule.filename);
|
|
10910
|
-
try {
|
|
10911
|
-
let existingContent = "";
|
|
10912
|
-
try {
|
|
10913
|
-
existingContent = fs6.readFileSync(filePath, "utf-8");
|
|
10914
|
-
} catch {
|
|
10915
|
-
}
|
|
10916
|
-
if (!existingContent) {
|
|
10917
|
-
fs6.writeFileSync(filePath, rule.content);
|
|
10918
|
-
rulesGenerated.push(rule.filename);
|
|
10919
|
-
} else if (!existingContent.includes("ContextStream Integration")) {
|
|
10920
|
-
fs6.writeFileSync(filePath, existingContent + "\n\n" + rule.content);
|
|
10921
|
-
rulesGenerated.push(rule.filename + " (appended)");
|
|
10922
|
-
}
|
|
10923
|
-
} catch {
|
|
10924
|
-
}
|
|
10925
|
-
}
|
|
10926
|
-
}
|
|
11165
|
+
const ruleResults = await writeEditorRules({
|
|
11166
|
+
folderPath: input.folder_path,
|
|
11167
|
+
editors: getAvailableEditors(),
|
|
11168
|
+
workspaceName: input.workspace_name,
|
|
11169
|
+
workspaceId: input.workspace_id
|
|
11170
|
+
});
|
|
11171
|
+
rulesGenerated = ruleResults.filter((r) => r.status === "created" || r.status === "updated" || r.status === "appended").map((r) => r.status === "created" ? r.filename : `${r.filename} (${r.status})`);
|
|
10927
11172
|
}
|
|
10928
11173
|
const response = {
|
|
10929
11174
|
...result,
|
|
@@ -11003,31 +11248,13 @@ Behavior:
|
|
|
11003
11248
|
});
|
|
11004
11249
|
let rulesGenerated = [];
|
|
11005
11250
|
if (input.generate_editor_rules) {
|
|
11006
|
-
const
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
if (!rule) continue;
|
|
11014
|
-
const filePath = path7.join(folderPath, rule.filename);
|
|
11015
|
-
try {
|
|
11016
|
-
let existingContent = "";
|
|
11017
|
-
try {
|
|
11018
|
-
existingContent = fs6.readFileSync(filePath, "utf-8");
|
|
11019
|
-
} catch {
|
|
11020
|
-
}
|
|
11021
|
-
if (!existingContent) {
|
|
11022
|
-
fs6.writeFileSync(filePath, rule.content);
|
|
11023
|
-
rulesGenerated.push(rule.filename);
|
|
11024
|
-
} else if (!existingContent.includes("ContextStream Integration")) {
|
|
11025
|
-
fs6.writeFileSync(filePath, existingContent + "\n\n" + rule.content);
|
|
11026
|
-
rulesGenerated.push(rule.filename + " (appended)");
|
|
11027
|
-
}
|
|
11028
|
-
} catch {
|
|
11029
|
-
}
|
|
11030
|
-
}
|
|
11251
|
+
const ruleResults = await writeEditorRules({
|
|
11252
|
+
folderPath,
|
|
11253
|
+
editors: getAvailableEditors(),
|
|
11254
|
+
workspaceName: newWorkspace.name || input.workspace_name,
|
|
11255
|
+
workspaceId: newWorkspace.id
|
|
11256
|
+
});
|
|
11257
|
+
rulesGenerated = ruleResults.filter((r) => r.status === "created" || r.status === "updated" || r.status === "appended").map((r) => r.status === "created" ? r.filename : `${r.filename} (${r.status})`);
|
|
11031
11258
|
}
|
|
11032
11259
|
const session = await client.initSession(
|
|
11033
11260
|
{
|
|
@@ -11432,7 +11659,7 @@ Example: "What were the auth decisions?" or "What are my TypeScript preferences?
|
|
|
11432
11659
|
These rules instruct the AI to automatically use ContextStream for memory and context.
|
|
11433
11660
|
Supported editors: ${getAvailableEditors().join(", ")}`,
|
|
11434
11661
|
inputSchema: external_exports.object({
|
|
11435
|
-
folder_path: external_exports.string().describe("Absolute path to the project folder"),
|
|
11662
|
+
folder_path: external_exports.string().optional().describe("Absolute path to the project folder (defaults to IDE root/cwd)"),
|
|
11436
11663
|
editors: external_exports.array(external_exports.enum(["codex", "windsurf", "cursor", "cline", "kilo", "roo", "claude", "aider", "all"])).optional().describe("Which editors to generate rules for. Defaults to all."),
|
|
11437
11664
|
workspace_name: external_exports.string().optional().describe("Workspace name to include in rules"),
|
|
11438
11665
|
workspace_id: external_exports.string().uuid().optional().describe("Workspace ID to include in rules"),
|
|
@@ -11443,58 +11670,48 @@ Supported editors: ${getAvailableEditors().join(", ")}`,
|
|
|
11443
11670
|
})
|
|
11444
11671
|
},
|
|
11445
11672
|
async (input) => {
|
|
11446
|
-
const
|
|
11447
|
-
|
|
11673
|
+
const folderPath = resolveFolderPath(input.folder_path, sessionManager);
|
|
11674
|
+
if (!folderPath) {
|
|
11675
|
+
return errorResult("Error: folder_path is required. Provide folder_path or run from a project directory.");
|
|
11676
|
+
}
|
|
11448
11677
|
const editors = input.editors?.includes("all") || !input.editors ? getAvailableEditors() : input.editors.filter((e) => e !== "all");
|
|
11449
11678
|
const results = [];
|
|
11450
|
-
|
|
11451
|
-
const
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
if (input.dry_run) {
|
|
11679
|
+
if (input.dry_run) {
|
|
11680
|
+
for (const editor of editors) {
|
|
11681
|
+
const rule = generateRuleContent(editor, {
|
|
11682
|
+
workspaceName: input.workspace_name,
|
|
11683
|
+
workspaceId: input.workspace_id,
|
|
11684
|
+
projectName: input.project_name,
|
|
11685
|
+
additionalRules: input.additional_rules,
|
|
11686
|
+
mode: input.mode
|
|
11687
|
+
});
|
|
11688
|
+
if (!rule) {
|
|
11689
|
+
results.push({ editor, filename: "", status: "unknown editor" });
|
|
11690
|
+
continue;
|
|
11691
|
+
}
|
|
11464
11692
|
results.push({
|
|
11465
11693
|
editor,
|
|
11466
11694
|
filename: rule.filename,
|
|
11467
|
-
status: "dry run - would
|
|
11695
|
+
status: "dry run - would update",
|
|
11468
11696
|
content: rule.content
|
|
11469
11697
|
});
|
|
11470
|
-
} else {
|
|
11471
|
-
try {
|
|
11472
|
-
let existingContent = "";
|
|
11473
|
-
try {
|
|
11474
|
-
existingContent = fs6.readFileSync(filePath, "utf-8");
|
|
11475
|
-
} catch {
|
|
11476
|
-
}
|
|
11477
|
-
if (existingContent && !existingContent.includes("ContextStream Integration")) {
|
|
11478
|
-
const updatedContent = existingContent + "\n\n" + rule.content;
|
|
11479
|
-
fs6.writeFileSync(filePath, updatedContent);
|
|
11480
|
-
results.push({ editor, filename: rule.filename, status: "appended to existing" });
|
|
11481
|
-
} else {
|
|
11482
|
-
fs6.writeFileSync(filePath, rule.content);
|
|
11483
|
-
results.push({ editor, filename: rule.filename, status: "created" });
|
|
11484
|
-
}
|
|
11485
|
-
} catch (err) {
|
|
11486
|
-
results.push({
|
|
11487
|
-
editor,
|
|
11488
|
-
filename: rule.filename,
|
|
11489
|
-
status: `error: ${err.message}`
|
|
11490
|
-
});
|
|
11491
|
-
}
|
|
11492
11698
|
}
|
|
11699
|
+
} else {
|
|
11700
|
+
const writeResults = await writeEditorRules({
|
|
11701
|
+
folderPath,
|
|
11702
|
+
editors,
|
|
11703
|
+
workspaceName: input.workspace_name,
|
|
11704
|
+
workspaceId: input.workspace_id,
|
|
11705
|
+
projectName: input.project_name,
|
|
11706
|
+
additionalRules: input.additional_rules,
|
|
11707
|
+
mode: input.mode
|
|
11708
|
+
});
|
|
11709
|
+
results.push(...writeResults);
|
|
11493
11710
|
}
|
|
11494
11711
|
const summary = {
|
|
11495
|
-
folder:
|
|
11712
|
+
folder: folderPath,
|
|
11496
11713
|
results,
|
|
11497
|
-
message: input.dry_run ? "Dry run complete. Use dry_run: false to write files." : `Generated ${results.filter((r) => r.status === "created" || r.status.
|
|
11714
|
+
message: input.dry_run ? "Dry run complete. Use dry_run: false to write files." : `Generated ${results.filter((r) => r.status === "created" || r.status === "updated" || r.status === "appended").length} rule files.`
|
|
11498
11715
|
};
|
|
11499
11716
|
return { content: [{ type: "text", text: formatContent(summary) }], structuredContent: toStructured(summary) };
|
|
11500
11717
|
}
|
|
@@ -11768,11 +11985,27 @@ This saves ~80% tokens compared to including full chat history.`,
|
|
|
11768
11985
|
const footer = `
|
|
11769
11986
|
---
|
|
11770
11987
|
\u{1F3AF} ${result.sources_used} sources | ~${result.token_estimate} tokens | format: ${result.format}`;
|
|
11771
|
-
const
|
|
11772
|
-
|
|
11988
|
+
const folderPathForRules = resolveFolderPath(void 0, sessionManager);
|
|
11989
|
+
const rulesNotice = getRulesNotice(folderPathForRules, detectedClientInfo?.name);
|
|
11990
|
+
let versionNotice = result.version_notice;
|
|
11991
|
+
if (!versionNotice) {
|
|
11992
|
+
try {
|
|
11993
|
+
versionNotice = await getUpdateNotice();
|
|
11994
|
+
} catch {
|
|
11995
|
+
}
|
|
11996
|
+
}
|
|
11997
|
+
const rulesNoticeLine = rulesNotice ? `
|
|
11998
|
+
[RULES_NOTICE] status=${rulesNotice.status} current=${rulesNotice.current ?? "unknown"} latest=${rulesNotice.latest} update="${rulesNotice.update_command}"` : "";
|
|
11999
|
+
const versionNoticeLine = versionNotice?.behind ? `
|
|
12000
|
+
[VERSION_NOTICE] current=${versionNotice.current} latest=${versionNotice.latest} upgrade="${versionNotice.upgrade_command}"` : "";
|
|
12001
|
+
const enrichedResult = {
|
|
12002
|
+
...result,
|
|
12003
|
+
...rulesNotice ? { rules_notice: rulesNotice } : {},
|
|
12004
|
+
...versionNotice ? { version_notice: versionNotice } : {}
|
|
12005
|
+
};
|
|
11773
12006
|
return {
|
|
11774
|
-
content: [{ type: "text", text: result.context + footer + versionNoticeLine }],
|
|
11775
|
-
structuredContent: toStructured(
|
|
12007
|
+
content: [{ type: "text", text: result.context + footer + rulesNoticeLine + versionNoticeLine }],
|
|
12008
|
+
structuredContent: toStructured(enrichedResult)
|
|
11776
12009
|
};
|
|
11777
12010
|
}
|
|
11778
12011
|
);
|
|
@@ -14827,6 +15060,12 @@ var SessionManager = class {
|
|
|
14827
15060
|
getContext() {
|
|
14828
15061
|
return this.context;
|
|
14829
15062
|
}
|
|
15063
|
+
/**
|
|
15064
|
+
* Get the current folder path (if known)
|
|
15065
|
+
*/
|
|
15066
|
+
getFolderPath() {
|
|
15067
|
+
return this.folderPath;
|
|
15068
|
+
}
|
|
14830
15069
|
/**
|
|
14831
15070
|
* Mark session as manually initialized (e.g., when session_init is called explicitly)
|
|
14832
15071
|
*/
|
|
@@ -14838,6 +15077,10 @@ var SessionManager = class {
|
|
|
14838
15077
|
if (workspaceId || projectId) {
|
|
14839
15078
|
this.client.setDefaults({ workspace_id: workspaceId, project_id: projectId });
|
|
14840
15079
|
}
|
|
15080
|
+
const contextFolderPath = typeof context.folder_path === "string" ? context.folder_path : void 0;
|
|
15081
|
+
if (contextFolderPath) {
|
|
15082
|
+
this.folderPath = contextFolderPath;
|
|
15083
|
+
}
|
|
14841
15084
|
}
|
|
14842
15085
|
/**
|
|
14843
15086
|
* Set the folder path hint (can be passed from tools that know the workspace path)
|
|
@@ -14929,6 +15172,9 @@ var SessionManager = class {
|
|
|
14929
15172
|
if (this.ideRoots.length === 0 && this.folderPath) {
|
|
14930
15173
|
this.ideRoots = [this.folderPath];
|
|
14931
15174
|
}
|
|
15175
|
+
if (this.ideRoots.length > 0) {
|
|
15176
|
+
this.folderPath = this.ideRoots[0];
|
|
15177
|
+
}
|
|
14932
15178
|
this.initializationPromise = this._doInitialize();
|
|
14933
15179
|
try {
|
|
14934
15180
|
const result = await this.initializationPromise;
|
|
@@ -15374,25 +15620,25 @@ async function runHttpGateway() {
|
|
|
15374
15620
|
|
|
15375
15621
|
// src/index.ts
|
|
15376
15622
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
15377
|
-
import { homedir as
|
|
15623
|
+
import { homedir as homedir5 } from "os";
|
|
15378
15624
|
import { join as join8 } from "path";
|
|
15379
15625
|
|
|
15380
15626
|
// src/setup.ts
|
|
15381
15627
|
import * as fs5 from "node:fs/promises";
|
|
15382
15628
|
import * as path6 from "node:path";
|
|
15383
|
-
import { homedir as
|
|
15629
|
+
import { homedir as homedir4 } from "node:os";
|
|
15384
15630
|
import { stdin, stdout } from "node:process";
|
|
15385
15631
|
import { createInterface } from "node:readline/promises";
|
|
15386
15632
|
|
|
15387
15633
|
// src/credentials.ts
|
|
15388
15634
|
import * as fs4 from "node:fs/promises";
|
|
15389
15635
|
import * as path5 from "node:path";
|
|
15390
|
-
import { homedir as
|
|
15636
|
+
import { homedir as homedir3 } from "node:os";
|
|
15391
15637
|
function normalizeApiUrl(input) {
|
|
15392
15638
|
return String(input ?? "").trim().replace(/\/+$/, "");
|
|
15393
15639
|
}
|
|
15394
15640
|
function credentialsFilePath() {
|
|
15395
|
-
return path5.join(
|
|
15641
|
+
return path5.join(homedir3(), ".contextstream", "credentials.json");
|
|
15396
15642
|
}
|
|
15397
15643
|
function isRecord(value) {
|
|
15398
15644
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -15490,27 +15736,27 @@ async function fileExists(filePath) {
|
|
|
15490
15736
|
return false;
|
|
15491
15737
|
}
|
|
15492
15738
|
}
|
|
15493
|
-
var
|
|
15494
|
-
var
|
|
15495
|
-
function
|
|
15496
|
-
return `${
|
|
15739
|
+
var CONTEXTSTREAM_START_MARKER2 = "<!-- BEGIN ContextStream -->";
|
|
15740
|
+
var CONTEXTSTREAM_END_MARKER2 = "<!-- END ContextStream -->";
|
|
15741
|
+
function wrapWithMarkers2(content) {
|
|
15742
|
+
return `${CONTEXTSTREAM_START_MARKER2}
|
|
15497
15743
|
${content.trim()}
|
|
15498
|
-
${
|
|
15744
|
+
${CONTEXTSTREAM_END_MARKER2}`;
|
|
15499
15745
|
}
|
|
15500
15746
|
async function upsertTextFile(filePath, content, _marker) {
|
|
15501
15747
|
await fs5.mkdir(path6.dirname(filePath), { recursive: true });
|
|
15502
15748
|
const exists = await fileExists(filePath);
|
|
15503
|
-
const wrappedContent =
|
|
15749
|
+
const wrappedContent = wrapWithMarkers2(content);
|
|
15504
15750
|
if (!exists) {
|
|
15505
15751
|
await fs5.writeFile(filePath, wrappedContent + "\n", "utf8");
|
|
15506
15752
|
return "created";
|
|
15507
15753
|
}
|
|
15508
15754
|
const existing = await fs5.readFile(filePath, "utf8").catch(() => "");
|
|
15509
|
-
const startIdx = existing.indexOf(
|
|
15510
|
-
const endIdx = existing.indexOf(
|
|
15755
|
+
const startIdx = existing.indexOf(CONTEXTSTREAM_START_MARKER2);
|
|
15756
|
+
const endIdx = existing.indexOf(CONTEXTSTREAM_END_MARKER2);
|
|
15511
15757
|
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
15512
15758
|
const before = existing.substring(0, startIdx);
|
|
15513
|
-
const after = existing.substring(endIdx +
|
|
15759
|
+
const after = existing.substring(endIdx + CONTEXTSTREAM_END_MARKER2.length);
|
|
15514
15760
|
const updated = before.trimEnd() + "\n\n" + wrappedContent + "\n" + after.trimStart();
|
|
15515
15761
|
await fs5.writeFile(filePath, updated.trim() + "\n", "utf8");
|
|
15516
15762
|
return "updated";
|
|
@@ -15525,7 +15771,7 @@ async function upsertTextFile(filePath, content, _marker) {
|
|
|
15525
15771
|
return "appended";
|
|
15526
15772
|
}
|
|
15527
15773
|
function globalRulesPathForEditor(editor) {
|
|
15528
|
-
const home =
|
|
15774
|
+
const home = homedir4();
|
|
15529
15775
|
switch (editor) {
|
|
15530
15776
|
case "codex":
|
|
15531
15777
|
return path6.join(home, ".codex", "AGENTS.md");
|
|
@@ -15554,7 +15800,7 @@ async function anyPathExists(paths) {
|
|
|
15554
15800
|
return false;
|
|
15555
15801
|
}
|
|
15556
15802
|
async function isCodexInstalled() {
|
|
15557
|
-
const home =
|
|
15803
|
+
const home = homedir4();
|
|
15558
15804
|
const envHome = process.env.CODEX_HOME;
|
|
15559
15805
|
const candidates = [
|
|
15560
15806
|
envHome,
|
|
@@ -15565,7 +15811,7 @@ async function isCodexInstalled() {
|
|
|
15565
15811
|
return anyPathExists(candidates);
|
|
15566
15812
|
}
|
|
15567
15813
|
async function isClaudeInstalled() {
|
|
15568
|
-
const home =
|
|
15814
|
+
const home = homedir4();
|
|
15569
15815
|
const candidates = [
|
|
15570
15816
|
path6.join(home, ".claude"),
|
|
15571
15817
|
path6.join(home, ".config", "claude")
|
|
@@ -15581,7 +15827,7 @@ async function isClaudeInstalled() {
|
|
|
15581
15827
|
return anyPathExists(candidates);
|
|
15582
15828
|
}
|
|
15583
15829
|
async function isWindsurfInstalled() {
|
|
15584
|
-
const home =
|
|
15830
|
+
const home = homedir4();
|
|
15585
15831
|
const candidates = [
|
|
15586
15832
|
path6.join(home, ".codeium"),
|
|
15587
15833
|
path6.join(home, ".codeium", "windsurf"),
|
|
@@ -15600,7 +15846,7 @@ async function isWindsurfInstalled() {
|
|
|
15600
15846
|
return anyPathExists(candidates);
|
|
15601
15847
|
}
|
|
15602
15848
|
async function isClineInstalled() {
|
|
15603
|
-
const home =
|
|
15849
|
+
const home = homedir4();
|
|
15604
15850
|
const candidates = [
|
|
15605
15851
|
path6.join(home, "Documents", "Cline"),
|
|
15606
15852
|
path6.join(home, ".cline"),
|
|
@@ -15609,7 +15855,7 @@ async function isClineInstalled() {
|
|
|
15609
15855
|
return anyPathExists(candidates);
|
|
15610
15856
|
}
|
|
15611
15857
|
async function isKiloInstalled() {
|
|
15612
|
-
const home =
|
|
15858
|
+
const home = homedir4();
|
|
15613
15859
|
const candidates = [
|
|
15614
15860
|
path6.join(home, ".kilocode"),
|
|
15615
15861
|
path6.join(home, ".config", "kilocode")
|
|
@@ -15617,7 +15863,7 @@ async function isKiloInstalled() {
|
|
|
15617
15863
|
return anyPathExists(candidates);
|
|
15618
15864
|
}
|
|
15619
15865
|
async function isRooInstalled() {
|
|
15620
|
-
const home =
|
|
15866
|
+
const home = homedir4();
|
|
15621
15867
|
const candidates = [
|
|
15622
15868
|
path6.join(home, ".roo"),
|
|
15623
15869
|
path6.join(home, ".config", "roo")
|
|
@@ -15625,7 +15871,7 @@ async function isRooInstalled() {
|
|
|
15625
15871
|
return anyPathExists(candidates);
|
|
15626
15872
|
}
|
|
15627
15873
|
async function isAiderInstalled() {
|
|
15628
|
-
const home =
|
|
15874
|
+
const home = homedir4();
|
|
15629
15875
|
const candidates = [
|
|
15630
15876
|
path6.join(home, ".aider.conf.yml"),
|
|
15631
15877
|
path6.join(home, ".config", "aider")
|
|
@@ -15633,7 +15879,7 @@ async function isAiderInstalled() {
|
|
|
15633
15879
|
return anyPathExists(candidates);
|
|
15634
15880
|
}
|
|
15635
15881
|
async function isCursorInstalled() {
|
|
15636
|
-
const home =
|
|
15882
|
+
const home = homedir4();
|
|
15637
15883
|
const candidates = [path6.join(home, ".cursor")];
|
|
15638
15884
|
if (process.platform === "darwin") {
|
|
15639
15885
|
candidates.push("/Applications/Cursor.app");
|
|
@@ -15781,7 +16027,7 @@ async function upsertJsonVsCodeMcpConfig(filePath, server) {
|
|
|
15781
16027
|
return before === after ? "skipped" : "updated";
|
|
15782
16028
|
}
|
|
15783
16029
|
function claudeDesktopConfigPath() {
|
|
15784
|
-
const home =
|
|
16030
|
+
const home = homedir4();
|
|
15785
16031
|
if (process.platform === "darwin") {
|
|
15786
16032
|
return path6.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
15787
16033
|
}
|
|
@@ -16185,7 +16431,7 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
|
|
|
16185
16431
|
if (mcpScope === "project" && editor !== "codex") continue;
|
|
16186
16432
|
try {
|
|
16187
16433
|
if (editor === "codex") {
|
|
16188
|
-
const filePath = path6.join(
|
|
16434
|
+
const filePath = path6.join(homedir4(), ".codex", "config.toml");
|
|
16189
16435
|
if (dryRun) {
|
|
16190
16436
|
writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
|
|
16191
16437
|
console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
|
|
@@ -16197,7 +16443,7 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
|
|
|
16197
16443
|
continue;
|
|
16198
16444
|
}
|
|
16199
16445
|
if (editor === "windsurf") {
|
|
16200
|
-
const filePath = path6.join(
|
|
16446
|
+
const filePath = path6.join(homedir4(), ".codeium", "windsurf", "mcp_config.json");
|
|
16201
16447
|
if (dryRun) {
|
|
16202
16448
|
writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
|
|
16203
16449
|
console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
|
|
@@ -16231,7 +16477,7 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
|
|
|
16231
16477
|
continue;
|
|
16232
16478
|
}
|
|
16233
16479
|
if (editor === "cursor") {
|
|
16234
|
-
const filePath = path6.join(
|
|
16480
|
+
const filePath = path6.join(homedir4(), ".cursor", "mcp.json");
|
|
16235
16481
|
if (dryRun) {
|
|
16236
16482
|
writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
|
|
16237
16483
|
console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
|
|
@@ -16458,7 +16704,7 @@ Applying to ${projects.length} project(s)...`);
|
|
|
16458
16704
|
// src/index.ts
|
|
16459
16705
|
var ENABLE_PROMPTS2 = (process.env.CONTEXTSTREAM_ENABLE_PROMPTS || "true").toLowerCase() !== "false";
|
|
16460
16706
|
function showFirstRunMessage() {
|
|
16461
|
-
const configDir = join8(
|
|
16707
|
+
const configDir = join8(homedir5(), ".contextstream");
|
|
16462
16708
|
const starShownFile = join8(configDir, ".star-shown");
|
|
16463
16709
|
if (existsSync4(starShownFile)) {
|
|
16464
16710
|
return;
|
package/dist/test-server.js
CHANGED
|
@@ -4050,6 +4050,21 @@ var coerce = {
|
|
|
4050
4050
|
};
|
|
4051
4051
|
var NEVER = INVALID;
|
|
4052
4052
|
|
|
4053
|
+
// src/version.ts
|
|
4054
|
+
import { createRequire } from "module";
|
|
4055
|
+
function getVersion() {
|
|
4056
|
+
try {
|
|
4057
|
+
const require2 = createRequire(import.meta.url);
|
|
4058
|
+
const pkg = require2("../package.json");
|
|
4059
|
+
const version = pkg?.version;
|
|
4060
|
+
if (typeof version === "string" && version.trim()) return version.trim();
|
|
4061
|
+
} catch {
|
|
4062
|
+
}
|
|
4063
|
+
return "unknown";
|
|
4064
|
+
}
|
|
4065
|
+
var VERSION = getVersion();
|
|
4066
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4067
|
+
|
|
4053
4068
|
// src/config.ts
|
|
4054
4069
|
var DEFAULT_API_URL = "https://api.contextstream.io";
|
|
4055
4070
|
function parseBooleanEnv(value) {
|
|
@@ -4065,7 +4080,7 @@ var configSchema = external_exports.object({
|
|
|
4065
4080
|
jwt: external_exports.string().min(1).optional(),
|
|
4066
4081
|
defaultWorkspaceId: external_exports.string().uuid().optional(),
|
|
4067
4082
|
defaultProjectId: external_exports.string().uuid().optional(),
|
|
4068
|
-
userAgent: external_exports.string().default(
|
|
4083
|
+
userAgent: external_exports.string().default(`contextstream-mcp/${VERSION}`),
|
|
4069
4084
|
allowHeaderAuth: external_exports.boolean().optional(),
|
|
4070
4085
|
contextPackEnabled: external_exports.boolean().default(true)
|
|
4071
4086
|
});
|
|
@@ -4097,21 +4112,6 @@ function loadConfig() {
|
|
|
4097
4112
|
return parsed.data;
|
|
4098
4113
|
}
|
|
4099
4114
|
|
|
4100
|
-
// src/version.ts
|
|
4101
|
-
import { createRequire } from "module";
|
|
4102
|
-
function getVersion() {
|
|
4103
|
-
try {
|
|
4104
|
-
const require2 = createRequire(import.meta.url);
|
|
4105
|
-
const pkg = require2("../package.json");
|
|
4106
|
-
const version = pkg?.version;
|
|
4107
|
-
if (typeof version === "string" && version.trim()) return version.trim();
|
|
4108
|
-
} catch {
|
|
4109
|
-
}
|
|
4110
|
-
return "unknown";
|
|
4111
|
-
}
|
|
4112
|
-
var VERSION = getVersion();
|
|
4113
|
-
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4114
|
-
|
|
4115
4115
|
// src/test-server.ts
|
|
4116
4116
|
var PORT = parseInt(process.env.MCP_TEST_PORT || "3099", 10);
|
|
4117
4117
|
var pendingRequests = /* @__PURE__ */ new Map();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contextstream/mcp-server",
|
|
3
3
|
"mcpName": "io.github.contextstreamio/mcp-server",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.17",
|
|
5
5
|
"description": "ContextStream MCP server - v0.4.x with consolidated domain tools (~11 tools, ~75% token reduction). Code context, memory, search, and AI tools.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|