agentic-loop 3.12.3 → 3.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.claude/skills/loopgram/SKILL.md +19 -0
  2. package/README.md +1 -0
  3. package/bin/ralph.sh +17 -11
  4. package/dist/loopgram/claude.d.ts +18 -0
  5. package/dist/loopgram/claude.d.ts.map +1 -0
  6. package/dist/loopgram/claude.js +89 -0
  7. package/dist/loopgram/claude.js.map +1 -0
  8. package/dist/loopgram/context-search.d.ts +26 -0
  9. package/dist/loopgram/context-search.d.ts.map +1 -0
  10. package/dist/loopgram/context-search.js +175 -0
  11. package/dist/loopgram/context-search.js.map +1 -0
  12. package/dist/loopgram/conversation.d.ts +39 -0
  13. package/dist/loopgram/conversation.d.ts.map +1 -0
  14. package/dist/loopgram/conversation.js +158 -0
  15. package/dist/loopgram/conversation.js.map +1 -0
  16. package/dist/loopgram/index.d.ts +3 -0
  17. package/dist/loopgram/index.d.ts.map +1 -0
  18. package/dist/loopgram/index.js +246 -0
  19. package/dist/loopgram/index.js.map +1 -0
  20. package/dist/loopgram/loop-monitor.d.ts +16 -0
  21. package/dist/loopgram/loop-monitor.d.ts.map +1 -0
  22. package/dist/loopgram/loop-monitor.js +149 -0
  23. package/dist/loopgram/loop-monitor.js.map +1 -0
  24. package/dist/loopgram/loop-runner.d.ts +28 -0
  25. package/dist/loopgram/loop-runner.d.ts.map +1 -0
  26. package/dist/loopgram/loop-runner.js +157 -0
  27. package/dist/loopgram/loop-runner.js.map +1 -0
  28. package/dist/loopgram/prd-generator.d.ts +37 -0
  29. package/dist/loopgram/prd-generator.d.ts.map +1 -0
  30. package/dist/loopgram/prd-generator.js +134 -0
  31. package/dist/loopgram/prd-generator.js.map +1 -0
  32. package/dist/loopgram/saver.d.ts +9 -0
  33. package/dist/loopgram/saver.d.ts.map +1 -0
  34. package/dist/loopgram/saver.js +35 -0
  35. package/dist/loopgram/saver.js.map +1 -0
  36. package/dist/loopgram/types.d.ts +37 -0
  37. package/dist/loopgram/types.d.ts.map +1 -0
  38. package/dist/loopgram/types.js +5 -0
  39. package/dist/loopgram/types.js.map +1 -0
  40. package/package.json +6 -2
  41. package/ralph/hooks/common.sh +89 -0
  42. package/ralph/hooks/warn-debug.sh +14 -32
  43. package/ralph/hooks/warn-empty-catch.sh +13 -29
  44. package/ralph/hooks/warn-secrets.sh +19 -37
  45. package/ralph/hooks/warn-urls.sh +17 -33
  46. package/ralph/init.sh +30 -0
  47. package/ralph/loop.sh +5 -2
  48. package/ralph/setup/ui.sh +0 -42
  49. package/ralph/setup.sh +69 -45
  50. package/ralph/utils.sh +167 -31
  51. package/templates/config/fastmcp.json +5 -5
  52. package/templates/hooks/warn-uv-python.sh +38 -0
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: Review and manage brainstorm ideas from Telegram
3
+ ---
4
+
5
+ # Loopgram Review
6
+
7
+ Review ideas captured from Telegram via Loopgram.
8
+
9
+ ## Commands
10
+
11
+ - `/loopgram list` - Show all saved ideas
12
+ - `/loopgram review <name>` - Review and refine a specific idea
13
+ - `/loopgram prd <name>` - Convert idea to PRD for Ralph execution
14
+
15
+ ## Workflow
16
+
17
+ 1. List recent ideas: `ls docs/ideas/`
18
+ 2. Read an idea: Read the file
19
+ 3. If ready, run `/prd docs/ideas/{name}.md` to convert to executable PRD
package/README.md CHANGED
@@ -86,6 +86,7 @@ npx agentic-loop run # Execute PRDs autonomously
86
86
  - [How Ralph Works](docs/RALPH.md) - Architecture, config, full reference
87
87
  - [Cheatsheet](docs/CHEATSHEET.md) - All commands at a glance
88
88
  - [Hooks Reference](docs/HOOKS.md) - Pre-commit and Claude Code hooks
89
+ - [Loopgram](docs/LOOPGRAM.md) - Telegram bot for mobile idea capture and loop monitoring
89
90
  - [Troubleshooting](docs/TROUBLESHOOTING.md) - Common issues and fixes
90
91
  - [Contributing](docs/CONTRIBUTING.md) - How to contribute
91
92
 
package/bin/ralph.sh CHANGED
@@ -61,13 +61,22 @@ if [[ ! -f ".ralph/config.json" ]]; then
61
61
  _project_type="node"
62
62
  fi
63
63
 
64
+ # Check user template override first
65
+ _user_template="$HOME/.config/ralph/templates/config/${_project_type}.json"
64
66
  _config_template="$RALPH_TEMPLATES/config/${_project_type}.json"
65
- if [[ -f "$_config_template" ]]; then
67
+
68
+ if [[ -f "$_user_template" ]]; then
69
+ cp "$_user_template" ".ralph/config.json"
70
+ echo "Using user template: $_user_template" >&2
71
+ elif [[ -f "$_config_template" ]]; then
66
72
  cp "$_config_template" ".ralph/config.json"
67
73
  else
68
74
  # Fall back to minimal config if template doesn't exist
75
+ _user_minimal="$HOME/.config/ralph/templates/config/minimal.json"
69
76
  _config_template="$RALPH_TEMPLATES/config/minimal.json"
70
- if [[ -f "$_config_template" ]]; then
77
+ if [[ -f "$_user_minimal" ]]; then
78
+ cp "$_user_minimal" ".ralph/config.json"
79
+ elif [[ -f "$_config_template" ]]; then
71
80
  cp "$_config_template" ".ralph/config.json"
72
81
  else
73
82
  echo '{"projectType": "unknown"}' > ".ralph/config.json"
@@ -101,6 +110,11 @@ if [[ "${_ralph_needs_autoconfig:-}" == "true" ]]; then
101
110
  unset _ralph_needs_autoconfig
102
111
  fi
103
112
 
113
+ # Merge user config defaults into project config
114
+ if [[ -f "$RALPH_DIR/config.json" && -f "$HOME/.config/ralph/config.json" ]]; then
115
+ _merge_user_config
116
+ fi
117
+
104
118
  # Main entry point
105
119
  main() {
106
120
  local cmd="${1:-help}"
@@ -185,15 +199,7 @@ main() {
185
199
  fi
186
200
  ;;
187
201
  config)
188
- if [[ ! -f "$RALPH_DIR/config.json" ]]; then
189
- print_error "Ralph not initialized. Run 'ralph init' first."
190
- exit 1
191
- fi
192
- echo "Auto-detecting project configuration..."
193
- auto_configure_project
194
- echo ""
195
- echo "Current config:"
196
- jq '.' "$RALPH_DIR/config.json"
202
+ ralph_config "$@"
197
203
  ;;
198
204
  help|-h|--help)
199
205
  ralph_help
@@ -0,0 +1,18 @@
1
+ import type { Message } from './types.js';
2
+ /**
3
+ * Build system prompt with optional project context
4
+ */
5
+ export declare function buildSystemPrompt(projectContext?: string): string;
6
+ /**
7
+ * Send a message to Claude and get a response
8
+ */
9
+ export declare function chat(history: Message[], model: string, projectContext?: string): Promise<string>;
10
+ /**
11
+ * Generate a summary of the conversation for saving
12
+ */
13
+ export declare function summarize(history: Message[], model: string): Promise<string>;
14
+ /**
15
+ * Extract a title from a summary document
16
+ */
17
+ export declare function extractTitle(summary: string): string;
18
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/loopgram/claude.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAuB1C;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAWjE;AAWD;;GAEG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,OAAO,EAAE,EAClB,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,OAAO,EAAE,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAepD"}
@@ -0,0 +1,89 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ const anthropic = new Anthropic();
3
+ const BASE_SYSTEM_PROMPT = `You are a thoughtful brainstorming partner helping develop software ideas.
4
+
5
+ Your role:
6
+ - Ask clarifying questions to deeply understand the idea
7
+ - Explore edge cases and trade-offs
8
+ - Challenge assumptions constructively
9
+ - Help refine vague concepts into concrete plans
10
+ - Keep responses concise but insightful (2-4 sentences usually)
11
+
12
+ When the user says "save this" or similar:
13
+ - Summarize the key decisions made
14
+ - Format as a structured idea document
15
+ - Confirm what you're saving
16
+
17
+ Don't:
18
+ - Write code unless asked
19
+ - Be overly agreeable - push back on weak ideas
20
+ - Give long lectures - keep it conversational`;
21
+ /**
22
+ * Build system prompt with optional project context
23
+ */
24
+ export function buildSystemPrompt(projectContext) {
25
+ if (!projectContext) {
26
+ return BASE_SYSTEM_PROMPT;
27
+ }
28
+ return `${BASE_SYSTEM_PROMPT}
29
+
30
+ ## Project Context
31
+ You are brainstorming for a specific project. Here's context about it:
32
+
33
+ ${projectContext}`;
34
+ }
35
+ const SUMMARY_PROMPT = `Summarize this brainstorming conversation into a structured idea document with:
36
+ - Title (short, descriptive)
37
+ - Summary (2-3 sentences)
38
+ - Key Decisions (bullet points)
39
+ - Open Questions (if any)
40
+ - Next Steps
41
+
42
+ Format as clean markdown.`;
43
+ /**
44
+ * Send a message to Claude and get a response
45
+ */
46
+ export async function chat(history, model, projectContext) {
47
+ const response = await anthropic.messages.create({
48
+ model,
49
+ max_tokens: 500,
50
+ system: buildSystemPrompt(projectContext),
51
+ messages: history,
52
+ });
53
+ const content = response.content[0];
54
+ return content.type === 'text' ? content.text : '';
55
+ }
56
+ /**
57
+ * Generate a summary of the conversation for saving
58
+ */
59
+ export async function summarize(history, model) {
60
+ const conversationText = history
61
+ .map((m) => `${m.role.toUpperCase()}: ${m.content}`)
62
+ .join('\n\n');
63
+ const response = await anthropic.messages.create({
64
+ model,
65
+ max_tokens: 1000,
66
+ system: SUMMARY_PROMPT,
67
+ messages: [{ role: 'user', content: conversationText }],
68
+ });
69
+ const content = response.content[0];
70
+ return content.type === 'text' ? content.text : '';
71
+ }
72
+ /**
73
+ * Extract a title from a summary document
74
+ */
75
+ export function extractTitle(summary) {
76
+ // Try to find a markdown heading
77
+ const headingMatch = summary.match(/^#\s*(.+)/m);
78
+ if (headingMatch) {
79
+ return headingMatch[1].replace(/^Title:?\s*/i, '').trim();
80
+ }
81
+ // Try to find "Title:" line
82
+ const titleMatch = summary.match(/^Title:?\s*(.+)/im);
83
+ if (titleMatch) {
84
+ return titleMatch[1].trim();
85
+ }
86
+ // Fallback to timestamp
87
+ return `brainstorm-${Date.now()}`;
88
+ }
89
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/loopgram/claude.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAG1C,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;AAElC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;8CAiBmB,CAAC;AAE/C;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,cAAuB;IACvD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,OAAO,GAAG,kBAAkB;;;;;EAK5B,cAAc,EAAE,CAAA;AAClB,CAAC;AAED,MAAM,cAAc,GAAG;;;;;;;0BAOG,CAAC;AAE3B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAkB,EAClB,KAAa,EACb,cAAuB;IAEvB,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC/C,KAAK;QACL,UAAU,EAAE,GAAG;QACf,MAAM,EAAE,iBAAiB,CAAC,cAAc,CAAC;QACzC,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAkB,EAClB,KAAa;IAEb,MAAM,gBAAgB,GAAG,OAAO;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;SACnD,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC/C,KAAK;QACL,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;KACxD,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,iCAAiC;IACjC,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,CAAC;IAED,4BAA4B;IAC5B,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACtD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,wBAAwB;IACxB,OAAO,cAAc,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,26 @@
1
+ interface SearchResult {
2
+ file: string;
3
+ matches: string[];
4
+ }
5
+ /**
6
+ * Search a project for files related to a topic using ripgrep
7
+ */
8
+ export declare function searchProject(projectPath: string, topic: string): SearchResult[];
9
+ /**
10
+ * Read key project files for additional context
11
+ */
12
+ export declare function readProjectFiles(projectPath: string): string;
13
+ /**
14
+ * Generate a summary of search results using Claude
15
+ */
16
+ export declare function generateContextSummary(projectName: string, topic: string, searchResults: SearchResult[], projectContext: string, model: string): Promise<string>;
17
+ /**
18
+ * Search project and generate context for brainstorming
19
+ */
20
+ export declare function getTopicContext(projectPath: string, projectName: string, topic: string, model: string): Promise<{
21
+ summary: string;
22
+ filesFound: string[];
23
+ searchTerms: string[];
24
+ }>;
25
+ export {};
26
+ //# sourceMappingURL=context-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-search.d.ts","sourceRoot":"","sources":["../../src/loopgram/context-search.ts"],"names":[],"mappings":"AAOA,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AA+BD;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CA+ChF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CA2B5D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,YAAY,EAAE,EAC7B,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAyC3E"}
@@ -0,0 +1,175 @@
1
+ import { execSync } from 'child_process';
2
+ import { readFileSync, existsSync } from 'fs';
3
+ import { join, relative } from 'path';
4
+ import Anthropic from '@anthropic-ai/sdk';
5
+ const anthropic = new Anthropic();
6
+ /**
7
+ * Use AI to generate smart search terms for a topic
8
+ */
9
+ async function generateSearchTerms(topic, model) {
10
+ const response = await anthropic.messages.create({
11
+ model,
12
+ max_tokens: 200,
13
+ system: `You generate search terms for code search. Given a topic, output 5-8 relevant keywords/patterns to search for in a codebase. Output ONLY the terms, one per line, no explanations. Include variations (e.g., "auth", "authenticate", "authentication").`,
14
+ messages: [
15
+ { role: 'user', content: `Topic: ${topic}` },
16
+ ],
17
+ });
18
+ const text = response.content[0];
19
+ if (text.type !== 'text')
20
+ return [topic];
21
+ const terms = text.text
22
+ .split('\n')
23
+ .map(t => t.trim().toLowerCase())
24
+ .filter(t => t.length > 0 && t.length < 30);
25
+ // Always include the original topic
26
+ if (!terms.includes(topic.toLowerCase())) {
27
+ terms.unshift(topic.toLowerCase());
28
+ }
29
+ return terms.slice(0, 8);
30
+ }
31
+ /**
32
+ * Search a project for files related to a topic using ripgrep
33
+ */
34
+ export function searchProject(projectPath, topic) {
35
+ const results = [];
36
+ try {
37
+ // Use ripgrep to find matching files (case insensitive)
38
+ // Escape special regex characters in topic
39
+ const escapedTopic = topic.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
40
+ // Use grep instead of rg for compatibility
41
+ const cmd = `grep -r -i -l "${escapedTopic}" "${projectPath}" --include="*.py" --include="*.ts" --include="*.js" --include="*.md" --include="*.json" --include="*.sh" 2>/dev/null | grep -v node_modules | grep -v __pycache__ | grep -v ".git" | head -20 || true`;
42
+ console.log(`[search] Running: ${cmd}`);
43
+ const rgOutput = execSync(cmd, {
44
+ encoding: 'utf-8',
45
+ maxBuffer: 1024 * 1024,
46
+ shell: '/bin/zsh'
47
+ }).trim();
48
+ console.log(`[search] Found ${rgOutput ? rgOutput.split('\n').length : 0} files for "${topic}"`);
49
+ if (!rgOutput) {
50
+ return results;
51
+ }
52
+ const files = rgOutput.split('\n').filter(Boolean);
53
+ for (const file of files.slice(0, 10)) { // Limit to 10 files
54
+ try {
55
+ // Get matching lines with context
56
+ const matchOutput = execSync(`rg -i -C 2 "${topic}" "${file}" 2>/dev/null | head -30`, { encoding: 'utf-8', maxBuffer: 1024 * 1024 }).trim();
57
+ results.push({
58
+ file: relative(projectPath, file),
59
+ matches: matchOutput ? [matchOutput] : [],
60
+ });
61
+ }
62
+ catch {
63
+ // File might not have readable matches
64
+ results.push({ file: relative(projectPath, file), matches: [] });
65
+ }
66
+ }
67
+ }
68
+ catch (error) {
69
+ // ripgrep not found or no matches
70
+ console.error('Search error:', error);
71
+ }
72
+ return results;
73
+ }
74
+ /**
75
+ * Read key project files for additional context
76
+ */
77
+ export function readProjectFiles(projectPath) {
78
+ const contextFiles = [
79
+ 'CLAUDE.md',
80
+ 'README.md',
81
+ 'package.json',
82
+ 'pyproject.toml',
83
+ ];
84
+ let context = '';
85
+ for (const file of contextFiles) {
86
+ const filePath = join(projectPath, file);
87
+ if (existsSync(filePath)) {
88
+ try {
89
+ const content = readFileSync(filePath, 'utf-8');
90
+ // Truncate large files
91
+ const truncated = content.length > 2000
92
+ ? content.substring(0, 2000) + '\n...[truncated]'
93
+ : content;
94
+ context += `\n### ${file}\n${truncated}\n`;
95
+ }
96
+ catch {
97
+ // Skip unreadable files
98
+ }
99
+ }
100
+ }
101
+ return context;
102
+ }
103
+ /**
104
+ * Generate a summary of search results using Claude
105
+ */
106
+ export async function generateContextSummary(projectName, topic, searchResults, projectContext, model) {
107
+ if (searchResults.length === 0) {
108
+ return `No code found related to "${topic}" in ${projectName}. This might be a new area to build.`;
109
+ }
110
+ // Build the content to summarize
111
+ let content = `Project: ${projectName}\nTopic: ${topic}\n\n`;
112
+ content += `## Project Context\n${projectContext}\n\n`;
113
+ content += `## Search Results\n`;
114
+ for (const result of searchResults) {
115
+ content += `\n### ${result.file}\n`;
116
+ if (result.matches.length > 0) {
117
+ content += '```\n' + result.matches.join('\n---\n') + '\n```\n';
118
+ }
119
+ }
120
+ const response = await anthropic.messages.create({
121
+ model,
122
+ max_tokens: 800,
123
+ system: `You are summarizing code search results to provide context for brainstorming.
124
+ Be concise but thorough. Focus on:
125
+ - What exists related to this topic
126
+ - Key patterns and approaches used
127
+ - Important files/functions
128
+ - Potential extension points
129
+
130
+ Keep the summary under 500 words.`,
131
+ messages: [
132
+ {
133
+ role: 'user',
134
+ content: `Summarize what exists in this codebase related to "${topic}":\n\n${content}`,
135
+ },
136
+ ],
137
+ });
138
+ const text = response.content[0];
139
+ return text.type === 'text' ? text.text : 'Unable to generate summary.';
140
+ }
141
+ /**
142
+ * Search project and generate context for brainstorming
143
+ */
144
+ export async function getTopicContext(projectPath, projectName, topic, model) {
145
+ // Use AI to generate smart search terms
146
+ console.log(`[context] Generating search terms for: ${topic}`);
147
+ const searchTerms = await generateSearchTerms(topic, model);
148
+ console.log(`[context] Search terms: ${searchTerms.join(', ')}`);
149
+ // Search for each term and combine results
150
+ const allResults = new Map();
151
+ for (const term of searchTerms) {
152
+ const results = searchProject(projectPath, term);
153
+ for (const result of results) {
154
+ // Dedupe by file path, merge matches
155
+ if (allResults.has(result.file)) {
156
+ const existing = allResults.get(result.file);
157
+ existing.matches.push(...result.matches);
158
+ }
159
+ else {
160
+ allResults.set(result.file, result);
161
+ }
162
+ }
163
+ }
164
+ const searchResults = Array.from(allResults.values()).slice(0, 15);
165
+ // Get basic project context
166
+ const projectContext = readProjectFiles(projectPath);
167
+ // Generate summary
168
+ const summary = await generateContextSummary(projectName, topic, searchResults, projectContext, model);
169
+ return {
170
+ summary,
171
+ filesFound: searchResults.map((r) => r.file),
172
+ searchTerms,
173
+ };
174
+ }
175
+ //# sourceMappingURL=context-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-search.js","sourceRoot":"","sources":["../../src/loopgram/context-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { Context } from 'telegraf';
2
+ import type { Message, BrainstormConfig, ProjectConfig } from './types.js';
3
+ /**
4
+ * Set context for a conversation (from /context command)
5
+ */
6
+ export declare function setConversationContext(chatId: number, context: string): void;
7
+ /**
8
+ * Get context for a conversation
9
+ */
10
+ export declare function getConversationContext(chatId: number): string | undefined;
11
+ /**
12
+ * Get conversation history for a chat, creating if needed
13
+ */
14
+ export declare function getHistory(chatId: number): Message[];
15
+ /**
16
+ * Clear conversation history for a chat
17
+ */
18
+ export declare function clearConversation(chatId: number): void;
19
+ /**
20
+ * Handle incoming text messages
21
+ */
22
+ export declare function handleMessage(ctx: Context, config: BrainstormConfig, project: ProjectConfig | null): Promise<void>;
23
+ /**
24
+ * Handle /save command - summarize and save the conversation
25
+ */
26
+ export declare function handleSaveCommand(ctx: Context, projectPath: string | null, config: BrainstormConfig): Promise<void>;
27
+ /**
28
+ * Handle /clear command - clear conversation history
29
+ */
30
+ export declare function handleClearCommand(ctx: Context): void;
31
+ /**
32
+ * Handle /projects command - list configured projects
33
+ */
34
+ export declare function handleProjectsCommand(ctx: Context, config: BrainstormConfig): void;
35
+ /**
36
+ * Handle /status command - show current conversation status
37
+ */
38
+ export declare function handleStatusCommand(ctx: Context, projectPath: string | null, config: BrainstormConfig): void;
39
+ //# sourceMappingURL=conversation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/loopgram/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAa3E;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEzE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAKpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGtD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,aAAa,GAAG,IAAI,GAC5B,OAAO,CAAC,IAAI,CAAC,CA4Cf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAMrD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,gBAAgB,GACvB,IAAI,CAUN;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,EAAE,gBAAgB,GACvB,IAAI,CAoBN"}
@@ -0,0 +1,158 @@
1
+ import { chat, summarize, extractTitle } from './claude.js';
2
+ import { saveIdea, slugify } from './saver.js';
3
+ // Store conversation history per chat (group or DM)
4
+ const conversations = new Map();
5
+ // Store loaded context per chat (from /context command)
6
+ const conversationContexts = new Map();
7
+ // Max history length (20 exchanges = 40 messages)
8
+ const MAX_HISTORY_LENGTH = 40;
9
+ /**
10
+ * Set context for a conversation (from /context command)
11
+ */
12
+ export function setConversationContext(chatId, context) {
13
+ conversationContexts.set(chatId, context);
14
+ }
15
+ /**
16
+ * Get context for a conversation
17
+ */
18
+ export function getConversationContext(chatId) {
19
+ return conversationContexts.get(chatId);
20
+ }
21
+ /**
22
+ * Get conversation history for a chat, creating if needed
23
+ */
24
+ export function getHistory(chatId) {
25
+ if (!conversations.has(chatId)) {
26
+ conversations.set(chatId, []);
27
+ }
28
+ return conversations.get(chatId);
29
+ }
30
+ /**
31
+ * Clear conversation history for a chat
32
+ */
33
+ export function clearConversation(chatId) {
34
+ conversations.delete(chatId);
35
+ conversationContexts.delete(chatId);
36
+ }
37
+ /**
38
+ * Handle incoming text messages
39
+ */
40
+ export async function handleMessage(ctx, config, project) {
41
+ const chatId = ctx.chat?.id;
42
+ const message = ctx.message;
43
+ if (!chatId || !message || !('text' in message)) {
44
+ return;
45
+ }
46
+ const userMessage = message.text;
47
+ const history = getHistory(chatId);
48
+ // Add user message to history
49
+ history.push({ role: 'user', content: userMessage });
50
+ // Build project context if available
51
+ let projectContext = project
52
+ ? `**Project:** ${project.name}\n**Description:** ${project.description || 'No description'}\n**Path:** ${project.path}`
53
+ : undefined;
54
+ // Add loaded context from /context command if available
55
+ const loadedContext = getConversationContext(chatId);
56
+ if (loadedContext && projectContext) {
57
+ projectContext += `\n\n## Codebase Context\n${loadedContext}`;
58
+ }
59
+ else if (loadedContext) {
60
+ projectContext = `## Codebase Context\n${loadedContext}`;
61
+ }
62
+ try {
63
+ // Get response from Claude with project context
64
+ const response = await chat(history, config.anthropic.model, projectContext);
65
+ // Add assistant response to history
66
+ history.push({ role: 'assistant', content: response });
67
+ // Trim history if too long
68
+ if (history.length > MAX_HISTORY_LENGTH) {
69
+ history.splice(0, 2);
70
+ }
71
+ await ctx.reply(response);
72
+ }
73
+ catch (error) {
74
+ console.error('Error calling Claude:', error);
75
+ await ctx.reply('Sorry, I had trouble processing that. Please try again.');
76
+ }
77
+ }
78
+ /**
79
+ * Handle /save command - summarize and save the conversation
80
+ */
81
+ export async function handleSaveCommand(ctx, projectPath, config) {
82
+ const chatId = ctx.chat?.id;
83
+ if (!chatId) {
84
+ return;
85
+ }
86
+ if (!projectPath) {
87
+ await ctx.reply('This group is not configured for a project. ' +
88
+ 'Add this group ID to ~/.config/ralph/brainstorm.json');
89
+ return;
90
+ }
91
+ const history = getHistory(chatId);
92
+ if (history.length < 2) {
93
+ await ctx.reply('Nothing to save yet. Start a conversation first!');
94
+ return;
95
+ }
96
+ try {
97
+ await ctx.reply('Summarizing conversation...');
98
+ // Generate summary
99
+ const summary = await summarize(history, config.anthropic.model);
100
+ // Extract title and create filename
101
+ const title = extractTitle(summary);
102
+ const filename = slugify(title);
103
+ // Save to project
104
+ const filepath = saveIdea(projectPath, filename, summary);
105
+ // Report success
106
+ const shortSummary = summary.length > 500 ? summary.slice(0, 500) + '...' : summary;
107
+ await ctx.reply(`✅ Saved to ${filepath}\n\n${shortSummary}`);
108
+ // Clear conversation after saving
109
+ clearConversation(chatId);
110
+ }
111
+ catch (error) {
112
+ console.error('Error saving idea:', error);
113
+ await ctx.reply('Sorry, I had trouble saving that. Please try again.');
114
+ }
115
+ }
116
+ /**
117
+ * Handle /clear command - clear conversation history
118
+ */
119
+ export function handleClearCommand(ctx) {
120
+ const chatId = ctx.chat?.id;
121
+ if (chatId) {
122
+ clearConversation(chatId);
123
+ ctx.reply('Conversation cleared. Start fresh!');
124
+ }
125
+ }
126
+ /**
127
+ * Handle /projects command - list configured projects
128
+ */
129
+ export function handleProjectsCommand(ctx, config) {
130
+ const projects = Object.values(config.projects);
131
+ if (projects.length === 0) {
132
+ ctx.reply('No projects configured yet. Add them to ~/.config/ralph/brainstorm.json');
133
+ return;
134
+ }
135
+ const list = projects.map((p) => `• ${p.name}: ${p.path}`).join('\n');
136
+ ctx.reply(`Configured projects:\n${list}`);
137
+ }
138
+ /**
139
+ * Handle /status command - show current conversation status
140
+ */
141
+ export function handleStatusCommand(ctx, projectPath, config) {
142
+ const chatId = ctx.chat?.id;
143
+ if (!chatId) {
144
+ return;
145
+ }
146
+ const history = getHistory(chatId);
147
+ const project = projectPath
148
+ ? Object.values(config.projects).find((p) => p.path === projectPath)
149
+ : null;
150
+ const lines = [
151
+ `📊 **Status**`,
152
+ `Messages: ${history.length}`,
153
+ `Project: ${project?.name || 'Not configured'}`,
154
+ `Model: ${config.anthropic.model}`,
155
+ ];
156
+ ctx.reply(lines.join('\n'));
157
+ }
158
+ //# sourceMappingURL=conversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../src/loopgram/conversation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loopgram/index.ts"],"names":[],"mappings":""}