@contextstream/mcp-server 0.3.19 → 0.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -334
- package/dist/index.js +984 -230
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4611,7 +4611,9 @@ var CacheTTL = {
|
|
|
4611
4611
|
// Search results - cache for 60 seconds
|
|
4612
4612
|
SEARCH: 60 * 1e3,
|
|
4613
4613
|
// User preferences - cache for 5 minutes
|
|
4614
|
-
USER_PREFS: 5 * 60 * 1e3
|
|
4614
|
+
USER_PREFS: 5 * 60 * 1e3,
|
|
4615
|
+
// Credits/plan - cache briefly to reflect upgrades quickly
|
|
4616
|
+
CREDIT_BALANCE: 60 * 1e3
|
|
4615
4617
|
};
|
|
4616
4618
|
var CacheKeys = {
|
|
4617
4619
|
workspace: (id) => `workspace:${id}`,
|
|
@@ -4620,7 +4622,8 @@ var CacheKeys = {
|
|
|
4620
4622
|
projectList: (workspaceId) => `projects:${workspaceId}`,
|
|
4621
4623
|
sessionInit: (workspaceId, projectId) => `session_init:${workspaceId || ""}:${projectId || ""}`,
|
|
4622
4624
|
memoryEvents: (workspaceId) => `memory:${workspaceId}`,
|
|
4623
|
-
search: (query, workspaceId) => `search:${workspaceId || ""}:${query}
|
|
4625
|
+
search: (query, workspaceId) => `search:${workspaceId || ""}:${query}`,
|
|
4626
|
+
creditBalance: () => "credits:balance"
|
|
4624
4627
|
};
|
|
4625
4628
|
var globalCache = new MemoryCache();
|
|
4626
4629
|
|
|
@@ -4666,6 +4669,25 @@ var ContextStreamClient = class {
|
|
|
4666
4669
|
me() {
|
|
4667
4670
|
return request(this.config, "/auth/me");
|
|
4668
4671
|
}
|
|
4672
|
+
// Credits / Billing (used for plan gating)
|
|
4673
|
+
async getCreditBalance() {
|
|
4674
|
+
const cacheKey = CacheKeys.creditBalance();
|
|
4675
|
+
const cached = globalCache.get(cacheKey);
|
|
4676
|
+
if (cached) return cached;
|
|
4677
|
+
const result = await request(this.config, "/credits/balance", { method: "GET" });
|
|
4678
|
+
const data = result && typeof result === "object" && "data" in result && result.data ? result.data : result;
|
|
4679
|
+
globalCache.set(cacheKey, data, CacheTTL.CREDIT_BALANCE);
|
|
4680
|
+
return data;
|
|
4681
|
+
}
|
|
4682
|
+
async getPlanName() {
|
|
4683
|
+
try {
|
|
4684
|
+
const balance = await this.getCreditBalance();
|
|
4685
|
+
const planName = balance?.plan?.name;
|
|
4686
|
+
return typeof planName === "string" ? planName.toLowerCase() : null;
|
|
4687
|
+
} catch {
|
|
4688
|
+
return null;
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4669
4691
|
// Workspaces & Projects
|
|
4670
4692
|
listWorkspaces(params) {
|
|
4671
4693
|
const query = new URLSearchParams();
|
|
@@ -5053,22 +5075,15 @@ var ContextStreamClient = class {
|
|
|
5053
5075
|
return context;
|
|
5054
5076
|
}
|
|
5055
5077
|
} else {
|
|
5056
|
-
const
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
context.workspace_created = true;
|
|
5066
|
-
writeLocalConfig(rootPath, {
|
|
5067
|
-
workspace_id: newWorkspace.id,
|
|
5068
|
-
workspace_name: newWorkspace.name,
|
|
5069
|
-
associated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5070
|
-
});
|
|
5071
|
-
}
|
|
5078
|
+
const folderDisplayName = rootPath?.split("/").pop() || "this folder";
|
|
5079
|
+
context.status = "requires_workspace_name";
|
|
5080
|
+
context.workspace_source = "none_found";
|
|
5081
|
+
context.ide_roots = ideRoots;
|
|
5082
|
+
context.folder_name = folderDisplayName;
|
|
5083
|
+
context.folder_path = rootPath;
|
|
5084
|
+
context.suggested_project_name = folderDisplayName;
|
|
5085
|
+
context.message = `No workspaces found for this account. Ask the user for a name for a new workspace, then create a project for "${folderDisplayName}".`;
|
|
5086
|
+
return context;
|
|
5072
5087
|
}
|
|
5073
5088
|
} catch (e) {
|
|
5074
5089
|
context.workspace_error = String(e);
|
|
@@ -6237,6 +6252,8 @@ You have access to ContextStream MCP tools for persistent memory and context.
|
|
|
6237
6252
|
| **1st message** | \`session_init(folder_path="...", context_hint="<user's message>")\` |
|
|
6238
6253
|
| **2nd+ messages** | \`context_smart(user_message="<user's message>")\` |
|
|
6239
6254
|
| **After completing task** | \`session_capture(...)\` - MUST capture decisions/insights |
|
|
6255
|
+
| **User frustration/correction** | \`session_capture_lesson(...)\` - MUST capture lessons |
|
|
6256
|
+
| **Command/tool error + fix** | \`session_capture_lesson(...)\` - MUST capture lessons |
|
|
6240
6257
|
|
|
6241
6258
|
**NO EXCEPTIONS.** Do not skip even if you think you have enough context.
|
|
6242
6259
|
|
|
@@ -6292,6 +6309,52 @@ You have access to ContextStream MCP tools for persistent memory and context.
|
|
|
6292
6309
|
|
|
6293
6310
|
---
|
|
6294
6311
|
|
|
6312
|
+
### Lesson Capture (MANDATORY)
|
|
6313
|
+
|
|
6314
|
+
When:
|
|
6315
|
+
1. **Expresses frustration** (caps, profanity, "COME ON", "WTF", repeated corrections)
|
|
6316
|
+
2. **Corrects you** ("No, you should...", "That's wrong", "Fix this")
|
|
6317
|
+
3. **Points out a mistake** (broken code, wrong approach, production issue)
|
|
6318
|
+
4. **A command/tool call fails and you learn the correct fix** (even if the user didn\u2019t explicitly correct you)
|
|
6319
|
+
|
|
6320
|
+
You MUST immediately call \`session_capture_lesson\` with:
|
|
6321
|
+
|
|
6322
|
+
| Field | Description | Example |
|
|
6323
|
+
|-------|-------------|---------|
|
|
6324
|
+
| \`title\` | What to remember | "Verify assets in git before pushing" |
|
|
6325
|
+
| \`severity\` | \`critical\`/\`high\`/\`medium\`/\`low\` | \`critical\` for production issues |
|
|
6326
|
+
| \`category\` | \`workflow\`/\`code_quality\`/\`verification\`/\`communication\`/\`project_specific\` | \`workflow\` |
|
|
6327
|
+
| \`trigger\` | What action caused the problem | "Pushed code referencing images without committing them" |
|
|
6328
|
+
| \`impact\` | What went wrong | "Production 404 errors - broken landing page" |
|
|
6329
|
+
| \`prevention\` | How to prevent in future | "Run git status to check untracked files before pushing" |
|
|
6330
|
+
| \`keywords\` | Keywords for matching | \`["git", "images", "assets", "push"]\` |
|
|
6331
|
+
|
|
6332
|
+
**Example call:**
|
|
6333
|
+
\`\`\`json
|
|
6334
|
+
{
|
|
6335
|
+
"title": "Always verify assets in git before pushing code references",
|
|
6336
|
+
"severity": "critical",
|
|
6337
|
+
"category": "workflow",
|
|
6338
|
+
"trigger": "Pushed code referencing /screenshots/*.png without committing images",
|
|
6339
|
+
"impact": "Production 404 errors - broken landing page",
|
|
6340
|
+
"prevention": "Run 'git status' to check untracked files before pushing code that references static assets",
|
|
6341
|
+
"keywords": ["git", "images", "assets", "push", "404", "static"]
|
|
6342
|
+
}
|
|
6343
|
+
\`\`\`
|
|
6344
|
+
|
|
6345
|
+
**Why this matters:**
|
|
6346
|
+
- Lessons are surfaced automatically in \`session_init\` and \`context_smart\`
|
|
6347
|
+
- Future sessions will warn you before repeating the same mistake
|
|
6348
|
+
- This prevents production issues and user frustration
|
|
6349
|
+
|
|
6350
|
+
**Severity guide:**
|
|
6351
|
+
- \`critical\`: Production outages, data loss, security issues
|
|
6352
|
+
- \`high\`: Breaking changes, significant user impact
|
|
6353
|
+
- \`medium\`: Workflow inefficiencies, minor bugs
|
|
6354
|
+
- \`low\`: Style/preference corrections
|
|
6355
|
+
|
|
6356
|
+
---
|
|
6357
|
+
|
|
6295
6358
|
### Quick Examples
|
|
6296
6359
|
|
|
6297
6360
|
\`\`\`
|
|
@@ -6407,6 +6470,39 @@ function toStructured(data) {
|
|
|
6407
6470
|
return void 0;
|
|
6408
6471
|
}
|
|
6409
6472
|
function registerTools(server, client, sessionManager) {
|
|
6473
|
+
const upgradeUrl2 = process.env.CONTEXTSTREAM_UPGRADE_URL || "https://contextstream.io/pricing";
|
|
6474
|
+
const defaultProTools = /* @__PURE__ */ new Set([
|
|
6475
|
+
// AI endpoints (typically paid/credit-metered)
|
|
6476
|
+
"ai_context",
|
|
6477
|
+
"ai_enhanced_context",
|
|
6478
|
+
"ai_context_budget",
|
|
6479
|
+
"ai_embeddings",
|
|
6480
|
+
"ai_plan",
|
|
6481
|
+
"ai_tasks"
|
|
6482
|
+
]);
|
|
6483
|
+
const proTools = (() => {
|
|
6484
|
+
const raw = process.env.CONTEXTSTREAM_PRO_TOOLS;
|
|
6485
|
+
if (!raw) return defaultProTools;
|
|
6486
|
+
const parsed = raw.split(",").map((t) => t.trim()).filter(Boolean);
|
|
6487
|
+
return parsed.length > 0 ? new Set(parsed) : defaultProTools;
|
|
6488
|
+
})();
|
|
6489
|
+
function getToolAccessTier(toolName) {
|
|
6490
|
+
return proTools.has(toolName) ? "pro" : "free";
|
|
6491
|
+
}
|
|
6492
|
+
function getToolAccessLabel(toolName) {
|
|
6493
|
+
return getToolAccessTier(toolName) === "pro" ? "PRO" : "Free";
|
|
6494
|
+
}
|
|
6495
|
+
async function gateIfProTool(toolName) {
|
|
6496
|
+
if (getToolAccessTier(toolName) !== "pro") return null;
|
|
6497
|
+
const planName = await client.getPlanName();
|
|
6498
|
+
if (planName !== "free") return null;
|
|
6499
|
+
return errorResult(
|
|
6500
|
+
[
|
|
6501
|
+
`Access denied: \`${toolName}\` requires ContextStream PRO.`,
|
|
6502
|
+
`Upgrade: ${upgradeUrl2}`
|
|
6503
|
+
].join("\n")
|
|
6504
|
+
);
|
|
6505
|
+
}
|
|
6410
6506
|
function wrapWithAutoContext(toolName, handler) {
|
|
6411
6507
|
if (!sessionManager) {
|
|
6412
6508
|
return handler;
|
|
@@ -6435,8 +6531,18 @@ function registerTools(server, client, sessionManager) {
|
|
|
6435
6531
|
};
|
|
6436
6532
|
}
|
|
6437
6533
|
function registerTool(name, config, handler) {
|
|
6534
|
+
const accessLabel = getToolAccessLabel(name);
|
|
6535
|
+
const labeledConfig = {
|
|
6536
|
+
...config,
|
|
6537
|
+
title: `${config.title} (${accessLabel})`,
|
|
6538
|
+
description: `${config.description}
|
|
6539
|
+
|
|
6540
|
+
Access: ${accessLabel}${accessLabel === "PRO" ? ` (upgrade: ${upgradeUrl2})` : ""}`
|
|
6541
|
+
};
|
|
6438
6542
|
const safeHandler = async (input) => {
|
|
6439
6543
|
try {
|
|
6544
|
+
const gated = await gateIfProTool(name);
|
|
6545
|
+
if (gated) return gated;
|
|
6440
6546
|
return await handler(input);
|
|
6441
6547
|
} catch (error) {
|
|
6442
6548
|
const errorMessage = error?.message || String(error);
|
|
@@ -6450,10 +6556,26 @@ function registerTools(server, client, sessionManager) {
|
|
|
6450
6556
|
};
|
|
6451
6557
|
server.registerTool(
|
|
6452
6558
|
name,
|
|
6453
|
-
|
|
6559
|
+
labeledConfig,
|
|
6454
6560
|
wrapWithAutoContext(name, safeHandler)
|
|
6455
6561
|
);
|
|
6456
6562
|
}
|
|
6563
|
+
function errorResult(text) {
|
|
6564
|
+
return {
|
|
6565
|
+
content: [{ type: "text", text }],
|
|
6566
|
+
isError: true
|
|
6567
|
+
};
|
|
6568
|
+
}
|
|
6569
|
+
function resolveWorkspaceId(explicitWorkspaceId) {
|
|
6570
|
+
if (explicitWorkspaceId) return explicitWorkspaceId;
|
|
6571
|
+
const ctx = sessionManager?.getContext();
|
|
6572
|
+
return typeof ctx?.workspace_id === "string" ? ctx.workspace_id : void 0;
|
|
6573
|
+
}
|
|
6574
|
+
function resolveProjectId(explicitProjectId) {
|
|
6575
|
+
if (explicitProjectId) return explicitProjectId;
|
|
6576
|
+
const ctx = sessionManager?.getContext();
|
|
6577
|
+
return typeof ctx?.project_id === "string" ? ctx.project_id : void 0;
|
|
6578
|
+
}
|
|
6457
6579
|
registerTool(
|
|
6458
6580
|
"auth_me",
|
|
6459
6581
|
{
|
|
@@ -6590,10 +6712,14 @@ function registerTools(server, client, sessionManager) {
|
|
|
6590
6712
|
{
|
|
6591
6713
|
title: "Index project",
|
|
6592
6714
|
description: "Trigger indexing for a project",
|
|
6593
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
6715
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
6594
6716
|
},
|
|
6595
6717
|
async (input) => {
|
|
6596
|
-
const
|
|
6718
|
+
const projectId = resolveProjectId(input.project_id);
|
|
6719
|
+
if (!projectId) {
|
|
6720
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
6721
|
+
}
|
|
6722
|
+
const result = await client.indexProject(projectId);
|
|
6597
6723
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
6598
6724
|
}
|
|
6599
6725
|
);
|
|
@@ -6943,10 +7069,14 @@ function registerTools(server, client, sessionManager) {
|
|
|
6943
7069
|
{
|
|
6944
7070
|
title: "Get project",
|
|
6945
7071
|
description: "Get project details by ID",
|
|
6946
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7072
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
6947
7073
|
},
|
|
6948
7074
|
async (input) => {
|
|
6949
|
-
const
|
|
7075
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7076
|
+
if (!projectId) {
|
|
7077
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7078
|
+
}
|
|
7079
|
+
const result = await client.getProject(projectId);
|
|
6950
7080
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
6951
7081
|
}
|
|
6952
7082
|
);
|
|
@@ -6955,10 +7085,14 @@ function registerTools(server, client, sessionManager) {
|
|
|
6955
7085
|
{
|
|
6956
7086
|
title: "Project overview",
|
|
6957
7087
|
description: "Get project overview with summary information",
|
|
6958
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7088
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
6959
7089
|
},
|
|
6960
7090
|
async (input) => {
|
|
6961
|
-
const
|
|
7091
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7092
|
+
if (!projectId) {
|
|
7093
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7094
|
+
}
|
|
7095
|
+
const result = await client.projectOverview(projectId);
|
|
6962
7096
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
6963
7097
|
}
|
|
6964
7098
|
);
|
|
@@ -6967,10 +7101,14 @@ function registerTools(server, client, sessionManager) {
|
|
|
6967
7101
|
{
|
|
6968
7102
|
title: "Project statistics",
|
|
6969
7103
|
description: "Get project statistics (files, lines, complexity)",
|
|
6970
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7104
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
6971
7105
|
},
|
|
6972
7106
|
async (input) => {
|
|
6973
|
-
const
|
|
7107
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7108
|
+
if (!projectId) {
|
|
7109
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7110
|
+
}
|
|
7111
|
+
const result = await client.projectStatistics(projectId);
|
|
6974
7112
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
6975
7113
|
}
|
|
6976
7114
|
);
|
|
@@ -6979,10 +7117,14 @@ function registerTools(server, client, sessionManager) {
|
|
|
6979
7117
|
{
|
|
6980
7118
|
title: "List project files",
|
|
6981
7119
|
description: "List all indexed files in a project",
|
|
6982
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7120
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
6983
7121
|
},
|
|
6984
7122
|
async (input) => {
|
|
6985
|
-
const
|
|
7123
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7124
|
+
if (!projectId) {
|
|
7125
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7126
|
+
}
|
|
7127
|
+
const result = await client.projectFiles(projectId);
|
|
6986
7128
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
6987
7129
|
}
|
|
6988
7130
|
);
|
|
@@ -6991,10 +7133,14 @@ function registerTools(server, client, sessionManager) {
|
|
|
6991
7133
|
{
|
|
6992
7134
|
title: "Index status",
|
|
6993
7135
|
description: "Get project indexing status",
|
|
6994
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7136
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
6995
7137
|
},
|
|
6996
7138
|
async (input) => {
|
|
6997
|
-
const
|
|
7139
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7140
|
+
if (!projectId) {
|
|
7141
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7142
|
+
}
|
|
7143
|
+
const result = await client.projectIndexStatus(projectId);
|
|
6998
7144
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
6999
7145
|
}
|
|
7000
7146
|
);
|
|
@@ -7006,18 +7152,22 @@ function registerTools(server, client, sessionManager) {
|
|
|
7006
7152
|
This indexes your entire project by reading files in batches.
|
|
7007
7153
|
Automatically detects code files and skips ignored directories like node_modules, target, dist, etc.`,
|
|
7008
7154
|
inputSchema: external_exports.object({
|
|
7009
|
-
project_id: external_exports.string().uuid().describe("Project to ingest files into"),
|
|
7155
|
+
project_id: external_exports.string().uuid().optional().describe("Project to ingest files into (defaults to current session project)"),
|
|
7010
7156
|
path: external_exports.string().describe("Local directory path to read files from")
|
|
7011
7157
|
})
|
|
7012
7158
|
},
|
|
7013
7159
|
async (input) => {
|
|
7160
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7161
|
+
if (!projectId) {
|
|
7162
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7163
|
+
}
|
|
7014
7164
|
(async () => {
|
|
7015
7165
|
try {
|
|
7016
7166
|
let totalIndexed = 0;
|
|
7017
7167
|
let batchCount = 0;
|
|
7018
|
-
console.error(`[ContextStream] Starting background ingestion for project ${
|
|
7168
|
+
console.error(`[ContextStream] Starting background ingestion for project ${projectId} from ${input.path}`);
|
|
7019
7169
|
for await (const batch of readAllFilesInBatches(input.path, { batchSize: 50 })) {
|
|
7020
|
-
const result = await client.ingestFiles(
|
|
7170
|
+
const result = await client.ingestFiles(projectId, batch);
|
|
7021
7171
|
totalIndexed += result.data?.files_indexed ?? batch.length;
|
|
7022
7172
|
batchCount++;
|
|
7023
7173
|
}
|
|
@@ -7029,7 +7179,7 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7029
7179
|
const summary = {
|
|
7030
7180
|
status: "started",
|
|
7031
7181
|
message: "Ingestion running in background",
|
|
7032
|
-
project_id:
|
|
7182
|
+
project_id: projectId,
|
|
7033
7183
|
path: input.path,
|
|
7034
7184
|
note: "Use 'projects_index_status' to monitor progress."
|
|
7035
7185
|
};
|
|
@@ -7047,10 +7197,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7047
7197
|
{
|
|
7048
7198
|
title: "Get workspace",
|
|
7049
7199
|
description: "Get workspace details by ID",
|
|
7050
|
-
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid() })
|
|
7200
|
+
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid().optional() })
|
|
7051
7201
|
},
|
|
7052
7202
|
async (input) => {
|
|
7053
|
-
const
|
|
7203
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
7204
|
+
if (!workspaceId) {
|
|
7205
|
+
return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
|
|
7206
|
+
}
|
|
7207
|
+
const result = await client.getWorkspace(workspaceId);
|
|
7054
7208
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7055
7209
|
}
|
|
7056
7210
|
);
|
|
@@ -7059,10 +7213,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7059
7213
|
{
|
|
7060
7214
|
title: "Workspace overview",
|
|
7061
7215
|
description: "Get workspace overview with summary information",
|
|
7062
|
-
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid() })
|
|
7216
|
+
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid().optional() })
|
|
7063
7217
|
},
|
|
7064
7218
|
async (input) => {
|
|
7065
|
-
const
|
|
7219
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
7220
|
+
if (!workspaceId) {
|
|
7221
|
+
return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
|
|
7222
|
+
}
|
|
7223
|
+
const result = await client.workspaceOverview(workspaceId);
|
|
7066
7224
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7067
7225
|
}
|
|
7068
7226
|
);
|
|
@@ -7071,10 +7229,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7071
7229
|
{
|
|
7072
7230
|
title: "Workspace analytics",
|
|
7073
7231
|
description: "Get workspace usage analytics",
|
|
7074
|
-
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid() })
|
|
7232
|
+
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid().optional() })
|
|
7075
7233
|
},
|
|
7076
7234
|
async (input) => {
|
|
7077
|
-
const
|
|
7235
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
7236
|
+
if (!workspaceId) {
|
|
7237
|
+
return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
|
|
7238
|
+
}
|
|
7239
|
+
const result = await client.workspaceAnalytics(workspaceId);
|
|
7078
7240
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7079
7241
|
}
|
|
7080
7242
|
);
|
|
@@ -7083,10 +7245,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7083
7245
|
{
|
|
7084
7246
|
title: "Workspace content",
|
|
7085
7247
|
description: "List content in a workspace",
|
|
7086
|
-
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid() })
|
|
7248
|
+
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid().optional() })
|
|
7087
7249
|
},
|
|
7088
7250
|
async (input) => {
|
|
7089
|
-
const
|
|
7251
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
7252
|
+
if (!workspaceId) {
|
|
7253
|
+
return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
|
|
7254
|
+
}
|
|
7255
|
+
const result = await client.workspaceContent(workspaceId);
|
|
7090
7256
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7091
7257
|
}
|
|
7092
7258
|
);
|
|
@@ -7208,10 +7374,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7208
7374
|
{
|
|
7209
7375
|
title: "Memory timeline",
|
|
7210
7376
|
description: "Get chronological timeline of memory events for a workspace",
|
|
7211
|
-
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid() })
|
|
7377
|
+
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid().optional() })
|
|
7212
7378
|
},
|
|
7213
7379
|
async (input) => {
|
|
7214
|
-
const
|
|
7380
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
7381
|
+
if (!workspaceId) {
|
|
7382
|
+
return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
|
|
7383
|
+
}
|
|
7384
|
+
const result = await client.memoryTimeline(workspaceId);
|
|
7215
7385
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7216
7386
|
}
|
|
7217
7387
|
);
|
|
@@ -7220,10 +7390,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7220
7390
|
{
|
|
7221
7391
|
title: "Memory summary",
|
|
7222
7392
|
description: "Get condensed summary of workspace memory",
|
|
7223
|
-
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid() })
|
|
7393
|
+
inputSchema: external_exports.object({ workspace_id: external_exports.string().uuid().optional() })
|
|
7224
7394
|
},
|
|
7225
7395
|
async (input) => {
|
|
7226
|
-
const
|
|
7396
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
7397
|
+
if (!workspaceId) {
|
|
7398
|
+
return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
|
|
7399
|
+
}
|
|
7400
|
+
const result = await client.memorySummary(workspaceId);
|
|
7227
7401
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7228
7402
|
}
|
|
7229
7403
|
);
|
|
@@ -7232,10 +7406,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7232
7406
|
{
|
|
7233
7407
|
title: "Find circular dependencies",
|
|
7234
7408
|
description: "Detect circular dependencies in project code",
|
|
7235
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7409
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
7236
7410
|
},
|
|
7237
7411
|
async (input) => {
|
|
7238
|
-
const
|
|
7412
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7413
|
+
if (!projectId) {
|
|
7414
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7415
|
+
}
|
|
7416
|
+
const result = await client.findCircularDependencies(projectId);
|
|
7239
7417
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7240
7418
|
}
|
|
7241
7419
|
);
|
|
@@ -7244,10 +7422,14 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7244
7422
|
{
|
|
7245
7423
|
title: "Find unused code",
|
|
7246
7424
|
description: "Detect unused code in project",
|
|
7247
|
-
inputSchema: external_exports.object({ project_id: external_exports.string().uuid() })
|
|
7425
|
+
inputSchema: external_exports.object({ project_id: external_exports.string().uuid().optional() })
|
|
7248
7426
|
},
|
|
7249
7427
|
async (input) => {
|
|
7250
|
-
const
|
|
7428
|
+
const projectId = resolveProjectId(input.project_id);
|
|
7429
|
+
if (!projectId) {
|
|
7430
|
+
return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
|
|
7431
|
+
}
|
|
7432
|
+
const result = await client.findUnusedCode(projectId);
|
|
7251
7433
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7252
7434
|
}
|
|
7253
7435
|
);
|
|
@@ -7285,7 +7467,7 @@ Automatically detects code files and skips ignored directories like node_modules
|
|
|
7285
7467
|
title: "Initialize conversation session",
|
|
7286
7468
|
description: `Initialize a new conversation session and automatically retrieve relevant context.
|
|
7287
7469
|
This is the FIRST tool AI assistants should call when starting a conversation.
|
|
7288
|
-
Returns: workspace info, project info, recent memory, recent decisions, and
|
|
7470
|
+
Returns: workspace info, project info, recent memory, recent decisions, relevant context, and high-priority lessons.
|
|
7289
7471
|
Automatically detects the IDE workspace/project path and can auto-index code.
|
|
7290
7472
|
|
|
7291
7473
|
IMPORTANT: Pass the user's FIRST MESSAGE as context_hint to get semantically relevant context!
|
|
@@ -7392,6 +7574,117 @@ Optionally generates AI editor rules for automatic ContextStream usage.`,
|
|
|
7392
7574
|
return { content: [{ type: "text", text: formatContent(response) }], structuredContent: toStructured(response) };
|
|
7393
7575
|
}
|
|
7394
7576
|
);
|
|
7577
|
+
registerTool(
|
|
7578
|
+
"workspace_bootstrap",
|
|
7579
|
+
{
|
|
7580
|
+
title: "Create workspace + project from folder",
|
|
7581
|
+
description: `Create a new workspace (user-provided name) and onboard the current folder as a project.
|
|
7582
|
+
This is useful when session_init returns status='requires_workspace_name' (no workspaces exist yet) or when you want to create a new workspace for a repo.
|
|
7583
|
+
|
|
7584
|
+
Behavior:
|
|
7585
|
+
- Creates a workspace with the given name
|
|
7586
|
+
- Associates the folder to that workspace (writes .contextstream/config.json)
|
|
7587
|
+
- Initializes a session for the folder, which creates the project (folder name) and starts indexing (if enabled)`,
|
|
7588
|
+
inputSchema: external_exports.object({
|
|
7589
|
+
workspace_name: external_exports.string().min(1).describe("Name for the new workspace (ask the user)"),
|
|
7590
|
+
folder_path: external_exports.string().optional().describe("Absolute folder path (defaults to IDE root/cwd)"),
|
|
7591
|
+
description: external_exports.string().optional().describe("Optional workspace description"),
|
|
7592
|
+
visibility: external_exports.enum(["private", "public"]).optional().describe("Workspace visibility (default: private)"),
|
|
7593
|
+
create_parent_mapping: external_exports.boolean().optional().describe("Also create a parent folder mapping (e.g., /dev/company/* -> workspace)"),
|
|
7594
|
+
generate_editor_rules: external_exports.boolean().optional().describe("Generate AI editor rules in the folder for automatic ContextStream usage"),
|
|
7595
|
+
context_hint: external_exports.string().optional().describe("Optional context hint for session initialization"),
|
|
7596
|
+
auto_index: external_exports.boolean().optional().describe("Automatically create and index project from folder (default: true)")
|
|
7597
|
+
})
|
|
7598
|
+
},
|
|
7599
|
+
async (input) => {
|
|
7600
|
+
let folderPath = input.folder_path;
|
|
7601
|
+
if (!folderPath) {
|
|
7602
|
+
try {
|
|
7603
|
+
const rootsResponse = await server.server.listRoots();
|
|
7604
|
+
if (rootsResponse?.roots && rootsResponse.roots.length > 0) {
|
|
7605
|
+
folderPath = rootsResponse.roots[0].uri.replace("file://", "");
|
|
7606
|
+
}
|
|
7607
|
+
} catch {
|
|
7608
|
+
}
|
|
7609
|
+
}
|
|
7610
|
+
if (!folderPath) {
|
|
7611
|
+
folderPath = process.cwd();
|
|
7612
|
+
}
|
|
7613
|
+
if (!folderPath) {
|
|
7614
|
+
return errorResult("Error: folder_path is required. Provide folder_path or run from a project directory.");
|
|
7615
|
+
}
|
|
7616
|
+
const folderName = folderPath.split("/").pop() || "My Project";
|
|
7617
|
+
const newWorkspace = await client.createWorkspace({
|
|
7618
|
+
name: input.workspace_name,
|
|
7619
|
+
description: input.description || `Workspace created for ${folderPath}`,
|
|
7620
|
+
visibility: input.visibility || "private"
|
|
7621
|
+
});
|
|
7622
|
+
if (!newWorkspace?.id) {
|
|
7623
|
+
return errorResult("Error: failed to create workspace.");
|
|
7624
|
+
}
|
|
7625
|
+
const associateResult = await client.associateWorkspace({
|
|
7626
|
+
folder_path: folderPath,
|
|
7627
|
+
workspace_id: newWorkspace.id,
|
|
7628
|
+
workspace_name: newWorkspace.name || input.workspace_name,
|
|
7629
|
+
create_parent_mapping: input.create_parent_mapping
|
|
7630
|
+
});
|
|
7631
|
+
let rulesGenerated = [];
|
|
7632
|
+
if (input.generate_editor_rules) {
|
|
7633
|
+
const fs3 = await import("fs");
|
|
7634
|
+
const path3 = await import("path");
|
|
7635
|
+
for (const editor of getAvailableEditors()) {
|
|
7636
|
+
const rule = generateRuleContent(editor, {
|
|
7637
|
+
workspaceName: newWorkspace.name || input.workspace_name,
|
|
7638
|
+
workspaceId: newWorkspace.id
|
|
7639
|
+
});
|
|
7640
|
+
if (!rule) continue;
|
|
7641
|
+
const filePath = path3.join(folderPath, rule.filename);
|
|
7642
|
+
try {
|
|
7643
|
+
let existingContent = "";
|
|
7644
|
+
try {
|
|
7645
|
+
existingContent = fs3.readFileSync(filePath, "utf-8");
|
|
7646
|
+
} catch {
|
|
7647
|
+
}
|
|
7648
|
+
if (!existingContent) {
|
|
7649
|
+
fs3.writeFileSync(filePath, rule.content);
|
|
7650
|
+
rulesGenerated.push(rule.filename);
|
|
7651
|
+
} else if (!existingContent.includes("ContextStream Integration")) {
|
|
7652
|
+
fs3.writeFileSync(filePath, existingContent + "\n\n" + rule.content);
|
|
7653
|
+
rulesGenerated.push(rule.filename + " (appended)");
|
|
7654
|
+
}
|
|
7655
|
+
} catch {
|
|
7656
|
+
}
|
|
7657
|
+
}
|
|
7658
|
+
}
|
|
7659
|
+
const session = await client.initSession(
|
|
7660
|
+
{
|
|
7661
|
+
workspace_id: newWorkspace.id,
|
|
7662
|
+
context_hint: input.context_hint,
|
|
7663
|
+
include_recent_memory: true,
|
|
7664
|
+
include_decisions: true,
|
|
7665
|
+
auto_index: input.auto_index
|
|
7666
|
+
},
|
|
7667
|
+
[folderPath]
|
|
7668
|
+
);
|
|
7669
|
+
if (sessionManager) {
|
|
7670
|
+
sessionManager.markInitialized(session);
|
|
7671
|
+
}
|
|
7672
|
+
const response = {
|
|
7673
|
+
...session,
|
|
7674
|
+
bootstrap: {
|
|
7675
|
+
folder_path: folderPath,
|
|
7676
|
+
project_name: folderName,
|
|
7677
|
+
workspace: {
|
|
7678
|
+
id: newWorkspace.id,
|
|
7679
|
+
name: newWorkspace.name || input.workspace_name
|
|
7680
|
+
},
|
|
7681
|
+
association: associateResult,
|
|
7682
|
+
editor_rules_generated: rulesGenerated.length > 0 ? rulesGenerated : void 0
|
|
7683
|
+
}
|
|
7684
|
+
};
|
|
7685
|
+
return { content: [{ type: "text", text: formatContent(response) }], structuredContent: toStructured(response) };
|
|
7686
|
+
}
|
|
7687
|
+
);
|
|
7395
7688
|
registerTool(
|
|
7396
7689
|
"session_capture",
|
|
7397
7690
|
{
|
|
@@ -7578,7 +7871,7 @@ Returns lessons filtered by:
|
|
|
7578
7871
|
limit: input.limit * 2
|
|
7579
7872
|
// Fetch more to filter
|
|
7580
7873
|
});
|
|
7581
|
-
let lessons = (searchResult
|
|
7874
|
+
let lessons = (searchResult.results || []).filter((item) => {
|
|
7582
7875
|
const tags = item.metadata?.tags || [];
|
|
7583
7876
|
const isLesson = tags.includes("lesson");
|
|
7584
7877
|
if (!isLesson) return false;
|
|
@@ -8032,7 +8325,7 @@ Format options:
|
|
|
8032
8325
|
- 'readable': Line-separated with labels
|
|
8033
8326
|
- 'structured': JSON-like grouped format
|
|
8034
8327
|
|
|
8035
|
-
Type codes: W=Workspace, P=Project, D=Decision, M=Memory, I=Insight, T=Task
|
|
8328
|
+
Type codes: W=Workspace, P=Project, D=Decision, M=Memory, I=Insight, T=Task, L=Lesson
|
|
8036
8329
|
|
|
8037
8330
|
Example usage:
|
|
8038
8331
|
1. User asks "how should I implement auth?"
|
|
@@ -8123,32 +8416,47 @@ function registerResources(server, client, apiUrl) {
|
|
|
8123
8416
|
}
|
|
8124
8417
|
|
|
8125
8418
|
// src/prompts.ts
|
|
8419
|
+
var ID_NOTES = [
|
|
8420
|
+
"Notes:",
|
|
8421
|
+
"- If ContextStream is not initialized in this conversation, call `session_init` first (omit ids).",
|
|
8422
|
+
"- Do not ask me for `workspace_id`/`project_id` \u2014 use session defaults or IDs returned by `session_init`.",
|
|
8423
|
+
"- Prefer omitting IDs in tool calls when the tool supports defaults."
|
|
8424
|
+
];
|
|
8425
|
+
var upgradeUrl = process.env.CONTEXTSTREAM_UPGRADE_URL || "https://contextstream.io/pricing";
|
|
8426
|
+
var proPrompts = /* @__PURE__ */ new Set([
|
|
8427
|
+
"build-context",
|
|
8428
|
+
"generate-plan",
|
|
8429
|
+
"generate-tasks",
|
|
8430
|
+
"token-budget-context"
|
|
8431
|
+
]);
|
|
8432
|
+
function promptAccessLabel(promptName) {
|
|
8433
|
+
return proPrompts.has(promptName) ? "PRO" : "Free";
|
|
8434
|
+
}
|
|
8126
8435
|
function registerPrompts(server) {
|
|
8127
8436
|
server.registerPrompt(
|
|
8128
8437
|
"explore-codebase",
|
|
8129
8438
|
{
|
|
8130
|
-
title:
|
|
8131
|
-
description: "Get an overview of a project codebase structure and key components"
|
|
8132
|
-
argsSchema: {
|
|
8133
|
-
project_id: external_exports.string().uuid().describe("Project ID to explore"),
|
|
8134
|
-
focus_area: external_exports.string().optional().describe('Optional area to focus on (e.g., "authentication", "api routes")')
|
|
8135
|
-
}
|
|
8439
|
+
title: `Explore Codebase (${promptAccessLabel("explore-codebase")})`,
|
|
8440
|
+
description: "Get an overview of a project codebase structure and key components"
|
|
8136
8441
|
},
|
|
8137
|
-
async (
|
|
8442
|
+
async () => ({
|
|
8138
8443
|
messages: [
|
|
8139
8444
|
{
|
|
8140
8445
|
role: "user",
|
|
8141
8446
|
content: {
|
|
8142
8447
|
type: "text",
|
|
8143
|
-
text:
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8448
|
+
text: [
|
|
8449
|
+
"I want to understand the current codebase.",
|
|
8450
|
+
"",
|
|
8451
|
+
...ID_NOTES,
|
|
8452
|
+
"",
|
|
8453
|
+
"Please help me by:",
|
|
8454
|
+
"1. Use `projects_overview` to get a project summary (use session defaults; only pass `project_id` if required).",
|
|
8455
|
+
"2. Use `projects_files` to identify key entry points.",
|
|
8456
|
+
"3. If a focus area is clear from our conversation, prioritize it; otherwise ask me what to focus on.",
|
|
8457
|
+
"4. Use `search_semantic` (and optionally `search_hybrid`) to find the most relevant files.",
|
|
8458
|
+
"5. Summarize the architecture, major modules, and where to start editing."
|
|
8459
|
+
].join("\n")
|
|
8152
8460
|
}
|
|
8153
8461
|
}
|
|
8154
8462
|
]
|
|
@@ -8157,37 +8465,32 @@ Provide a clear, structured overview that helps me navigate this codebase effect
|
|
|
8157
8465
|
server.registerPrompt(
|
|
8158
8466
|
"capture-decision",
|
|
8159
8467
|
{
|
|
8160
|
-
title:
|
|
8161
|
-
description: "Document an architectural or technical decision in workspace memory"
|
|
8162
|
-
argsSchema: {
|
|
8163
|
-
workspace_id: external_exports.string().uuid().describe("Workspace ID"),
|
|
8164
|
-
decision_title: external_exports.string().describe("Brief title of the decision"),
|
|
8165
|
-
context: external_exports.string().describe("What prompted this decision"),
|
|
8166
|
-
decision: external_exports.string().describe("The decision made"),
|
|
8167
|
-
consequences: external_exports.string().optional().describe("Expected consequences or tradeoffs")
|
|
8168
|
-
}
|
|
8468
|
+
title: `Capture Decision (${promptAccessLabel("capture-decision")})`,
|
|
8469
|
+
description: "Document an architectural or technical decision in workspace memory"
|
|
8169
8470
|
},
|
|
8170
|
-
async (
|
|
8471
|
+
async () => ({
|
|
8171
8472
|
messages: [
|
|
8172
8473
|
{
|
|
8173
8474
|
role: "user",
|
|
8174
8475
|
content: {
|
|
8175
8476
|
type: "text",
|
|
8176
|
-
text:
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
-
|
|
8185
|
-
-
|
|
8186
|
-
- title:
|
|
8187
|
-
- content:
|
|
8188
|
-
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8477
|
+
text: [
|
|
8478
|
+
"Please capture an architectural/technical decision in ContextStream memory.",
|
|
8479
|
+
"",
|
|
8480
|
+
...ID_NOTES,
|
|
8481
|
+
"",
|
|
8482
|
+
"Instructions:",
|
|
8483
|
+
"- If the decision is already described in this conversation, extract: title, context, decision, consequences/tradeoffs.",
|
|
8484
|
+
"- If anything is missing, ask me 1\u20133 quick questions to fill the gaps.",
|
|
8485
|
+
"- Then call `session_capture` with:",
|
|
8486
|
+
' - event_type: "decision"',
|
|
8487
|
+
" - title: (short ADR title)",
|
|
8488
|
+
" - content: a well-formatted ADR (Context, Decision, Consequences)",
|
|
8489
|
+
' - tags: include relevant tags (e.g., "adr", "architecture")',
|
|
8490
|
+
' - importance: "high"',
|
|
8491
|
+
"",
|
|
8492
|
+
"After capturing, confirm what was saved."
|
|
8493
|
+
].join("\n")
|
|
8191
8494
|
}
|
|
8192
8495
|
}
|
|
8193
8496
|
]
|
|
@@ -8196,35 +8499,35 @@ After creating, confirm the decision was recorded and summarize it.`
|
|
|
8196
8499
|
server.registerPrompt(
|
|
8197
8500
|
"review-context",
|
|
8198
8501
|
{
|
|
8199
|
-
title:
|
|
8200
|
-
description: "Build context for reviewing code changes"
|
|
8201
|
-
argsSchema: {
|
|
8202
|
-
project_id: external_exports.string().uuid().describe("Project ID"),
|
|
8203
|
-
file_paths: external_exports.string().describe("Comma-separated file paths being changed"),
|
|
8204
|
-
change_description: external_exports.string().describe("Brief description of the changes")
|
|
8205
|
-
}
|
|
8502
|
+
title: `Code Review Context (${promptAccessLabel("review-context")})`,
|
|
8503
|
+
description: "Build context for reviewing code changes"
|
|
8206
8504
|
},
|
|
8207
|
-
async (
|
|
8505
|
+
async () => ({
|
|
8208
8506
|
messages: [
|
|
8209
8507
|
{
|
|
8210
8508
|
role: "user",
|
|
8211
8509
|
content: {
|
|
8212
8510
|
type: "text",
|
|
8213
|
-
text:
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8511
|
+
text: [
|
|
8512
|
+
"I need context to review a set of code changes.",
|
|
8513
|
+
"",
|
|
8514
|
+
...ID_NOTES,
|
|
8515
|
+
"",
|
|
8516
|
+
"First:",
|
|
8517
|
+
"- If file paths and a short change description are not already in this conversation, ask me for them.",
|
|
8518
|
+
"",
|
|
8519
|
+
"Then build review context by:",
|
|
8520
|
+
"1. Using `graph_dependencies` to find what depends on the changed areas.",
|
|
8521
|
+
"2. Using `graph_impact` to assess potential blast radius.",
|
|
8522
|
+
"3. Using `memory_search` to find related decisions/notes.",
|
|
8523
|
+
"4. Using `search_semantic` to find related code patterns.",
|
|
8524
|
+
"",
|
|
8525
|
+
"Provide:",
|
|
8526
|
+
"- What the files/components do",
|
|
8527
|
+
"- What might be affected",
|
|
8528
|
+
"- Relevant prior decisions/lessons",
|
|
8529
|
+
"- Review checklist + risks to focus on"
|
|
8530
|
+
].join("\n")
|
|
8228
8531
|
}
|
|
8229
8532
|
}
|
|
8230
8533
|
]
|
|
@@ -8233,36 +8536,36 @@ Provide:
|
|
|
8233
8536
|
server.registerPrompt(
|
|
8234
8537
|
"investigate-bug",
|
|
8235
8538
|
{
|
|
8236
|
-
title:
|
|
8237
|
-
description: "Build context for debugging an issue"
|
|
8238
|
-
argsSchema: {
|
|
8239
|
-
project_id: external_exports.string().uuid().describe("Project ID"),
|
|
8240
|
-
error_message: external_exports.string().describe("Error message or symptom"),
|
|
8241
|
-
affected_area: external_exports.string().optional().describe("Known affected area or component")
|
|
8242
|
-
}
|
|
8539
|
+
title: `Investigate Bug (${promptAccessLabel("investigate-bug")})`,
|
|
8540
|
+
description: "Build context for debugging an issue"
|
|
8243
8541
|
},
|
|
8244
|
-
async (
|
|
8542
|
+
async () => ({
|
|
8245
8543
|
messages: [
|
|
8246
8544
|
{
|
|
8247
8545
|
role: "user",
|
|
8248
8546
|
content: {
|
|
8249
8547
|
type: "text",
|
|
8250
|
-
text:
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8548
|
+
text: [
|
|
8549
|
+
"I want help investigating a bug.",
|
|
8550
|
+
"",
|
|
8551
|
+
...ID_NOTES,
|
|
8552
|
+
"",
|
|
8553
|
+
"First:",
|
|
8554
|
+
"- If the error/symptom is not already stated, ask me for the exact error message and what I expected vs what happened.",
|
|
8555
|
+
"- If an affected area/component is not known, ask me where I noticed it.",
|
|
8556
|
+
"",
|
|
8557
|
+
"Then:",
|
|
8558
|
+
"1. Use `search_semantic` to find code related to the error/symptom.",
|
|
8559
|
+
"2. Use `search_pattern` to locate where similar errors are thrown or logged.",
|
|
8560
|
+
"3. If you identify key functions, use `graph_call_path` to trace call flows.",
|
|
8561
|
+
"4. Use `memory_search` to check if we have prior notes/bugs about this area.",
|
|
8562
|
+
"",
|
|
8563
|
+
"Return:",
|
|
8564
|
+
"- Likely origin locations",
|
|
8565
|
+
"- Call flow (if found)",
|
|
8566
|
+
"- Related past context",
|
|
8567
|
+
"- Suggested debugging steps"
|
|
8568
|
+
].join("\n")
|
|
8266
8569
|
}
|
|
8267
8570
|
}
|
|
8268
8571
|
]
|
|
@@ -8271,32 +8574,32 @@ Provide:
|
|
|
8271
8574
|
server.registerPrompt(
|
|
8272
8575
|
"explore-knowledge",
|
|
8273
8576
|
{
|
|
8274
|
-
title:
|
|
8275
|
-
description: "Navigate and understand the knowledge graph for a workspace"
|
|
8276
|
-
argsSchema: {
|
|
8277
|
-
workspace_id: external_exports.string().uuid().describe("Workspace ID"),
|
|
8278
|
-
starting_topic: external_exports.string().optional().describe("Topic to start exploration from")
|
|
8279
|
-
}
|
|
8577
|
+
title: `Explore Knowledge Graph (${promptAccessLabel("explore-knowledge")})`,
|
|
8578
|
+
description: "Navigate and understand the knowledge graph for a workspace"
|
|
8280
8579
|
},
|
|
8281
|
-
async (
|
|
8580
|
+
async () => ({
|
|
8282
8581
|
messages: [
|
|
8283
8582
|
{
|
|
8284
8583
|
role: "user",
|
|
8285
8584
|
content: {
|
|
8286
8585
|
type: "text",
|
|
8287
|
-
text:
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8586
|
+
text: [
|
|
8587
|
+
"Help me explore the knowledge captured in this workspace.",
|
|
8588
|
+
"",
|
|
8589
|
+
...ID_NOTES,
|
|
8590
|
+
"",
|
|
8591
|
+
"Approach:",
|
|
8592
|
+
"1. Use `memory_summary` for a high-level overview.",
|
|
8593
|
+
"2. Use `memory_decisions` to see decision history (titles + a few key details).",
|
|
8594
|
+
"3. Use `memory_list_nodes` to see available knowledge nodes.",
|
|
8595
|
+
"4. If a starting topic is clear from the conversation, use `memory_search` for it.",
|
|
8596
|
+
"5. Use `graph_related` on the most relevant nodes to expand connections.",
|
|
8597
|
+
"",
|
|
8598
|
+
"Provide:",
|
|
8599
|
+
"- Key themes and topics",
|
|
8600
|
+
"- Important decisions + rationale",
|
|
8601
|
+
"- Suggested \u201Cnext nodes\u201D to explore"
|
|
8602
|
+
].join("\n")
|
|
8300
8603
|
}
|
|
8301
8604
|
}
|
|
8302
8605
|
]
|
|
@@ -8305,37 +8608,37 @@ Provide:
|
|
|
8305
8608
|
server.registerPrompt(
|
|
8306
8609
|
"onboard-to-project",
|
|
8307
8610
|
{
|
|
8308
|
-
title:
|
|
8309
|
-
description: "Generate onboarding context for a new team member"
|
|
8310
|
-
argsSchema: {
|
|
8311
|
-
project_id: external_exports.string().uuid().describe("Project ID"),
|
|
8312
|
-
workspace_id: external_exports.string().uuid().describe("Workspace ID"),
|
|
8313
|
-
role: external_exports.string().optional().describe('Role of the person being onboarded (e.g., "backend developer", "frontend developer")')
|
|
8314
|
-
}
|
|
8611
|
+
title: `Project Onboarding (${promptAccessLabel("onboard-to-project")})`,
|
|
8612
|
+
description: "Generate onboarding context for a new team member"
|
|
8315
8613
|
},
|
|
8316
|
-
async (
|
|
8614
|
+
async () => ({
|
|
8317
8615
|
messages: [
|
|
8318
8616
|
{
|
|
8319
8617
|
role: "user",
|
|
8320
8618
|
content: {
|
|
8321
8619
|
type: "text",
|
|
8322
|
-
text:
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
-
|
|
8338
|
-
-
|
|
8620
|
+
text: [
|
|
8621
|
+
"Create an onboarding guide for a new team member joining this project.",
|
|
8622
|
+
"",
|
|
8623
|
+
...ID_NOTES,
|
|
8624
|
+
"",
|
|
8625
|
+
"First:",
|
|
8626
|
+
"- If the role is not specified, ask me what role they are onboarding into (backend, frontend, fullstack, etc.).",
|
|
8627
|
+
"",
|
|
8628
|
+
"Gather context:",
|
|
8629
|
+
"1. Use `projects_overview` and `projects_statistics` for project summary.",
|
|
8630
|
+
"2. Use `projects_files` to identify key entry points.",
|
|
8631
|
+
"3. Use `memory_timeline` and `memory_decisions` to understand recent changes and architectural choices.",
|
|
8632
|
+
"4. Use `search_semantic` to find READMEs/docs/setup instructions.",
|
|
8633
|
+
"",
|
|
8634
|
+
"Output:",
|
|
8635
|
+
"- Project overview and purpose",
|
|
8636
|
+
"- Tech stack + architecture map",
|
|
8637
|
+
"- Key files/entry points relevant to the role",
|
|
8638
|
+
"- Important decisions + rationale",
|
|
8639
|
+
"- Recent changes/current focus",
|
|
8640
|
+
"- Step-by-step getting started"
|
|
8641
|
+
].join("\n")
|
|
8339
8642
|
}
|
|
8340
8643
|
}
|
|
8341
8644
|
]
|
|
@@ -8344,33 +8647,30 @@ Provide an onboarding guide that includes:
|
|
|
8344
8647
|
server.registerPrompt(
|
|
8345
8648
|
"analyze-refactoring",
|
|
8346
8649
|
{
|
|
8347
|
-
title:
|
|
8348
|
-
description: "Analyze a codebase for refactoring opportunities"
|
|
8349
|
-
argsSchema: {
|
|
8350
|
-
project_id: external_exports.string().uuid().describe("Project ID"),
|
|
8351
|
-
target_area: external_exports.string().optional().describe("Specific area to analyze")
|
|
8352
|
-
}
|
|
8650
|
+
title: `Refactoring Analysis (${promptAccessLabel("analyze-refactoring")})`,
|
|
8651
|
+
description: "Analyze a codebase for refactoring opportunities"
|
|
8353
8652
|
},
|
|
8354
|
-
async (
|
|
8653
|
+
async () => ({
|
|
8355
8654
|
messages: [
|
|
8356
8655
|
{
|
|
8357
8656
|
role: "user",
|
|
8358
8657
|
content: {
|
|
8359
8658
|
type: "text",
|
|
8360
|
-
text:
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8659
|
+
text: [
|
|
8660
|
+
"Analyze the codebase for refactoring opportunities.",
|
|
8661
|
+
"",
|
|
8662
|
+
...ID_NOTES,
|
|
8663
|
+
"",
|
|
8664
|
+
"If a target area is obvious from our conversation, focus there; otherwise ask me what area to analyze.",
|
|
8665
|
+
"",
|
|
8666
|
+
"Please investigate:",
|
|
8667
|
+
"1. `graph_circular_dependencies` (circular deps to break)",
|
|
8668
|
+
"2. `graph_unused_code` (dead code to remove)",
|
|
8669
|
+
"3. `search_pattern` (duplication patterns)",
|
|
8670
|
+
"4. `projects_statistics` (high complexity hotspots)",
|
|
8671
|
+
"",
|
|
8672
|
+
"Provide a prioritized list with quick wins vs deeper refactors."
|
|
8673
|
+
].join("\n")
|
|
8374
8674
|
}
|
|
8375
8675
|
}
|
|
8376
8676
|
]
|
|
@@ -8379,34 +8679,452 @@ Provide:
|
|
|
8379
8679
|
server.registerPrompt(
|
|
8380
8680
|
"build-context",
|
|
8381
8681
|
{
|
|
8382
|
-
title:
|
|
8383
|
-
description: "Build comprehensive context for an LLM task"
|
|
8384
|
-
argsSchema: {
|
|
8385
|
-
query: external_exports.string().describe("What you need context for"),
|
|
8386
|
-
workspace_id: external_exports.string().uuid().optional().describe("Workspace ID"),
|
|
8387
|
-
project_id: external_exports.string().uuid().optional().describe("Project ID"),
|
|
8388
|
-
include_memory: external_exports.string().optional().describe('Include memory/decisions ("true" or "false")')
|
|
8389
|
-
}
|
|
8682
|
+
title: `Build LLM Context (${promptAccessLabel("build-context")})`,
|
|
8683
|
+
description: "Build comprehensive context for an LLM task"
|
|
8390
8684
|
},
|
|
8391
|
-
async (
|
|
8685
|
+
async () => ({
|
|
8392
8686
|
messages: [
|
|
8393
8687
|
{
|
|
8394
8688
|
role: "user",
|
|
8395
8689
|
content: {
|
|
8396
8690
|
type: "text",
|
|
8397
|
-
text:
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
-
|
|
8406
|
-
-
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
|
|
8691
|
+
text: [
|
|
8692
|
+
"Build comprehensive context for the task we are working on.",
|
|
8693
|
+
"",
|
|
8694
|
+
`Access: ${promptAccessLabel("build-context")}${promptAccessLabel("build-context") === "PRO" ? ` (upgrade: ${upgradeUrl})` : ""}`,
|
|
8695
|
+
"",
|
|
8696
|
+
...ID_NOTES,
|
|
8697
|
+
"",
|
|
8698
|
+
"First:",
|
|
8699
|
+
"- If the \u201Cquery\u201D is clear from the latest user request, use that.",
|
|
8700
|
+
"- Otherwise ask me: \u201CWhat do you need context for?\u201D",
|
|
8701
|
+
"",
|
|
8702
|
+
"Then:",
|
|
8703
|
+
"- Call `ai_enhanced_context` with include_code=true, include_docs=true, include_memory=true (omit IDs unless required).",
|
|
8704
|
+
"- Synthesize the returned context into a short briefing with links/file paths and key decisions/risks."
|
|
8705
|
+
].join("\n")
|
|
8706
|
+
}
|
|
8707
|
+
}
|
|
8708
|
+
]
|
|
8709
|
+
})
|
|
8710
|
+
);
|
|
8711
|
+
server.registerPrompt(
|
|
8712
|
+
"smart-search",
|
|
8713
|
+
{
|
|
8714
|
+
title: `Smart Search (${promptAccessLabel("smart-search")})`,
|
|
8715
|
+
description: "Search across memory, decisions, and code for a query"
|
|
8716
|
+
},
|
|
8717
|
+
async () => ({
|
|
8718
|
+
messages: [
|
|
8719
|
+
{
|
|
8720
|
+
role: "user",
|
|
8721
|
+
content: {
|
|
8722
|
+
type: "text",
|
|
8723
|
+
text: [
|
|
8724
|
+
"Find the most relevant context for what I am asking about.",
|
|
8725
|
+
"",
|
|
8726
|
+
...ID_NOTES,
|
|
8727
|
+
"",
|
|
8728
|
+
"First:",
|
|
8729
|
+
"- If a query is clear from the conversation, use it.",
|
|
8730
|
+
"- Otherwise ask me what I want to find.",
|
|
8731
|
+
"",
|
|
8732
|
+
"Then:",
|
|
8733
|
+
"1. Use `session_smart_search` for the query.",
|
|
8734
|
+
"2. If results are thin, follow up with `search_hybrid` and `memory_search`.",
|
|
8735
|
+
"3. Return the top results with file paths/links and a short synthesis."
|
|
8736
|
+
].join("\n")
|
|
8737
|
+
}
|
|
8738
|
+
}
|
|
8739
|
+
]
|
|
8740
|
+
})
|
|
8741
|
+
);
|
|
8742
|
+
server.registerPrompt(
|
|
8743
|
+
"recall-context",
|
|
8744
|
+
{
|
|
8745
|
+
title: `Recall Context (${promptAccessLabel("recall-context")})`,
|
|
8746
|
+
description: "Retrieve relevant past decisions and memory for a query"
|
|
8747
|
+
},
|
|
8748
|
+
async () => ({
|
|
8749
|
+
messages: [
|
|
8750
|
+
{
|
|
8751
|
+
role: "user",
|
|
8752
|
+
content: {
|
|
8753
|
+
type: "text",
|
|
8754
|
+
text: [
|
|
8755
|
+
"Recall relevant past context (decisions, notes, lessons) for what I am asking about.",
|
|
8756
|
+
"",
|
|
8757
|
+
...ID_NOTES,
|
|
8758
|
+
"",
|
|
8759
|
+
"First:",
|
|
8760
|
+
"- If a recall query is clear from the conversation, use it.",
|
|
8761
|
+
"- Otherwise ask me what topic I want to recall.",
|
|
8762
|
+
"",
|
|
8763
|
+
"Then:",
|
|
8764
|
+
"- Use `session_recall` with the query (omit IDs unless required).",
|
|
8765
|
+
"- Summarize the key points and any relevant decisions/lessons."
|
|
8766
|
+
].join("\n")
|
|
8767
|
+
}
|
|
8768
|
+
}
|
|
8769
|
+
]
|
|
8770
|
+
})
|
|
8771
|
+
);
|
|
8772
|
+
server.registerPrompt(
|
|
8773
|
+
"session-summary",
|
|
8774
|
+
{
|
|
8775
|
+
title: `Session Summary (${promptAccessLabel("session-summary")})`,
|
|
8776
|
+
description: "Get a compact summary of workspace/project context"
|
|
8777
|
+
},
|
|
8778
|
+
async () => ({
|
|
8779
|
+
messages: [
|
|
8780
|
+
{
|
|
8781
|
+
role: "user",
|
|
8782
|
+
content: {
|
|
8783
|
+
type: "text",
|
|
8784
|
+
text: [
|
|
8785
|
+
"Generate a compact, token-efficient summary of the current workspace/project context.",
|
|
8786
|
+
"",
|
|
8787
|
+
...ID_NOTES,
|
|
8788
|
+
"",
|
|
8789
|
+
"Use `session_summary` (default max_tokens=500 unless I specify otherwise).",
|
|
8790
|
+
"Then list:",
|
|
8791
|
+
"- Top decisions (titles only)",
|
|
8792
|
+
"- Any high-priority lessons to watch for"
|
|
8793
|
+
].join("\n")
|
|
8794
|
+
}
|
|
8795
|
+
}
|
|
8796
|
+
]
|
|
8797
|
+
})
|
|
8798
|
+
);
|
|
8799
|
+
server.registerPrompt(
|
|
8800
|
+
"capture-lesson",
|
|
8801
|
+
{
|
|
8802
|
+
title: `Capture Lesson (${promptAccessLabel("capture-lesson")})`,
|
|
8803
|
+
description: "Record a lesson learned from an error or correction"
|
|
8804
|
+
},
|
|
8805
|
+
async () => ({
|
|
8806
|
+
messages: [
|
|
8807
|
+
{
|
|
8808
|
+
role: "user",
|
|
8809
|
+
content: {
|
|
8810
|
+
type: "text",
|
|
8811
|
+
text: [
|
|
8812
|
+
"Capture a lesson learned so it is surfaced in future sessions.",
|
|
8813
|
+
"",
|
|
8814
|
+
...ID_NOTES,
|
|
8815
|
+
"",
|
|
8816
|
+
"If the lesson details are not fully present in the conversation, ask me for:",
|
|
8817
|
+
"- title (what to remember)",
|
|
8818
|
+
"- severity (low|medium|high|critical, default medium)",
|
|
8819
|
+
"- category (workflow|code_quality|verification|communication|project_specific)",
|
|
8820
|
+
"- trigger (what caused it)",
|
|
8821
|
+
"- impact (what went wrong)",
|
|
8822
|
+
"- prevention (how to prevent it)",
|
|
8823
|
+
"- keywords (optional)",
|
|
8824
|
+
"",
|
|
8825
|
+
"Then call `session_capture_lesson` with those fields and confirm it was saved."
|
|
8826
|
+
].join("\n")
|
|
8827
|
+
}
|
|
8828
|
+
}
|
|
8829
|
+
]
|
|
8830
|
+
})
|
|
8831
|
+
);
|
|
8832
|
+
server.registerPrompt(
|
|
8833
|
+
"capture-preference",
|
|
8834
|
+
{
|
|
8835
|
+
title: `Capture Preference (${promptAccessLabel("capture-preference")})`,
|
|
8836
|
+
description: "Save a user preference to memory"
|
|
8837
|
+
},
|
|
8838
|
+
async () => ({
|
|
8839
|
+
messages: [
|
|
8840
|
+
{
|
|
8841
|
+
role: "user",
|
|
8842
|
+
content: {
|
|
8843
|
+
type: "text",
|
|
8844
|
+
text: [
|
|
8845
|
+
"Save a user preference to ContextStream memory.",
|
|
8846
|
+
"",
|
|
8847
|
+
...ID_NOTES,
|
|
8848
|
+
"",
|
|
8849
|
+
"If the preference is not explicit in the conversation, ask me what to remember.",
|
|
8850
|
+
"",
|
|
8851
|
+
"Then call `session_capture` with:",
|
|
8852
|
+
'- event_type: "preference"',
|
|
8853
|
+
"- title: (short title)",
|
|
8854
|
+
"- content: (preference text)",
|
|
8855
|
+
'- importance: "medium"'
|
|
8856
|
+
].join("\n")
|
|
8857
|
+
}
|
|
8858
|
+
}
|
|
8859
|
+
]
|
|
8860
|
+
})
|
|
8861
|
+
);
|
|
8862
|
+
server.registerPrompt(
|
|
8863
|
+
"capture-task",
|
|
8864
|
+
{
|
|
8865
|
+
title: `Capture Task (${promptAccessLabel("capture-task")})`,
|
|
8866
|
+
description: "Capture an action item into memory"
|
|
8867
|
+
},
|
|
8868
|
+
async () => ({
|
|
8869
|
+
messages: [
|
|
8870
|
+
{
|
|
8871
|
+
role: "user",
|
|
8872
|
+
content: {
|
|
8873
|
+
type: "text",
|
|
8874
|
+
text: [
|
|
8875
|
+
"Capture an action item into ContextStream memory.",
|
|
8876
|
+
"",
|
|
8877
|
+
...ID_NOTES,
|
|
8878
|
+
"",
|
|
8879
|
+
"If the task is not explicit in the conversation, ask me what to capture.",
|
|
8880
|
+
"",
|
|
8881
|
+
"Then call `session_capture` with:",
|
|
8882
|
+
'- event_type: "task"',
|
|
8883
|
+
"- title: (short title)",
|
|
8884
|
+
"- content: (task details)",
|
|
8885
|
+
'- importance: "medium"'
|
|
8886
|
+
].join("\n")
|
|
8887
|
+
}
|
|
8888
|
+
}
|
|
8889
|
+
]
|
|
8890
|
+
})
|
|
8891
|
+
);
|
|
8892
|
+
server.registerPrompt(
|
|
8893
|
+
"capture-bug",
|
|
8894
|
+
{
|
|
8895
|
+
title: `Capture Bug (${promptAccessLabel("capture-bug")})`,
|
|
8896
|
+
description: "Capture a bug report into workspace memory"
|
|
8897
|
+
},
|
|
8898
|
+
async () => ({
|
|
8899
|
+
messages: [
|
|
8900
|
+
{
|
|
8901
|
+
role: "user",
|
|
8902
|
+
content: {
|
|
8903
|
+
type: "text",
|
|
8904
|
+
text: [
|
|
8905
|
+
"Capture a bug report in ContextStream memory.",
|
|
8906
|
+
"",
|
|
8907
|
+
...ID_NOTES,
|
|
8908
|
+
"",
|
|
8909
|
+
"If details are missing, ask me for:",
|
|
8910
|
+
"- title",
|
|
8911
|
+
"- description",
|
|
8912
|
+
"- steps to reproduce (optional)",
|
|
8913
|
+
"- expected behavior (optional)",
|
|
8914
|
+
"- actual behavior (optional)",
|
|
8915
|
+
"",
|
|
8916
|
+
"Then call `session_capture` with:",
|
|
8917
|
+
'- event_type: "bug"',
|
|
8918
|
+
"- title: (bug title)",
|
|
8919
|
+
"- content: a well-formatted bug report (include all provided details)",
|
|
8920
|
+
"- tags: component/area tags",
|
|
8921
|
+
'- importance: "high"'
|
|
8922
|
+
].join("\n")
|
|
8923
|
+
}
|
|
8924
|
+
}
|
|
8925
|
+
]
|
|
8926
|
+
})
|
|
8927
|
+
);
|
|
8928
|
+
server.registerPrompt(
|
|
8929
|
+
"capture-feature",
|
|
8930
|
+
{
|
|
8931
|
+
title: `Capture Feature (${promptAccessLabel("capture-feature")})`,
|
|
8932
|
+
description: "Capture a feature request into workspace memory"
|
|
8933
|
+
},
|
|
8934
|
+
async () => ({
|
|
8935
|
+
messages: [
|
|
8936
|
+
{
|
|
8937
|
+
role: "user",
|
|
8938
|
+
content: {
|
|
8939
|
+
type: "text",
|
|
8940
|
+
text: [
|
|
8941
|
+
"Capture a feature request in ContextStream memory.",
|
|
8942
|
+
"",
|
|
8943
|
+
...ID_NOTES,
|
|
8944
|
+
"",
|
|
8945
|
+
"If details are missing, ask me for:",
|
|
8946
|
+
"- title",
|
|
8947
|
+
"- description",
|
|
8948
|
+
"- rationale (optional)",
|
|
8949
|
+
"- acceptance criteria (optional)",
|
|
8950
|
+
"",
|
|
8951
|
+
"Then call `session_capture` with:",
|
|
8952
|
+
'- event_type: "feature"',
|
|
8953
|
+
"- title: (feature title)",
|
|
8954
|
+
"- content: a well-formatted feature request",
|
|
8955
|
+
"- tags: component/area tags",
|
|
8956
|
+
'- importance: "medium"'
|
|
8957
|
+
].join("\n")
|
|
8958
|
+
}
|
|
8959
|
+
}
|
|
8960
|
+
]
|
|
8961
|
+
})
|
|
8962
|
+
);
|
|
8963
|
+
server.registerPrompt(
|
|
8964
|
+
"generate-plan",
|
|
8965
|
+
{
|
|
8966
|
+
title: `Generate Plan (${promptAccessLabel("generate-plan")})`,
|
|
8967
|
+
description: "Generate a development plan from a description"
|
|
8968
|
+
},
|
|
8969
|
+
async () => ({
|
|
8970
|
+
messages: [
|
|
8971
|
+
{
|
|
8972
|
+
role: "user",
|
|
8973
|
+
content: {
|
|
8974
|
+
type: "text",
|
|
8975
|
+
text: [
|
|
8976
|
+
"Generate a development plan for what I am trying to build/fix.",
|
|
8977
|
+
"",
|
|
8978
|
+
`Access: ${promptAccessLabel("generate-plan")}${promptAccessLabel("generate-plan") === "PRO" ? ` (upgrade: ${upgradeUrl})` : ""}`,
|
|
8979
|
+
"",
|
|
8980
|
+
...ID_NOTES,
|
|
8981
|
+
"",
|
|
8982
|
+
"Use the most recent user request as the plan description. If unclear, ask me for a one-paragraph description.",
|
|
8983
|
+
"",
|
|
8984
|
+
"Then call `ai_plan` and present the plan as an ordered list with milestones and risks."
|
|
8985
|
+
].join("\n")
|
|
8986
|
+
}
|
|
8987
|
+
}
|
|
8988
|
+
]
|
|
8989
|
+
})
|
|
8990
|
+
);
|
|
8991
|
+
server.registerPrompt(
|
|
8992
|
+
"generate-tasks",
|
|
8993
|
+
{
|
|
8994
|
+
title: `Generate Tasks (${promptAccessLabel("generate-tasks")})`,
|
|
8995
|
+
description: "Generate actionable tasks from a plan or description"
|
|
8996
|
+
},
|
|
8997
|
+
async () => ({
|
|
8998
|
+
messages: [
|
|
8999
|
+
{
|
|
9000
|
+
role: "user",
|
|
9001
|
+
content: {
|
|
9002
|
+
type: "text",
|
|
9003
|
+
text: [
|
|
9004
|
+
"Generate actionable tasks for the work we are discussing.",
|
|
9005
|
+
"",
|
|
9006
|
+
`Access: ${promptAccessLabel("generate-tasks")}${promptAccessLabel("generate-tasks") === "PRO" ? ` (upgrade: ${upgradeUrl})` : ""}`,
|
|
9007
|
+
"",
|
|
9008
|
+
...ID_NOTES,
|
|
9009
|
+
"",
|
|
9010
|
+
"If a plan_id exists in the conversation, use it. Otherwise use the latest user request as the description.",
|
|
9011
|
+
"If granularity is not specified, default to medium.",
|
|
9012
|
+
"",
|
|
9013
|
+
"Call `ai_tasks` and return a checklist of tasks with acceptance criteria for each."
|
|
9014
|
+
].join("\n")
|
|
9015
|
+
}
|
|
9016
|
+
}
|
|
9017
|
+
]
|
|
9018
|
+
})
|
|
9019
|
+
);
|
|
9020
|
+
server.registerPrompt(
|
|
9021
|
+
"token-budget-context",
|
|
9022
|
+
{
|
|
9023
|
+
title: `Token-Budget Context (${promptAccessLabel("token-budget-context")})`,
|
|
9024
|
+
description: "Get the most relevant context that fits within a token budget"
|
|
9025
|
+
},
|
|
9026
|
+
async () => ({
|
|
9027
|
+
messages: [
|
|
9028
|
+
{
|
|
9029
|
+
role: "user",
|
|
9030
|
+
content: {
|
|
9031
|
+
type: "text",
|
|
9032
|
+
text: [
|
|
9033
|
+
"Build the most relevant context that fits within a token budget.",
|
|
9034
|
+
"",
|
|
9035
|
+
`Access: ${promptAccessLabel("token-budget-context")}${promptAccessLabel("token-budget-context") === "PRO" ? ` (upgrade: ${upgradeUrl})` : ""}`,
|
|
9036
|
+
"",
|
|
9037
|
+
...ID_NOTES,
|
|
9038
|
+
"",
|
|
9039
|
+
"First:",
|
|
9040
|
+
"- If a query is clear from the conversation, use it; otherwise ask me for a query.",
|
|
9041
|
+
"- If max_tokens is not specified, ask me for a token budget (e.g., 500/1000/2000).",
|
|
9042
|
+
"",
|
|
9043
|
+
"Then call `ai_context_budget` and return the packed context plus a short note about what was included/excluded."
|
|
9044
|
+
].join("\n")
|
|
9045
|
+
}
|
|
9046
|
+
}
|
|
9047
|
+
]
|
|
9048
|
+
})
|
|
9049
|
+
);
|
|
9050
|
+
server.registerPrompt(
|
|
9051
|
+
"find-todos",
|
|
9052
|
+
{
|
|
9053
|
+
title: `Find TODOs (${promptAccessLabel("find-todos")})`,
|
|
9054
|
+
description: "Scan the codebase for TODO/FIXME/HACK notes and summarize"
|
|
9055
|
+
},
|
|
9056
|
+
async () => ({
|
|
9057
|
+
messages: [
|
|
9058
|
+
{
|
|
9059
|
+
role: "user",
|
|
9060
|
+
content: {
|
|
9061
|
+
type: "text",
|
|
9062
|
+
text: [
|
|
9063
|
+
"Scan the codebase for TODO/FIXME/HACK notes and summarize them.",
|
|
9064
|
+
"",
|
|
9065
|
+
...ID_NOTES,
|
|
9066
|
+
"",
|
|
9067
|
+
"Use `search_pattern` with query `TODO|FIXME|HACK` (or a pattern inferred from the conversation).",
|
|
9068
|
+
"Group results by file path, summarize themes, and propose a small prioritized cleanup list."
|
|
9069
|
+
].join("\n")
|
|
9070
|
+
}
|
|
9071
|
+
}
|
|
9072
|
+
]
|
|
9073
|
+
})
|
|
9074
|
+
);
|
|
9075
|
+
server.registerPrompt(
|
|
9076
|
+
"generate-editor-rules",
|
|
9077
|
+
{
|
|
9078
|
+
title: `Generate Editor Rules (${promptAccessLabel("generate-editor-rules")})`,
|
|
9079
|
+
description: "Generate ContextStream AI rule files for your editor"
|
|
9080
|
+
},
|
|
9081
|
+
async () => ({
|
|
9082
|
+
messages: [
|
|
9083
|
+
{
|
|
9084
|
+
role: "user",
|
|
9085
|
+
content: {
|
|
9086
|
+
type: "text",
|
|
9087
|
+
text: [
|
|
9088
|
+
"Generate ContextStream AI rule files for my editor.",
|
|
9089
|
+
"",
|
|
9090
|
+
...ID_NOTES,
|
|
9091
|
+
"",
|
|
9092
|
+
"First:",
|
|
9093
|
+
"- If you can infer the project folder path from the environment/IDE roots, use it.",
|
|
9094
|
+
"- Otherwise ask me for an absolute folder path.",
|
|
9095
|
+
"- Ask which editor(s) (windsurf,cursor,cline,kilo,roo,claude,aider) or default to all.",
|
|
9096
|
+
"",
|
|
9097
|
+
"Then call `generate_editor_rules` and confirm which files were created/updated."
|
|
9098
|
+
].join("\n")
|
|
9099
|
+
}
|
|
9100
|
+
}
|
|
9101
|
+
]
|
|
9102
|
+
})
|
|
9103
|
+
);
|
|
9104
|
+
server.registerPrompt(
|
|
9105
|
+
"index-local-repo",
|
|
9106
|
+
{
|
|
9107
|
+
title: `Index Local Repo (${promptAccessLabel("index-local-repo")})`,
|
|
9108
|
+
description: "Ingest local files into ContextStream for indexing/search"
|
|
9109
|
+
},
|
|
9110
|
+
async () => ({
|
|
9111
|
+
messages: [
|
|
9112
|
+
{
|
|
9113
|
+
role: "user",
|
|
9114
|
+
content: {
|
|
9115
|
+
type: "text",
|
|
9116
|
+
text: [
|
|
9117
|
+
"Ingest local files into ContextStream for indexing/search.",
|
|
9118
|
+
"",
|
|
9119
|
+
...ID_NOTES,
|
|
9120
|
+
"",
|
|
9121
|
+
"First:",
|
|
9122
|
+
"- Ask me for the local directory path to ingest if it is not already specified.",
|
|
9123
|
+
"",
|
|
9124
|
+
"Then:",
|
|
9125
|
+
"- Call `projects_ingest_local` with the path (use session defaults for project, or the `project_id` returned by `session_init`).",
|
|
9126
|
+
"- Explain how to monitor progress via `projects_index_status`."
|
|
9127
|
+
].join("\n")
|
|
8410
9128
|
}
|
|
8411
9129
|
}
|
|
8412
9130
|
]
|
|
@@ -8587,6 +9305,25 @@ var SessionManager = class {
|
|
|
8587
9305
|
parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
8588
9306
|
parts.push("\u{1F9E0} AUTO-CONTEXT LOADED (ContextStream)");
|
|
8589
9307
|
parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
9308
|
+
if (context.status === "requires_workspace_name") {
|
|
9309
|
+
parts.push("");
|
|
9310
|
+
parts.push("\u26A0\uFE0F NO WORKSPACE FOUND");
|
|
9311
|
+
parts.push(`Folder: ${context.folder_name || "unknown"}`);
|
|
9312
|
+
parts.push("");
|
|
9313
|
+
parts.push("Please ask the user for a name for the new workspace.");
|
|
9314
|
+
parts.push("Then create a project for this folder.");
|
|
9315
|
+
parts.push("");
|
|
9316
|
+
parts.push("Recommended: call `workspace_bootstrap` with:");
|
|
9317
|
+
if (typeof context.folder_path === "string") {
|
|
9318
|
+
parts.push(` - folder_path: ${context.folder_path}`);
|
|
9319
|
+
} else {
|
|
9320
|
+
parts.push(" - folder_path: (your repo folder path)");
|
|
9321
|
+
}
|
|
9322
|
+
parts.push(' - workspace_name: "<user-provided name>"');
|
|
9323
|
+
parts.push("");
|
|
9324
|
+
parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
9325
|
+
return parts.join("\n");
|
|
9326
|
+
}
|
|
8590
9327
|
if (context.status === "requires_workspace_selection") {
|
|
8591
9328
|
parts.push("");
|
|
8592
9329
|
parts.push("\u26A0\uFE0F NEW FOLDER DETECTED");
|
|
@@ -8643,6 +9380,21 @@ var SessionManager = class {
|
|
|
8643
9380
|
parts.push(` \u2022 [${type}] ${title}`);
|
|
8644
9381
|
});
|
|
8645
9382
|
}
|
|
9383
|
+
const lessonsWarning = typeof context.lessons_warning === "string" ? context.lessons_warning : void 0;
|
|
9384
|
+
const lessons = Array.isArray(context.lessons) ? context.lessons : [];
|
|
9385
|
+
if (lessonsWarning || lessons.length > 0) {
|
|
9386
|
+
parts.push("");
|
|
9387
|
+
parts.push("\u26A0\uFE0F Lessons (review before changes):");
|
|
9388
|
+
if (lessonsWarning) {
|
|
9389
|
+
parts.push(` ${lessonsWarning}`);
|
|
9390
|
+
}
|
|
9391
|
+
lessons.slice(0, 3).forEach((l) => {
|
|
9392
|
+
const title = l.title || "Lesson";
|
|
9393
|
+
const severity = l.severity || "unknown";
|
|
9394
|
+
parts.push(` \u2022 [${severity}] ${title}`);
|
|
9395
|
+
});
|
|
9396
|
+
parts.push(' Use session_get_lessons(query="...") for details.');
|
|
9397
|
+
}
|
|
8646
9398
|
parts.push("");
|
|
8647
9399
|
if (context.ide_roots && context.ide_roots.length > 0) {
|
|
8648
9400
|
const roots = context.ide_roots;
|
|
@@ -8705,6 +9457,8 @@ Environment variables:
|
|
|
8705
9457
|
CONTEXTSTREAM_JWT JWT for authentication (alternative to API key)
|
|
8706
9458
|
CONTEXTSTREAM_WORKSPACE_ID Optional default workspace ID
|
|
8707
9459
|
CONTEXTSTREAM_PROJECT_ID Optional default project ID
|
|
9460
|
+
CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
|
|
9461
|
+
CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
|
|
8708
9462
|
|
|
8709
9463
|
Examples:
|
|
8710
9464
|
CONTEXTSTREAM_API_URL="https://api.contextstream.io" \\
|