rampup 0.1.0

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/knowledge.js ADDED
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Knowledge Base Client for CLI
3
+ * Save and search team Q&A entries
4
+ */
5
+
6
+ import { getIdToken } from './auth.js';
7
+
8
+ const ENTITLEMENT_API_URL = process.env.ENTITLEMENT_API_URL ||
9
+ 'https://entitlement-service.rian-19c.workers.dev';
10
+
11
+ /**
12
+ * Get user's organization (required for knowledge operations)
13
+ */
14
+ export async function getMyOrg() {
15
+ const token = await getIdToken();
16
+
17
+ if (!token) {
18
+ return null;
19
+ }
20
+
21
+ try {
22
+ const response = await fetch(`${ENTITLEMENT_API_URL}/orgs/my`, {
23
+ headers: {
24
+ 'Authorization': `Bearer ${token}`,
25
+ 'Content-Type': 'application/json',
26
+ },
27
+ });
28
+
29
+ if (!response.ok) {
30
+ return null;
31
+ }
32
+
33
+ const data = await response.json();
34
+ return data.org;
35
+ } catch (error) {
36
+ console.warn('[Knowledge] Failed to get org:', error.message);
37
+ return null;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Save a Q&A to the team knowledge base
43
+ * @param {Object} data - Knowledge entry data
44
+ * @param {string} data.question - The question
45
+ * @param {string} data.answer - The answer
46
+ * @param {string} [data.repoUrl] - Associated repo URL
47
+ * @param {string} [data.repoName] - Repository name
48
+ * @param {string[]} [data.tags] - Tags for categorization
49
+ * @param {string} [data.category] - Category: general, architecture, onboarding, debugging
50
+ */
51
+ export async function saveKnowledge(data) {
52
+ const token = await getIdToken();
53
+
54
+ if (!token) {
55
+ throw new Error('Not logged in. Run `ramp login` first.');
56
+ }
57
+
58
+ // Get user's org
59
+ const org = await getMyOrg();
60
+ if (!org) {
61
+ throw new Error('You are not part of a team. Join or create a team at rampup.dev');
62
+ }
63
+
64
+ try {
65
+ const response = await fetch(`${ENTITLEMENT_API_URL}/orgs/${org.id}/knowledge`, {
66
+ method: 'POST',
67
+ headers: {
68
+ 'Authorization': `Bearer ${token}`,
69
+ 'Content-Type': 'application/json',
70
+ },
71
+ body: JSON.stringify({
72
+ ...data,
73
+ source: 'cli',
74
+ }),
75
+ });
76
+
77
+ if (!response.ok) {
78
+ const error = await response.json().catch(() => ({ message: 'Failed to save' }));
79
+ throw new Error(error.error?.message || error.message || `HTTP ${response.status}`);
80
+ }
81
+
82
+ return await response.json();
83
+ } catch (error) {
84
+ if (error.message.includes('Not logged in') || error.message.includes('not part of a team')) {
85
+ throw error;
86
+ }
87
+ throw new Error(`Failed to save knowledge: ${error.message}`);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Search the team knowledge base
93
+ * @param {Object} options - Search options
94
+ * @param {string} [options.query] - Search query
95
+ * @param {string} [options.repoUrl] - Filter by repo
96
+ * @param {string} [options.category] - Filter by category
97
+ * @param {number} [options.limit] - Max results (default 10)
98
+ */
99
+ export async function searchKnowledge(options = {}) {
100
+ const token = await getIdToken();
101
+
102
+ if (!token) {
103
+ throw new Error('Not logged in. Run `ramp login` first.');
104
+ }
105
+
106
+ // Get user's org
107
+ const org = await getMyOrg();
108
+ if (!org) {
109
+ throw new Error('You are not part of a team. Join or create a team at rampup.dev');
110
+ }
111
+
112
+ try {
113
+ const params = new URLSearchParams();
114
+ if (options.query) params.set('q', options.query);
115
+ if (options.repoUrl) params.set('repo', options.repoUrl);
116
+ if (options.category) params.set('category', options.category);
117
+ params.set('limit', String(options.limit || 10));
118
+
119
+ const response = await fetch(
120
+ `${ENTITLEMENT_API_URL}/orgs/${org.id}/knowledge?${params.toString()}`,
121
+ {
122
+ headers: {
123
+ 'Authorization': `Bearer ${token}`,
124
+ 'Content-Type': 'application/json',
125
+ },
126
+ }
127
+ );
128
+
129
+ if (!response.ok) {
130
+ const error = await response.json().catch(() => ({ message: 'Search failed' }));
131
+ throw new Error(error.error?.message || error.message || `HTTP ${response.status}`);
132
+ }
133
+
134
+ return await response.json();
135
+ } catch (error) {
136
+ if (error.message.includes('Not logged in') || error.message.includes('not part of a team')) {
137
+ throw error;
138
+ }
139
+ throw new Error(`Failed to search knowledge: ${error.message}`);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Get a single knowledge entry by ID
145
+ * @param {string} knowledgeId - The entry ID
146
+ */
147
+ export async function getKnowledgeEntry(knowledgeId) {
148
+ const token = await getIdToken();
149
+
150
+ if (!token) {
151
+ throw new Error('Not logged in. Run `ramp login` first.');
152
+ }
153
+
154
+ const org = await getMyOrg();
155
+ if (!org) {
156
+ throw new Error('You are not part of a team. Join or create a team at rampup.dev');
157
+ }
158
+
159
+ try {
160
+ const response = await fetch(
161
+ `${ENTITLEMENT_API_URL}/orgs/${org.id}/knowledge/${knowledgeId}`,
162
+ {
163
+ headers: {
164
+ 'Authorization': `Bearer ${token}`,
165
+ 'Content-Type': 'application/json',
166
+ },
167
+ }
168
+ );
169
+
170
+ if (!response.ok) {
171
+ if (response.status === 404) {
172
+ throw new Error('Knowledge entry not found');
173
+ }
174
+ const error = await response.json().catch(() => ({ message: 'Failed to get entry' }));
175
+ throw new Error(error.error?.message || error.message || `HTTP ${response.status}`);
176
+ }
177
+
178
+ return await response.json();
179
+ } catch (error) {
180
+ if (error.message.includes('Not logged in') || error.message.includes('not part of a team')) {
181
+ throw error;
182
+ }
183
+ throw new Error(`Failed to get knowledge entry: ${error.message}`);
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Format a knowledge entry for display in the CLI
189
+ * @param {Object} entry - Knowledge entry
190
+ */
191
+ export function formatKnowledgeEntry(entry) {
192
+ const lines = [];
193
+
194
+ // Header with category and tags
195
+ const categoryEmoji = {
196
+ general: 'πŸ“‹',
197
+ architecture: 'πŸ—οΈ',
198
+ onboarding: 'πŸ‘‹',
199
+ debugging: 'πŸ›',
200
+ }[entry.category] || 'πŸ“‹';
201
+
202
+ lines.push(`${categoryEmoji} ${entry.category.toUpperCase()}`);
203
+
204
+ if (entry.tags && entry.tags.length > 0) {
205
+ lines.push(`Tags: ${entry.tags.map(t => `#${t}`).join(' ')}`);
206
+ }
207
+
208
+ if (entry.repoName) {
209
+ lines.push(`Repo: ${entry.repoName}`);
210
+ }
211
+
212
+ lines.push('');
213
+ lines.push(`Q: ${entry.question}`);
214
+ lines.push('');
215
+ lines.push(`A: ${entry.answer}`);
216
+ lines.push('');
217
+ lines.push(`β€” ${entry.creatorEmail || 'Unknown'} β€’ ${new Date(entry.createdAt).toLocaleDateString()} β€’ ${entry.voteCount} votes`);
218
+
219
+ return lines.join('\n');
220
+ }
221
+
222
+ export default {
223
+ getMyOrg,
224
+ saveKnowledge,
225
+ searchKnowledge,
226
+ getKnowledgeEntry,
227
+ formatKnowledgeEntry,
228
+ };
package/omni/config.js ADDED
@@ -0,0 +1,51 @@
1
+ // config.js - Omni AI Context Bridge configuration
2
+ import os from 'os';
3
+ import path from 'path';
4
+
5
+ // Detect operating system
6
+ const platform = process.platform;
7
+
8
+ // Default paths based on OS
9
+ const defaultPaths = {
10
+ win32: {
11
+ chatGpt: 'C:\\Program Files\\ChatGPT\\ChatGPT.exe',
12
+ claude: 'C:\\Program Files\\Claude\\Claude.exe'
13
+ },
14
+ darwin: {
15
+ chatGpt: '/Applications/ChatGPT.app',
16
+ claude: '/Applications/Claude.app'
17
+ },
18
+ linux: {
19
+ chatGpt: '/usr/bin/chatgpt',
20
+ claude: '/usr/bin/claude'
21
+ }
22
+ };
23
+
24
+ export default {
25
+ // Path to store context data
26
+ contextStorePath: path.join(os.homedir(), '.ramp', 'omni-contexts.json'),
27
+
28
+ // Paths to desktop applications
29
+ paths: {
30
+ chatGpt: process.env.CHATGPT_PATH || defaultPaths[platform]?.chatGpt,
31
+ claude: process.env.CLAUDE_PATH || defaultPaths[platform]?.claude
32
+ },
33
+
34
+ // Web app URLs
35
+ urls: {
36
+ chatGpt: 'https://chat.openai.com',
37
+ claude: 'https://claude.ai'
38
+ },
39
+
40
+ // CSS selectors for web interfaces
41
+ selectors: {
42
+ chatGpt: {
43
+ lastMessage: '.markdown',
44
+ inputBox: 'textarea[data-id="root"]'
45
+ },
46
+ claude: {
47
+ lastMessage: '.claude-response-text',
48
+ inputBox: 'textarea[placeholder="Message Claude…"]'
49
+ }
50
+ }
51
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "rampup",
3
+ "version": "0.1.0",
4
+ "description": "Ramp - Understand any codebase in hours. AI-powered developer onboarding CLI.",
5
+ "type": "module",
6
+ "bin": {
7
+ "ramp": "./index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "auth.js",
12
+ "entitlements.js",
13
+ "knowledge.js",
14
+ "omni/"
15
+ ],
16
+ "keywords": [
17
+ "cli",
18
+ "ai",
19
+ "codebase",
20
+ "onboarding",
21
+ "learning",
22
+ "developer",
23
+ "documentation"
24
+ ],
25
+ "author": "Ramp <hello@rampup.dev>",
26
+ "license": "MIT",
27
+ "homepage": "https://rampup.dev",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/rampup-dev/ramp.git"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/rampup-dev/ramp/issues"
34
+ },
35
+ "engines": {
36
+ "node": ">=18.0.0"
37
+ },
38
+ "dependencies": {
39
+ "@anthropic-ai/sdk": "^0.70.1",
40
+ "chalk": "^4.1.2",
41
+ "clipboardy": "^3.0.0",
42
+ "commander": "^11.1.0",
43
+ "firebase": "^10.14.1",
44
+ "inquirer": "^8.2.6",
45
+ "open": "^9.1.0",
46
+ "openai": "^4.0.0",
47
+ "ora": "^5.4.1"
48
+ }
49
+ }