@contextstream/mcp-server 0.4.48 → 0.4.49
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/hooks/auto-rules.js +5 -6
- package/dist/hooks/user-prompt-submit.js +10 -5
- package/dist/index.js +295 -104
- package/package.json +1 -1
package/dist/hooks/auto-rules.js
CHANGED
|
@@ -105,7 +105,7 @@ function buildHooksConfig(options) {
|
|
|
105
105
|
],
|
|
106
106
|
UserPromptSubmit: userPromptHooks
|
|
107
107
|
};
|
|
108
|
-
if (options?.includePreCompact) {
|
|
108
|
+
if (options?.includePreCompact !== false) {
|
|
109
109
|
config.PreCompact = [
|
|
110
110
|
{
|
|
111
111
|
// Match both manual (/compact) and automatic compaction
|
|
@@ -157,7 +157,7 @@ async function installHookScripts(options) {
|
|
|
157
157
|
preToolUse: "npx @contextstream/mcp-server hook pre-tool-use",
|
|
158
158
|
userPrompt: "npx @contextstream/mcp-server hook user-prompt-submit"
|
|
159
159
|
};
|
|
160
|
-
if (options?.includePreCompact) {
|
|
160
|
+
if (options?.includePreCompact !== false) {
|
|
161
161
|
result.preCompact = "npx @contextstream/mcp-server hook pre-compact";
|
|
162
162
|
}
|
|
163
163
|
if (options?.includeMediaAware !== false) {
|
|
@@ -203,7 +203,7 @@ async function installClaudeCodeHooks(options) {
|
|
|
203
203
|
"npx @contextstream/mcp-server hook pre-tool-use",
|
|
204
204
|
"npx @contextstream/mcp-server hook user-prompt-submit"
|
|
205
205
|
);
|
|
206
|
-
if (options.includePreCompact) {
|
|
206
|
+
if (options.includePreCompact !== false) {
|
|
207
207
|
result.scripts.push("npx @contextstream/mcp-server hook pre-compact");
|
|
208
208
|
}
|
|
209
209
|
if (options.includeMediaAware !== false) {
|
|
@@ -270,12 +270,11 @@ When Media-Aware hook detects media patterns, it injects context about:
|
|
|
270
270
|
- How to get clips for Remotion (with frame-based props)
|
|
271
271
|
- How to index new media files
|
|
272
272
|
|
|
273
|
-
### PreCompact Hook
|
|
273
|
+
### PreCompact Hook
|
|
274
274
|
- **Command:** \`npx @contextstream/mcp-server hook pre-compact\`
|
|
275
275
|
- **Purpose:** Saves conversation state before context compaction
|
|
276
276
|
- **Triggers:** Both manual (/compact) and automatic compaction
|
|
277
|
-
- **
|
|
278
|
-
- **Note:** Enable with \`generate_rules(include_pre_compact=true)\` to activate
|
|
277
|
+
- **Installed:** By default (disable with \`CONTEXTSTREAM_HOOK_ENABLED=false\`)
|
|
279
278
|
|
|
280
279
|
When PreCompact runs, it:
|
|
281
280
|
1. Parses the transcript for active files and tool calls
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
// src/hooks/user-prompt-submit.ts
|
|
4
4
|
var ENABLED = process.env.CONTEXTSTREAM_REMINDER_ENABLED !== "false";
|
|
5
|
-
var REMINDER = `[CONTEXTSTREAM
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
var REMINDER = `[CONTEXTSTREAM - DO THIS FIRST]
|
|
6
|
+
mcp__contextstream__context(user_message="<user's message>") - CALL THIS BEFORE ANY OTHER TOOL
|
|
7
|
+
|
|
8
|
+
Why: Delivers task-specific rules, lessons from past mistakes, and relevant context.
|
|
9
|
+
Skip it = repeat past mistakes, miss relevant decisions, fly blind.
|
|
10
|
+
|
|
11
|
+
BEFORE Glob/Grep/Read/Search/Explore:
|
|
12
|
+
mcp__contextstream__search(mode="hybrid", query="...") FIRST
|
|
13
|
+
Local tools ONLY if search returns 0 results.
|
|
14
|
+
[END]`;
|
|
10
15
|
function detectEditorFormat(input) {
|
|
11
16
|
if (input.hookName !== void 0) {
|
|
12
17
|
return "cline";
|
package/dist/index.js
CHANGED
|
@@ -591,7 +591,7 @@ function buildHooksConfig(options) {
|
|
|
591
591
|
],
|
|
592
592
|
UserPromptSubmit: userPromptHooks
|
|
593
593
|
};
|
|
594
|
-
if (options?.includePreCompact) {
|
|
594
|
+
if (options?.includePreCompact !== false) {
|
|
595
595
|
config.PreCompact = [
|
|
596
596
|
{
|
|
597
597
|
// Match both manual (/compact) and automatic compaction
|
|
@@ -643,7 +643,7 @@ async function installHookScripts(options) {
|
|
|
643
643
|
preToolUse: "npx @contextstream/mcp-server hook pre-tool-use",
|
|
644
644
|
userPrompt: "npx @contextstream/mcp-server hook user-prompt-submit"
|
|
645
645
|
};
|
|
646
|
-
if (options?.includePreCompact) {
|
|
646
|
+
if (options?.includePreCompact !== false) {
|
|
647
647
|
result.preCompact = "npx @contextstream/mcp-server hook pre-compact";
|
|
648
648
|
}
|
|
649
649
|
if (options?.includeMediaAware !== false) {
|
|
@@ -689,7 +689,7 @@ async function installClaudeCodeHooks(options) {
|
|
|
689
689
|
"npx @contextstream/mcp-server hook pre-tool-use",
|
|
690
690
|
"npx @contextstream/mcp-server hook user-prompt-submit"
|
|
691
691
|
);
|
|
692
|
-
if (options.includePreCompact) {
|
|
692
|
+
if (options.includePreCompact !== false) {
|
|
693
693
|
result.scripts.push("npx @contextstream/mcp-server hook pre-compact");
|
|
694
694
|
}
|
|
695
695
|
if (options.includeMediaAware !== false) {
|
|
@@ -756,12 +756,11 @@ When Media-Aware hook detects media patterns, it injects context about:
|
|
|
756
756
|
- How to get clips for Remotion (with frame-based props)
|
|
757
757
|
- How to index new media files
|
|
758
758
|
|
|
759
|
-
### PreCompact Hook
|
|
759
|
+
### PreCompact Hook
|
|
760
760
|
- **Command:** \`npx @contextstream/mcp-server hook pre-compact\`
|
|
761
761
|
- **Purpose:** Saves conversation state before context compaction
|
|
762
762
|
- **Triggers:** Both manual (/compact) and automatic compaction
|
|
763
|
-
- **
|
|
764
|
-
- **Note:** Enable with \`generate_rules(include_pre_compact=true)\` to activate
|
|
763
|
+
- **Installed:** By default (disable with \`CONTEXTSTREAM_HOOK_ENABLED=false\`)
|
|
765
764
|
|
|
766
765
|
When PreCompact runs, it:
|
|
767
766
|
1. Parses the transcript for active files and tool calls
|
|
@@ -2633,11 +2632,16 @@ var init_user_prompt_submit = __esm({
|
|
|
2633
2632
|
"src/hooks/user-prompt-submit.ts"() {
|
|
2634
2633
|
"use strict";
|
|
2635
2634
|
ENABLED3 = process.env.CONTEXTSTREAM_REMINDER_ENABLED !== "false";
|
|
2636
|
-
REMINDER = `[CONTEXTSTREAM
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2635
|
+
REMINDER = `[CONTEXTSTREAM - DO THIS FIRST]
|
|
2636
|
+
mcp__contextstream__context(user_message="<user's message>") - CALL THIS BEFORE ANY OTHER TOOL
|
|
2637
|
+
|
|
2638
|
+
Why: Delivers task-specific rules, lessons from past mistakes, and relevant context.
|
|
2639
|
+
Skip it = repeat past mistakes, miss relevant decisions, fly blind.
|
|
2640
|
+
|
|
2641
|
+
BEFORE Glob/Grep/Read/Search/Explore:
|
|
2642
|
+
mcp__contextstream__search(mode="hybrid", query="...") FIRST
|
|
2643
|
+
Local tools ONLY if search returns 0 results.
|
|
2644
|
+
[END]`;
|
|
2641
2645
|
isDirectRun3 = process.argv[1]?.includes("user-prompt-submit") || process.argv[2] === "user-prompt-submit";
|
|
2642
2646
|
if (isDirectRun3) {
|
|
2643
2647
|
runUserPromptSubmitHook().catch(() => process.exit(0));
|
|
@@ -12103,62 +12107,103 @@ function applyMcpToolPrefix(markdown, toolPrefix) {
|
|
|
12103
12107
|
const toolRegex = new RegExp(`(?<!__)\\b(${toolPattern})\\b(?=\\s*\\()`, "g");
|
|
12104
12108
|
return markdown.replace(toolRegex, `${toolPrefix}$1`);
|
|
12105
12109
|
}
|
|
12106
|
-
var
|
|
12107
|
-
|
|
12110
|
+
var CONTEXTSTREAM_RULES_BOOTSTRAP = `
|
|
12111
|
+
<contextstream_rules>
|
|
12112
|
+
| Message | Required |
|
|
12113
|
+
|---------|----------|
|
|
12114
|
+
| **1st message** | \`init()\` \u2192 \`context(user_message="...")\` |
|
|
12115
|
+
| **Every message** | \`context(user_message="...")\` FIRST |
|
|
12116
|
+
| **Before file search** | \`search(mode="hybrid")\` BEFORE Glob/Grep/Read |
|
|
12117
|
+
</contextstream_rules>
|
|
12108
12118
|
|
|
12109
|
-
|
|
12119
|
+
**Why?** \`context()\` delivers task-specific rules, lessons from past mistakes, and relevant decisions. Skip it = fly blind.
|
|
12110
12120
|
|
|
12111
|
-
|
|
12112
|
-
**EVERY response MUST start with:**
|
|
12113
|
-
1. \`init()\` (1st message only) \u2192 then \`context(user_message="<msg>")\`
|
|
12114
|
-
2. \`context(user_message="<msg>")\` (EVERY subsequent message)
|
|
12121
|
+
**Hooks:** \`<system-reminder>\` tags contain injected instructions \u2014 follow them exactly.
|
|
12115
12122
|
|
|
12116
|
-
**
|
|
12117
|
-
\u2192 \`search(mode="hybrid", query="...")\` FIRST \u2014 local tools ONLY if 0 results
|
|
12123
|
+
**Notices:** [LESSONS_WARNING] \u2192 tell user first | [RULES_NOTICE] \u2192 run \`generate_rules()\` | [VERSION_NOTICE] \u2192 tell user to update
|
|
12118
12124
|
|
|
12119
|
-
|
|
12120
|
-
|
|
12125
|
+
v${RULES_VERSION}
|
|
12126
|
+
`.trim();
|
|
12127
|
+
var CONTEXTSTREAM_RULES_DYNAMIC = CONTEXTSTREAM_RULES_BOOTSTRAP;
|
|
12128
|
+
var CONTEXTSTREAM_RULES_FULL = `
|
|
12129
|
+
## \u{1F6A8} MANDATORY: CALL CONTEXT EVERY MESSAGE \u{1F6A8}
|
|
12121
12130
|
|
|
12122
|
-
|
|
12131
|
+
<contextstream_rules>
|
|
12132
|
+
**EVERY response MUST start with \`context(user_message="...")\`**
|
|
12123
12133
|
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12134
|
+
| Message | What to Call |
|
|
12135
|
+
|---------|--------------|
|
|
12136
|
+
| 1st message | \`init()\` \u2192 \`context(user_message="<msg>")\` |
|
|
12137
|
+
| **EVERY message after** | \`context(user_message="<msg>")\` **FIRST** |
|
|
12128
12138
|
|
|
12129
|
-
|
|
12139
|
+
**BEFORE Glob/Grep/Read/Search:** \u2192 \`search(mode="hybrid")\` FIRST
|
|
12140
|
+
</contextstream_rules>
|
|
12130
12141
|
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12142
|
+
**This block MUST appear at the start of EVERY response.** Failing to call \`context()\` means missing rules, lessons, and relevant context.
|
|
12143
|
+
|
|
12144
|
+
---
|
|
12145
|
+
|
|
12146
|
+
## Why \`context()\` is MANDATORY Every Message
|
|
12147
|
+
|
|
12148
|
+
\u274C **WRONG:** "I already called init, I don't need context"
|
|
12149
|
+
\u2705 **CORRECT:** \`context()\` is required EVERY message, not just the first
|
|
12138
12150
|
|
|
12139
|
-
|
|
12151
|
+
**What you lose without \`context()\`:**
|
|
12152
|
+
- Dynamic rules matched to your current task
|
|
12153
|
+
- Lessons from past mistakes (you WILL repeat them)
|
|
12154
|
+
- Semantically relevant decisions and context
|
|
12155
|
+
- Warnings about risky operations
|
|
12156
|
+
|
|
12157
|
+
**\`init()\` gives recent items by TIME. \`context()\` finds items RELEVANT to THIS message.**
|
|
12158
|
+
|
|
12159
|
+
---
|
|
12160
|
+
|
|
12161
|
+
## Handle Notices from context()
|
|
12140
12162
|
|
|
12141
12163
|
- **[LESSONS_WARNING]** \u2192 Tell user about past mistakes BEFORE proceeding
|
|
12142
12164
|
- **[RULES_NOTICE]** \u2192 Run \`generate_rules()\` to update
|
|
12143
12165
|
- **[VERSION_NOTICE]** \u2192 Tell user to update MCP
|
|
12144
12166
|
|
|
12145
|
-
|
|
12167
|
+
---
|
|
12146
12168
|
|
|
12147
|
-
|
|
12148
|
-
\u2192 Just execute directly: \`workspace(action="list")\`, \`help(action="version")\`
|
|
12169
|
+
## \u{1F6A8} HOOKS - AUTOMATIC RULE ENFORCEMENT \u{1F6A8}
|
|
12149
12170
|
|
|
12150
|
-
|
|
12151
|
-
`.trim();
|
|
12152
|
-
var CONTEXTSTREAM_RULES_FULL = `
|
|
12153
|
-
## ContextStream Rules
|
|
12171
|
+
**ContextStream installs hooks that automatically enforce rules.** You MUST follow hook output.
|
|
12154
12172
|
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12173
|
+
### Installed Hooks
|
|
12174
|
+
|
|
12175
|
+
| Hook | What It Does | Output |
|
|
12176
|
+
|------|--------------|--------|
|
|
12177
|
+
| **UserPromptSubmit** | Injects rules reminder on EVERY message | \`<system-reminder>\` with rules block |
|
|
12178
|
+
| **PreToolUse** | Blocks Glob/Grep/Search/Explore when ContextStream is available | Error message redirecting to \`search()\` |
|
|
12179
|
+
| **PostToolUse** | Auto-indexes files after Edit/Write operations | Background indexing |
|
|
12180
|
+
| **PreCompact** | Saves session state before context compaction | Snapshot creation |
|
|
12181
|
+
|
|
12182
|
+
### How Hooks Work
|
|
12183
|
+
|
|
12184
|
+
1. **\`<system-reminder>\` tags** - Injected by UserPromptSubmit hook on every message
|
|
12185
|
+
- These tags contain the current rules
|
|
12186
|
+
- **FOLLOW THE INSTRUCTIONS INSIDE** - they ARE the rules
|
|
12187
|
+
- Example: \`[CONTEXTSTREAM RULES] 1. BEFORE Glob/Grep... [END RULES]\`
|
|
12160
12188
|
|
|
12161
|
-
**
|
|
12189
|
+
2. **PreToolUse blocking** - If you try to use Glob/Grep/Search/Explore:
|
|
12190
|
+
- Hook returns error: \`STOP: Use mcp__contextstream__search(mode="hybrid") instead\`
|
|
12191
|
+
- **You MUST use the suggested ContextStream tool instead**
|
|
12192
|
+
- Local tools are only allowed if project is not indexed or ContextStream returns 0 results
|
|
12193
|
+
|
|
12194
|
+
3. **PostToolUse indexing** - After Edit/Write operations:
|
|
12195
|
+
- Changed files are automatically re-indexed
|
|
12196
|
+
- No action required from you
|
|
12197
|
+
|
|
12198
|
+
4. **PreCompact snapshots** - Before context compaction:
|
|
12199
|
+
- Hook reminds you to save important state
|
|
12200
|
+
- Call \`session(action="capture", event_type="session_snapshot", ...)\` when warned
|
|
12201
|
+
|
|
12202
|
+
### Disabling Hooks
|
|
12203
|
+
|
|
12204
|
+
Set environment variable: \`CONTEXTSTREAM_HOOK_ENABLED=false\`
|
|
12205
|
+
|
|
12206
|
+
**Note:** Disabling hooks removes rule enforcement. Only disable for debugging.
|
|
12162
12207
|
|
|
12163
12208
|
---
|
|
12164
12209
|
|
|
@@ -12244,27 +12289,27 @@ You have access to ContextStream MCP tools for persistent memory and context.
|
|
|
12244
12289
|
v0.4.x uses **~11 consolidated domain tools** for ~75% token reduction vs previous versions.
|
|
12245
12290
|
Rules Version: ${RULES_VERSION}
|
|
12246
12291
|
|
|
12247
|
-
## TL;DR -
|
|
12292
|
+
## TL;DR - CONTEXT EVERY MESSAGE
|
|
12248
12293
|
|
|
12249
|
-
|
|
|
12250
|
-
|
|
12251
|
-
|
|
|
12252
|
-
|
|
|
12253
|
-
|
|
|
12254
|
-
|
|
|
12255
|
-
| **User
|
|
12294
|
+
| Message | Required |
|
|
12295
|
+
|---------|----------|
|
|
12296
|
+
| **1st message** | \`init()\` \u2192 \`context(user_message="<msg>")\` |
|
|
12297
|
+
| **EVERY message after** | \`context(user_message="<msg>")\` **FIRST** |
|
|
12298
|
+
| **Before file search** | \`search(mode="hybrid")\` FIRST |
|
|
12299
|
+
| **After significant work** | \`session(action="capture", event_type="decision", ...)\` |
|
|
12300
|
+
| **User correction** | \`session(action="capture_lesson", ...)\` |
|
|
12256
12301
|
|
|
12257
|
-
###
|
|
12302
|
+
### Why EVERY Message?
|
|
12258
12303
|
|
|
12259
|
-
|
|
12260
|
-
-
|
|
12261
|
-
-
|
|
12262
|
-
-
|
|
12263
|
-
-
|
|
12304
|
+
\`context()\` delivers:
|
|
12305
|
+
- **Dynamic rules** matched to your current task
|
|
12306
|
+
- **Lessons** from past mistakes (prevents repeating errors)
|
|
12307
|
+
- **Relevant decisions** and context (semantic search)
|
|
12308
|
+
- **Warnings** about risky operations
|
|
12264
12309
|
|
|
12265
|
-
**
|
|
12310
|
+
**Without \`context()\`, you are blind to relevant context and will repeat past mistakes.**
|
|
12266
12311
|
|
|
12267
|
-
###
|
|
12312
|
+
### Protocol
|
|
12268
12313
|
|
|
12269
12314
|
| Step | What to Call |
|
|
12270
12315
|
|------|--------------|
|
|
@@ -12275,12 +12320,7 @@ Rules Version: ${RULES_VERSION}
|
|
|
12275
12320
|
| **User correction** | \`session(action="capture_lesson", ...)\` |
|
|
12276
12321
|
| **\u26A0\uFE0F When warnings received** | **STOP**, acknowledge, explain mitigation, then proceed |
|
|
12277
12322
|
|
|
12278
|
-
**
|
|
12279
|
-
- Single-word commands: "list", "show", "version", "help"
|
|
12280
|
-
- Data retrieval with no context dependency: "list my workspaces", "what projects do I have"
|
|
12281
|
-
- Status checks: "am I authenticated?", "what's the server version?"
|
|
12282
|
-
|
|
12283
|
-
**First message rule (for coding tasks):** After \`init\`:
|
|
12323
|
+
**First message rule:** After \`init\`:
|
|
12284
12324
|
1. Check for \`lessons\` in response - if present, READ and SUMMARIZE them to user
|
|
12285
12325
|
2. Then call \`context\` before any other tool or response
|
|
12286
12326
|
|
|
@@ -12380,8 +12420,8 @@ ContextStream tracks context pressure to help you stay ahead of conversation com
|
|
|
12380
12420
|
- \`prepare_save\`: Start thinking about saving important state
|
|
12381
12421
|
- \`save_now\`: Immediately call \`session(action="capture", event_type="session_snapshot")\` to preserve state
|
|
12382
12422
|
|
|
12383
|
-
**PreCompact Hook
|
|
12384
|
-
|
|
12423
|
+
**PreCompact Hook:** Automatically saves session state before context compaction.
|
|
12424
|
+
Installed by default. Disable with: \`CONTEXTSTREAM_HOOK_ENABLED=false\`
|
|
12385
12425
|
|
|
12386
12426
|
**Before compaction happens (when warned):**
|
|
12387
12427
|
\`\`\`
|
|
@@ -12678,7 +12718,7 @@ Everything else = full protocol (init \u2192 context \u2192 search \u2192 work)
|
|
|
12678
12718
|
### Context Pressure & Compaction
|
|
12679
12719
|
|
|
12680
12720
|
- If \`context\` returns high/critical \`context_pressure\`: call \`session(action="capture", ...)\` to save state
|
|
12681
|
-
- PreCompact hooks automatically save snapshots before compaction
|
|
12721
|
+
- PreCompact hooks automatically save snapshots before compaction
|
|
12682
12722
|
|
|
12683
12723
|
### Enhanced Context (Warnings)
|
|
12684
12724
|
|
|
@@ -12793,8 +12833,8 @@ function getTemplate(editor) {
|
|
|
12793
12833
|
function generateRuleContent(editor, options) {
|
|
12794
12834
|
const template = getTemplate(editor);
|
|
12795
12835
|
if (!template) return null;
|
|
12796
|
-
const mode = options?.mode || "
|
|
12797
|
-
const rules = mode === "full" ? CONTEXTSTREAM_RULES_FULL : mode === "minimal" ? CONTEXTSTREAM_RULES_MINIMAL : CONTEXTSTREAM_RULES_DYNAMIC;
|
|
12836
|
+
const mode = options?.mode || "bootstrap";
|
|
12837
|
+
const rules = mode === "full" ? CONTEXTSTREAM_RULES_FULL : mode === "minimal" ? CONTEXTSTREAM_RULES_MINIMAL : mode === "bootstrap" ? CONTEXTSTREAM_RULES_BOOTSTRAP : CONTEXTSTREAM_RULES_DYNAMIC;
|
|
12798
12838
|
let content = template.build(rules);
|
|
12799
12839
|
if (options?.workspaceName || options?.projectName) {
|
|
12800
12840
|
const header = `
|
|
@@ -13070,6 +13110,112 @@ function trackToolTokenSavings(client, tool, contextText, params, extraMetadata)
|
|
|
13070
13110
|
}
|
|
13071
13111
|
}
|
|
13072
13112
|
|
|
13113
|
+
// src/educational-microcopy.ts
|
|
13114
|
+
var SESSION_INIT_TIPS = [
|
|
13115
|
+
"AI work that doesn't disappear.",
|
|
13116
|
+
"Every conversation builds context. Every artifact persists.",
|
|
13117
|
+
"Your AI remembers. Now you can see what it knows.",
|
|
13118
|
+
"Context that survives sessions.",
|
|
13119
|
+
"The bridge between AI conversations and human artifacts."
|
|
13120
|
+
];
|
|
13121
|
+
function getSessionInitTip(sessionId) {
|
|
13122
|
+
const index = sessionId ? Math.abs(hashString(sessionId)) % SESSION_INIT_TIPS.length : Math.floor(Math.random() * SESSION_INIT_TIPS.length);
|
|
13123
|
+
return SESSION_INIT_TIPS[index];
|
|
13124
|
+
}
|
|
13125
|
+
var CAPTURE_HINTS = {
|
|
13126
|
+
// Core event types
|
|
13127
|
+
decision: "Future you will thank present you.",
|
|
13128
|
+
preference: "Noted. This will inform future suggestions.",
|
|
13129
|
+
insight: "Captured for future reference.",
|
|
13130
|
+
note: "Saved. Won't disappear when the chat does.",
|
|
13131
|
+
implementation: "Implementation recorded.",
|
|
13132
|
+
task: "Task tracked.",
|
|
13133
|
+
bug: "Bug logged for tracking.",
|
|
13134
|
+
feature: "Feature request captured.",
|
|
13135
|
+
plan: "This plan will be here when you come back.",
|
|
13136
|
+
correction: "Correction noted. Learning from this.",
|
|
13137
|
+
lesson: "Learn once, remember forever.",
|
|
13138
|
+
warning: "Warning logged.",
|
|
13139
|
+
frustration: "Feedback captured. We're listening.",
|
|
13140
|
+
conversation: "Conversation preserved.",
|
|
13141
|
+
session_snapshot: "Session state saved. Ready to resume anytime."
|
|
13142
|
+
};
|
|
13143
|
+
function getCaptureHint(eventType) {
|
|
13144
|
+
return CAPTURE_HINTS[eventType] || "Captured. This will survive when the chat disappears.";
|
|
13145
|
+
}
|
|
13146
|
+
var EMPTY_STATE_HINTS = {
|
|
13147
|
+
// Plans
|
|
13148
|
+
list_plans: "No plans yet. Plans live here, not in chat transcripts.",
|
|
13149
|
+
get_plan: "Plan not found. Create one to track implementation across sessions.",
|
|
13150
|
+
// Memory & Search
|
|
13151
|
+
recall: "Nothing found yet. Context builds over time.",
|
|
13152
|
+
search: "No matches. Try a different query or let context accumulate.",
|
|
13153
|
+
list_events: "No events yet. Start capturing decisions and insights.",
|
|
13154
|
+
decisions: "No decisions captured yet. Record the 'why' behind your choices.",
|
|
13155
|
+
timeline: "Timeline empty. Events will appear as you work.",
|
|
13156
|
+
// Lessons
|
|
13157
|
+
get_lessons: "No lessons yet. Capture mistakes to learn from them.",
|
|
13158
|
+
// Tasks
|
|
13159
|
+
list_tasks: "No tasks yet. Break plans into trackable tasks.",
|
|
13160
|
+
// Todos
|
|
13161
|
+
list_todos: "No todos yet. Action items will appear here.",
|
|
13162
|
+
// Diagrams
|
|
13163
|
+
list_diagrams: "No diagrams yet. AI-generated diagrams persist here.",
|
|
13164
|
+
// Docs
|
|
13165
|
+
list_docs: "No docs yet. Turn AI explanations into shareable documentation.",
|
|
13166
|
+
// Reminders
|
|
13167
|
+
list_reminders: "No reminders set. Schedule follow-ups that won't be forgotten.",
|
|
13168
|
+
// Generic
|
|
13169
|
+
default: "Nothing yet. Start a conversation\u2014context builds over time."
|
|
13170
|
+
};
|
|
13171
|
+
function getEmptyStateHint(action) {
|
|
13172
|
+
return EMPTY_STATE_HINTS[action] || EMPTY_STATE_HINTS.default;
|
|
13173
|
+
}
|
|
13174
|
+
var POST_COMPACT_HINTS = {
|
|
13175
|
+
restored: "Picked up where you left off. Session ended, memory didn't.",
|
|
13176
|
+
restored_with_session: (sessionId) => `Restored from session ${sessionId}. Session ended, memory didn't.`,
|
|
13177
|
+
no_snapshot: "No prior session found. Fresh start\u2014context will build as you work.",
|
|
13178
|
+
failed: "Couldn't restore previous session. Use context to retrieve what you need."
|
|
13179
|
+
};
|
|
13180
|
+
var PLAN_HINTS = {
|
|
13181
|
+
created: "Plan saved. It will be here when you come back.",
|
|
13182
|
+
activated: "Plan is now active. Track progress across sessions.",
|
|
13183
|
+
completed: "Plan completed. The journey is preserved for future reference.",
|
|
13184
|
+
abandoned: "Plan archived. Abandoned plans still teach.",
|
|
13185
|
+
updated: "Plan updated. Changes are preserved."
|
|
13186
|
+
};
|
|
13187
|
+
function getPlanStatusHint(status) {
|
|
13188
|
+
const statusMap = {
|
|
13189
|
+
draft: PLAN_HINTS.created,
|
|
13190
|
+
active: PLAN_HINTS.activated,
|
|
13191
|
+
completed: PLAN_HINTS.completed,
|
|
13192
|
+
abandoned: PLAN_HINTS.abandoned,
|
|
13193
|
+
archived: PLAN_HINTS.abandoned
|
|
13194
|
+
};
|
|
13195
|
+
return statusMap[status] || PLAN_HINTS.updated;
|
|
13196
|
+
}
|
|
13197
|
+
var TASK_HINTS = {
|
|
13198
|
+
created: "Task tracked. It won't disappear when the chat does.",
|
|
13199
|
+
completed: "Task done. Progress is preserved.",
|
|
13200
|
+
blocked: "Task blocked. Capture what's blocking for future reference.",
|
|
13201
|
+
cancelled: "Task cancelled. The history remains."
|
|
13202
|
+
};
|
|
13203
|
+
var INTEGRATION_HINTS = {
|
|
13204
|
+
not_connected: "Connect integrations to sync context where your team already works.",
|
|
13205
|
+
slack: "Context from Slack conversations, connected.",
|
|
13206
|
+
github: "Issues and PRs linked to the decisions behind them.",
|
|
13207
|
+
notion: "Decisions synced to where your team documents."
|
|
13208
|
+
};
|
|
13209
|
+
function hashString(str) {
|
|
13210
|
+
let hash = 0;
|
|
13211
|
+
for (let i = 0; i < str.length; i++) {
|
|
13212
|
+
const char = str.charCodeAt(i);
|
|
13213
|
+
hash = (hash << 5) - hash + char;
|
|
13214
|
+
hash = hash & hash;
|
|
13215
|
+
}
|
|
13216
|
+
return hash;
|
|
13217
|
+
}
|
|
13218
|
+
|
|
13073
13219
|
// src/tools.ts
|
|
13074
13220
|
var LOG_LEVEL = (process.env.CONTEXTSTREAM_LOG_LEVEL || "normal").toLowerCase();
|
|
13075
13221
|
var LOG_QUIET = LOG_LEVEL === "quiet";
|
|
@@ -13135,6 +13281,7 @@ var lastAutoSavePressureLevel = "";
|
|
|
13135
13281
|
var contextCallsSinceLastSave = 0;
|
|
13136
13282
|
var SEARCH_RULES_REMINDER_ENABLED = process.env.CONTEXTSTREAM_SEARCH_REMINDER?.toLowerCase() !== "false";
|
|
13137
13283
|
var SEARCH_RULES_REMINDER = `[SEARCH] Use search(mode="hybrid") before Glob/Grep/Read. Local tools only if 0 results.`;
|
|
13284
|
+
var CONTEXT_CALL_REMINDER = `[CONTEXT] Call context(user_message="...") at start of EVERY response. This is MANDATORY.`;
|
|
13138
13285
|
var LESSONS_REMINDER_PREFIX = `
|
|
13139
13286
|
\u{1F6A8} [LESSONS_WARNING] Past Mistakes Found - READ BEFORE PROCEEDING!
|
|
13140
13287
|
\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
|
|
@@ -16821,6 +16968,8 @@ This does semantic search on the first message. You only need context on subsequ
|
|
|
16821
16968
|
ideRoots
|
|
16822
16969
|
);
|
|
16823
16970
|
result.tools_hint = getCoreToolsHint();
|
|
16971
|
+
const sessionId = typeof result.session_id === "string" ? result.session_id : void 0;
|
|
16972
|
+
result.educational_tip = getSessionInitTip(sessionId);
|
|
16824
16973
|
const shouldRestoreContext = input.is_post_compact ?? RESTORE_CONTEXT_DEFAULT;
|
|
16825
16974
|
if (shouldRestoreContext) {
|
|
16826
16975
|
result.is_post_compact = true;
|
|
@@ -16890,15 +17039,15 @@ This does semantic search on the first message. You only need context on subsequ
|
|
|
16890
17039
|
...snapshotData
|
|
16891
17040
|
};
|
|
16892
17041
|
result.is_post_compact = true;
|
|
16893
|
-
result.post_compact_hint = prevSessionId ?
|
|
17042
|
+
result.post_compact_hint = prevSessionId ? POST_COMPACT_HINTS.restored_with_session(prevSessionId) : POST_COMPACT_HINTS.restored;
|
|
16894
17043
|
} else {
|
|
16895
17044
|
result.is_post_compact = true;
|
|
16896
|
-
result.post_compact_hint =
|
|
17045
|
+
result.post_compact_hint = POST_COMPACT_HINTS.no_snapshot;
|
|
16897
17046
|
}
|
|
16898
17047
|
} catch (err) {
|
|
16899
17048
|
logDebug(`Failed to restore post-compact context: ${err}`);
|
|
16900
17049
|
result.is_post_compact = true;
|
|
16901
|
-
result.post_compact_hint =
|
|
17050
|
+
result.post_compact_hint = POST_COMPACT_HINTS.failed;
|
|
16902
17051
|
}
|
|
16903
17052
|
}
|
|
16904
17053
|
}
|
|
@@ -16934,7 +17083,7 @@ This does semantic search on the first message. You only need context on subsequ
|
|
|
16934
17083
|
slack_connected: intStatus.slack,
|
|
16935
17084
|
github_connected: intStatus.github,
|
|
16936
17085
|
auto_hide_enabled: true,
|
|
16937
|
-
hint: intStatus.slack || intStatus.github ? "Integration tools are now available in the tool list." :
|
|
17086
|
+
hint: intStatus.slack || intStatus.github ? "Integration tools are now available in the tool list." : INTEGRATION_HINTS.not_connected + " https://contextstream.io/settings/integrations"
|
|
16938
17087
|
};
|
|
16939
17088
|
} catch (error) {
|
|
16940
17089
|
logDebug(`Failed to check integration status: ${error}`);
|
|
@@ -17946,11 +18095,11 @@ Supported editors: ${getAvailableEditors().join(", ")}`,
|
|
|
17946
18095
|
workspace_id: external_exports.string().uuid().optional().describe("Workspace ID to include in rules"),
|
|
17947
18096
|
project_name: external_exports.string().optional().describe("Project name to include in rules"),
|
|
17948
18097
|
additional_rules: external_exports.string().optional().describe("Additional project-specific rules to append"),
|
|
17949
|
-
mode: external_exports.enum(["minimal", "full"]).optional().describe("Rule verbosity
|
|
17950
|
-
overwrite_existing: external_exports.boolean().optional().describe("
|
|
18098
|
+
mode: external_exports.enum(["minimal", "full", "bootstrap"]).optional().default("bootstrap").describe("Rule verbosity: bootstrap (~15 lines, recommended), minimal (~80 lines), full (~600 lines)"),
|
|
18099
|
+
overwrite_existing: external_exports.boolean().optional().default(true).describe("Overwrite ContextStream block in existing rule files (default: true). User content outside the block is preserved."),
|
|
17951
18100
|
apply_global: external_exports.boolean().optional().describe("Also write global rule files for supported editors"),
|
|
17952
18101
|
install_hooks: external_exports.boolean().optional().describe("Install Claude Code hooks to enforce ContextStream-first search. Defaults to true for Claude users. Set to false to skip."),
|
|
17953
|
-
include_pre_compact: external_exports.boolean().optional().describe("Include PreCompact hook for automatic state saving before context compaction. Defaults to
|
|
18102
|
+
include_pre_compact: external_exports.boolean().optional().describe("Include PreCompact hook for automatic state saving before context compaction. Defaults to true."),
|
|
17954
18103
|
dry_run: external_exports.boolean().optional().describe("If true, return content without writing files")
|
|
17955
18104
|
})
|
|
17956
18105
|
},
|
|
@@ -18041,7 +18190,7 @@ Supported editors: ${getAvailableEditors().join(", ")}`,
|
|
|
18041
18190
|
{ editor, file: "~/.claude/hooks/contextstream-reminder.py", status: "dry run - would create" },
|
|
18042
18191
|
{ editor, file: "~/.claude/settings.json", status: "dry run - would update" }
|
|
18043
18192
|
);
|
|
18044
|
-
if (input.include_pre_compact) {
|
|
18193
|
+
if (input.include_pre_compact !== false) {
|
|
18045
18194
|
hooksResults.push({ editor, file: "~/.claude/hooks/contextstream-precompact.py", status: "dry run - would create" });
|
|
18046
18195
|
}
|
|
18047
18196
|
} else if (editor === "cline") {
|
|
@@ -18072,7 +18221,7 @@ Supported editors: ${getAvailableEditors().join(", ")}`,
|
|
|
18072
18221
|
const allHookResults = await installAllEditorHooks({
|
|
18073
18222
|
scope: "global",
|
|
18074
18223
|
editors: hookSupportedEditors,
|
|
18075
|
-
includePreCompact: input.include_pre_compact
|
|
18224
|
+
includePreCompact: input.include_pre_compact !== false
|
|
18076
18225
|
});
|
|
18077
18226
|
for (const result of allHookResults) {
|
|
18078
18227
|
for (const file of result.installed) {
|
|
@@ -18659,6 +18808,9 @@ Action: ${cp.suggested_action === "prepare_save" ? "Consider saving important de
|
|
|
18659
18808
|
const instructionsLine = result.instructions ? `
|
|
18660
18809
|
|
|
18661
18810
|
[INSTRUCTIONS] ${result.instructions}` : "";
|
|
18811
|
+
const contextRulesLine = `
|
|
18812
|
+
|
|
18813
|
+
${CONTEXT_CALL_REMINDER}`;
|
|
18662
18814
|
const allWarnings = [
|
|
18663
18815
|
serverWarningsLine || lessonsWarningLine,
|
|
18664
18816
|
// Server warnings OR client-side lesson detection
|
|
@@ -18671,6 +18823,8 @@ ${versionWarningLine}` : "",
|
|
|
18671
18823
|
contextPressureWarning,
|
|
18672
18824
|
semanticHints,
|
|
18673
18825
|
instructionsLine,
|
|
18826
|
+
contextRulesLine,
|
|
18827
|
+
// Reinforce context() must be called every message
|
|
18674
18828
|
searchRulesLine
|
|
18675
18829
|
].filter(Boolean).join("");
|
|
18676
18830
|
const finalContext = postCompactContext + result.context;
|
|
@@ -19929,8 +20083,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
19929
20083
|
code_refs: input.code_refs,
|
|
19930
20084
|
provenance: input.provenance
|
|
19931
20085
|
});
|
|
20086
|
+
const captureHint = getCaptureHint(input.event_type);
|
|
20087
|
+
const resultWithHint = { ...result, hint: captureHint };
|
|
19932
20088
|
return {
|
|
19933
|
-
content: [{ type: "text", text: formatContent(
|
|
20089
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
19934
20090
|
};
|
|
19935
20091
|
}
|
|
19936
20092
|
case "capture_lesson": {
|
|
@@ -19986,8 +20142,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
19986
20142
|
importance: input.severity === "critical" ? "critical" : input.severity === "high" ? "high" : "medium",
|
|
19987
20143
|
tags: input.keywords || []
|
|
19988
20144
|
});
|
|
20145
|
+
const lessonHint = getCaptureHint("lesson");
|
|
20146
|
+
const resultWithHint = { ...result, hint: lessonHint };
|
|
19989
20147
|
return {
|
|
19990
|
-
content: [{ type: "text", text: formatContent(
|
|
20148
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
19991
20149
|
};
|
|
19992
20150
|
}
|
|
19993
20151
|
case "get_lessons": {
|
|
@@ -20000,8 +20158,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20000
20158
|
context_hint: input.query,
|
|
20001
20159
|
limit: input.limit
|
|
20002
20160
|
});
|
|
20161
|
+
const lessons = result?.data?.lessons || result?.lessons || [];
|
|
20162
|
+
const resultWithHint = Array.isArray(lessons) && lessons.length === 0 ? { ...result, hint: getEmptyStateHint("get_lessons") } : result;
|
|
20003
20163
|
return {
|
|
20004
|
-
content: [{ type: "text", text: formatContent(
|
|
20164
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20005
20165
|
};
|
|
20006
20166
|
}
|
|
20007
20167
|
case "recall": {
|
|
@@ -20015,7 +20175,9 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20015
20175
|
include_related: input.include_related,
|
|
20016
20176
|
include_decisions: input.include_decisions
|
|
20017
20177
|
});
|
|
20018
|
-
const
|
|
20178
|
+
const recallResults = result?.data?.results || result?.results || [];
|
|
20179
|
+
const recallWithHint = Array.isArray(recallResults) && recallResults.length === 0 ? { ...result, hint: getEmptyStateHint("recall") } : result;
|
|
20180
|
+
const outputText = formatContent(recallWithHint);
|
|
20019
20181
|
trackToolTokenSavings(client, "session_recall", outputText, {
|
|
20020
20182
|
workspace_id: workspaceId,
|
|
20021
20183
|
project_id: projectId
|
|
@@ -20035,8 +20197,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20035
20197
|
content: input.content,
|
|
20036
20198
|
importance
|
|
20037
20199
|
});
|
|
20200
|
+
const rememberHint = getCaptureHint("preference");
|
|
20201
|
+
const resultWithHint = { ...result, hint: rememberHint };
|
|
20038
20202
|
return {
|
|
20039
|
-
content: [{ type: "text", text: formatContent(
|
|
20203
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20040
20204
|
};
|
|
20041
20205
|
}
|
|
20042
20206
|
case "user_context": {
|
|
@@ -20149,8 +20313,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20149
20313
|
source_tool: input.source_tool || "mcp",
|
|
20150
20314
|
is_personal: input.is_personal
|
|
20151
20315
|
});
|
|
20316
|
+
const planHint = getPlanStatusHint(input.status || "draft");
|
|
20317
|
+
const resultWithHint = { ...result, hint: planHint };
|
|
20152
20318
|
return {
|
|
20153
|
-
content: [{ type: "text", text: formatContent(
|
|
20319
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20154
20320
|
};
|
|
20155
20321
|
}
|
|
20156
20322
|
case "get_plan": {
|
|
@@ -20180,8 +20346,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20180
20346
|
tags: input.tags,
|
|
20181
20347
|
due_at: input.due_at
|
|
20182
20348
|
});
|
|
20349
|
+
const planUpdateHint = input.status ? getPlanStatusHint(input.status) : "Plan updated. Changes are preserved.";
|
|
20350
|
+
const resultWithHint = { ...result, hint: planUpdateHint };
|
|
20183
20351
|
return {
|
|
20184
|
-
content: [{ type: "text", text: formatContent(
|
|
20352
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20185
20353
|
};
|
|
20186
20354
|
}
|
|
20187
20355
|
case "list_plans": {
|
|
@@ -20195,8 +20363,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20195
20363
|
limit: input.limit,
|
|
20196
20364
|
is_personal: input.is_personal
|
|
20197
20365
|
});
|
|
20366
|
+
const plans = result?.data?.plans || result?.plans || result?.data?.items || result?.items || [];
|
|
20367
|
+
const resultWithHint = plans.length === 0 ? { ...result, hint: getEmptyStateHint("list_plans") } : result;
|
|
20198
20368
|
return {
|
|
20199
|
-
content: [{ type: "text", text: formatContent(
|
|
20369
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20200
20370
|
};
|
|
20201
20371
|
}
|
|
20202
20372
|
case "restore_context": {
|
|
@@ -20690,8 +20860,10 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
20690
20860
|
project_id: projectId,
|
|
20691
20861
|
limit: input.limit
|
|
20692
20862
|
});
|
|
20863
|
+
const events = result?.data?.items || result?.items || result?.data || [];
|
|
20864
|
+
const resultWithHint = Array.isArray(events) && events.length === 0 ? { ...result, hint: getEmptyStateHint("list_events") } : result;
|
|
20693
20865
|
return {
|
|
20694
|
-
content: [{ type: "text", text: formatContent(
|
|
20866
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20695
20867
|
};
|
|
20696
20868
|
}
|
|
20697
20869
|
case "import_batch": {
|
|
@@ -20884,8 +21056,10 @@ ${formatContent(result)}`
|
|
|
20884
21056
|
tags: input.tags,
|
|
20885
21057
|
is_personal: input.is_personal
|
|
20886
21058
|
});
|
|
21059
|
+
const taskCreateHint = TASK_HINTS.created;
|
|
21060
|
+
const resultWithHint = { ...result, hint: taskCreateHint };
|
|
20887
21061
|
return {
|
|
20888
|
-
content: [{ type: "text", text: formatContent(
|
|
21062
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20889
21063
|
};
|
|
20890
21064
|
}
|
|
20891
21065
|
case "get_task": {
|
|
@@ -20917,8 +21091,17 @@ ${formatContent(result)}`
|
|
|
20917
21091
|
tags: input.tags,
|
|
20918
21092
|
blocked_reason: input.blocked_reason
|
|
20919
21093
|
});
|
|
21094
|
+
let taskUpdateHint = "Task updated.";
|
|
21095
|
+
if (input.task_status === "completed") {
|
|
21096
|
+
taskUpdateHint = TASK_HINTS.completed;
|
|
21097
|
+
} else if (input.task_status === "blocked") {
|
|
21098
|
+
taskUpdateHint = TASK_HINTS.blocked;
|
|
21099
|
+
} else if (input.task_status === "cancelled") {
|
|
21100
|
+
taskUpdateHint = TASK_HINTS.cancelled;
|
|
21101
|
+
}
|
|
21102
|
+
const resultWithHint = { ...result, hint: taskUpdateHint };
|
|
20920
21103
|
return {
|
|
20921
|
-
content: [{ type: "text", text: formatContent(
|
|
21104
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20922
21105
|
};
|
|
20923
21106
|
}
|
|
20924
21107
|
case "delete_task": {
|
|
@@ -20945,8 +21128,10 @@ ${formatContent(result)}`
|
|
|
20945
21128
|
limit: input.limit,
|
|
20946
21129
|
is_personal: input.is_personal
|
|
20947
21130
|
});
|
|
21131
|
+
const tasks = result?.data?.tasks || result?.tasks || result?.data?.items || result?.items || [];
|
|
21132
|
+
const resultWithHint = Array.isArray(tasks) && tasks.length === 0 ? { ...result, hint: getEmptyStateHint("list_tasks") } : result;
|
|
20948
21133
|
return {
|
|
20949
|
-
content: [{ type: "text", text: formatContent(
|
|
21134
|
+
content: [{ type: "text", text: formatContent(resultWithHint) }]
|
|
20950
21135
|
};
|
|
20951
21136
|
}
|
|
20952
21137
|
case "reorder_tasks": {
|
|
@@ -20998,8 +21183,10 @@ ${formatContent(result)}`
|
|
|
20998
21183
|
priority: input.todo_priority,
|
|
20999
21184
|
is_personal: input.is_personal
|
|
21000
21185
|
});
|
|
21186
|
+
const todos = todosResult?.data?.todos || todosResult?.todos || todosResult?.data?.items || todosResult?.items || [];
|
|
21187
|
+
const todosWithHint = Array.isArray(todos) && todos.length === 0 ? { ...todosResult, hint: getEmptyStateHint("list_todos") } : todosResult;
|
|
21001
21188
|
return {
|
|
21002
|
-
content: [{ type: "text", text: formatContent(
|
|
21189
|
+
content: [{ type: "text", text: formatContent(todosWithHint) }]
|
|
21003
21190
|
};
|
|
21004
21191
|
}
|
|
21005
21192
|
case "get_todo": {
|
|
@@ -21075,8 +21262,10 @@ ${formatContent(result)}`
|
|
|
21075
21262
|
diagram_type: input.diagram_type,
|
|
21076
21263
|
is_personal: input.is_personal
|
|
21077
21264
|
});
|
|
21265
|
+
const diagrams = diagramsResult?.data?.diagrams || diagramsResult?.diagrams || diagramsResult?.data?.items || diagramsResult?.items || [];
|
|
21266
|
+
const diagramsWithHint = Array.isArray(diagrams) && diagrams.length === 0 ? { ...diagramsResult, hint: getEmptyStateHint("list_diagrams") } : diagramsResult;
|
|
21078
21267
|
return {
|
|
21079
|
-
content: [{ type: "text", text: formatContent(
|
|
21268
|
+
content: [{ type: "text", text: formatContent(diagramsWithHint) }]
|
|
21080
21269
|
};
|
|
21081
21270
|
}
|
|
21082
21271
|
case "get_diagram": {
|
|
@@ -21149,8 +21338,10 @@ ${formatContent(result)}`
|
|
|
21149
21338
|
doc_type: input.doc_type,
|
|
21150
21339
|
is_personal: input.is_personal
|
|
21151
21340
|
});
|
|
21341
|
+
const docs = docsResult?.data?.docs || docsResult?.docs || docsResult?.data?.items || docsResult?.items || [];
|
|
21342
|
+
const docsWithHint = Array.isArray(docs) && docs.length === 0 ? { ...docsResult, hint: getEmptyStateHint("list_docs") } : docsResult;
|
|
21152
21343
|
return {
|
|
21153
|
-
content: [{ type: "text", text: formatContent(
|
|
21344
|
+
content: [{ type: "text", text: formatContent(docsWithHint) }]
|
|
21154
21345
|
};
|
|
21155
21346
|
}
|
|
21156
21347
|
case "get_doc": {
|
|
@@ -23048,14 +23239,14 @@ Content ID: ${input.content_id}`
|
|
|
23048
23239
|
// For editor_rules
|
|
23049
23240
|
folder_path: external_exports.string().optional(),
|
|
23050
23241
|
editors: external_exports.array(external_exports.string()).optional(),
|
|
23051
|
-
mode: external_exports.enum(["minimal", "full"]).optional(),
|
|
23242
|
+
mode: external_exports.enum(["minimal", "full", "bootstrap"]).optional(),
|
|
23052
23243
|
dry_run: external_exports.boolean().optional(),
|
|
23053
23244
|
workspace_id: external_exports.string().uuid().optional(),
|
|
23054
23245
|
workspace_name: external_exports.string().optional(),
|
|
23055
23246
|
project_name: external_exports.string().optional(),
|
|
23056
23247
|
additional_rules: external_exports.string().optional(),
|
|
23057
23248
|
install_hooks: external_exports.boolean().optional().describe("Install Claude Code hooks (PreToolUse, UserPromptSubmit, PostToolUse). Default: true for Claude users."),
|
|
23058
|
-
include_pre_compact: external_exports.boolean().optional().describe("Include PreCompact hook for auto-saving state before compaction. Default:
|
|
23249
|
+
include_pre_compact: external_exports.boolean().optional().describe("Include PreCompact hook for auto-saving state before compaction. Default: true."),
|
|
23059
23250
|
include_post_write: external_exports.boolean().optional().describe("Include PostToolUse hook for real-time file indexing after Edit/Write operations. Default: true."),
|
|
23060
23251
|
// For enable_bundle
|
|
23061
23252
|
bundle: external_exports.enum([
|
|
@@ -23112,7 +23303,7 @@ Each domain tool has an 'action' parameter for specific operations.` : "";
|
|
|
23112
23303
|
scope: input.folder_path ? "both" : "user",
|
|
23113
23304
|
projectPath: input.folder_path,
|
|
23114
23305
|
dryRun: input.dry_run,
|
|
23115
|
-
includePreCompact: input.include_pre_compact,
|
|
23306
|
+
includePreCompact: input.include_pre_compact !== false,
|
|
23116
23307
|
includePostWrite: input.include_post_write
|
|
23117
23308
|
});
|
|
23118
23309
|
} catch (err) {
|
|
@@ -25845,7 +26036,7 @@ Code: ${device.user_code}`);
|
|
|
25845
26036
|
}
|
|
25846
26037
|
}
|
|
25847
26038
|
}
|
|
25848
|
-
const mode = "
|
|
26039
|
+
const mode = "full";
|
|
25849
26040
|
const detectedPlanName = await client.getPlanName();
|
|
25850
26041
|
const detectedGraphTier = await client.getGraphTier();
|
|
25851
26042
|
const graphTierLabel = detectedGraphTier === "full" ? "full graph" : detectedGraphTier === "lite" ? "graph-lite" : "none";
|
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.49",
|
|
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",
|