Skip to content

Commit 5a20dc7

Browse files
committed
v1.1.0: Renamed to vertex-devcode, fixed TypeScript visualizer, added .env loader, error handling improvements
1 parent be2c0ce commit 5a20dc7

9 files changed

Lines changed: 152 additions & 32 deletions

File tree

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,13 @@ dist
33
node_modules
44
.vscode-test/
55
*.vsix
6+
.env
7+
.env.sample
8+
.env.local
9+
.vscode/.env
10+
.vscode/.env.local
11+
.vscode/.env.sample
12+
.vscode/.env.*.local
13+
.vscode/.env.*.sample
14+
.vsix*
15+
.vsix

DOCS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Initializes the AI service with the VS Code extension context.
6161
- **Parameters**:
6262
- `context`: VS Code extension context for accessing secrets storage
6363
- **Returns**: `Promise<boolean>` - true if initialization succeeds
64-
- **Side Effects**: Loads API keys from secret storage, initializes configured AI providers
64+
- **Side Effects**: Loads API keys from secret storage, initializes configured AI Integration
6565

6666
**Provider Management**
6767

@@ -1107,8 +1107,8 @@ See [LICENSE](LICENSE) for license information.
11071107

11081108
## Support
11091109

1110-
- **Issues**: [GitHub Issues](https://github.com/yourusername/vertex-vscode/issues)
1111-
- **Discussions**: [GitHub Discussions](https://github.com/yourusername/vertex-vscode/discussions)
1110+
- **Issues**: [GitHub Issues](https://github.com/dev0root6/Vertex-code-IDE//issues)
1111+
- **Discussions**: [GitHub Discussions](https://github.com/dev0root6/Vertex-code-IDE//discussions)
11121112
- **Email**: support@vertex-ide.com
11131113

11141114
---

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Vertex DevCode
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
{
2-
"name": "vertex-vscode",
3-
"displayName": "Vertex",
4-
"description": "Vertex: The Visual Learning IDE for VS Code",
5-
"version": "0.0.1",
2+
"name": "vertex-devcode",
3+
"displayName": "Vertex DevCode",
4+
"description": "Vertex DevCode: The Visual Learning IDE with AI-Powered Insights",
5+
"version": "1.1.0",
6+
"publisher": "vertex-dev",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/dev0root6/Vertex-code-IDE"
10+
},
611
"engines": {
7-
"vscode": "^1.107.0"
12+
"vscode": "^1.109.0"
813
},
914
"categories": [
1015
"Other"
@@ -24,8 +29,10 @@
2429
"command": "vertex.resetApiKey",
2530
"title": "Vertex: Reset Gemini API Key"
2631
},
27-
{
28-
"command": "vertex.loadLesson",
32+
{ "command": "vertex.loadEnvKeys",
33+
"title": "Vertex: Load API Keys from .env"
34+
},
35+
{ "command": "vertex.loadLesson",
2936
"title": "Vertex: Load Sample Lesson"
3037
},
3138
{

src/extension.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,50 @@ export function activate(context: vscode.ExtensionContext) {
6262
await aiService.initialize(context);
6363
}
6464
});
65+
context.subscriptions.push(resetAllKeys);
66+
67+
// Load API keys from .env file (Development helper)
68+
let loadEnvKeys = vscode.commands.registerCommand('vertex.loadEnvKeys', async () => {
69+
const fs = require('fs');
70+
const path = require('path');
71+
const envPath = path.join(__dirname, '..', '.vscode', '.env');
72+
73+
try {
74+
const envContent = fs.readFileSync(envPath, 'utf8');
75+
const lines = envContent.split('\n');
76+
77+
// Get the 3rd GEMINI_API_KEY
78+
const geminiKeys = lines
79+
.filter((line: string) => line.trim().startsWith('GEMINI_API_KEY='))
80+
.map((line: string) => line.split('=')[1].trim());
81+
82+
if (geminiKeys.length >= 3) {
83+
await context.secrets.store('GEMINI_API_KEY', geminiKeys[2]);
84+
vscode.window.showInformationMessage(`✅ Loaded 3rd Gemini key: ${geminiKeys[2].substring(0, 15)}...`);
85+
}
86+
87+
// Load OpenRouter key
88+
const openRouterLine = lines.find((line: string) => line.trim().startsWith('OPENROUTER='));
89+
if (openRouterLine) {
90+
const key = openRouterLine.split('=')[1].trim();
91+
await context.secrets.store('OPENROUTER_API_KEY', key);
92+
vscode.window.showInformationMessage(`✅ Loaded OpenRouter key`);
93+
}
94+
95+
// Load Ollama key
96+
const ollamaLine = lines.find((line: string) => line.trim().startsWith('OLLAMA_API_KEY='));
97+
if (ollamaLine) {
98+
const key = ollamaLine.split('=')[1].trim();
99+
await context.secrets.store('OLLAMA_CLOUD_API_KEY', key);
100+
vscode.window.showInformationMessage(`✅ Loaded Ollama key`);
101+
}
102+
103+
await aiService.syncModels();
104+
} catch (error) {
105+
vscode.window.showErrorMessage(`Failed to load .env file: ${error}`);
106+
}
107+
});
108+
context.subscriptions.push(loadEnvKeys);
65109

66110
// Command to load a sample lesson
67111
let loadLesson = vscode.commands.registerCommand('vertex.loadLesson', async () => {

src/ghostTextProvider.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@ export class GhostTextProvider implements vscode.InlineCompletionItemProvider {
88
context: vscode.InlineCompletionContext,
99
token: vscode.CancellationToken
1010
): Promise<vscode.InlineCompletionList | vscode.InlineCompletionItem[]> {
11-
const slateService = TeacherSlateService.getInstance();
12-
if (!slateService.isActive()) {
13-
return [];
14-
}
11+
try {
12+
const slateService = TeacherSlateService.getInstance();
13+
if (!slateService.isActive()) {
14+
return [];
15+
}
1516

16-
const fullCode = slateService.getLessonCode();
17-
if (!fullCode) {
18-
return [];
19-
}
17+
const fullCode = slateService.getLessonCode();
18+
if (!fullCode) {
19+
return [];
20+
}
2021

21-
// Get the entire document text and the full lesson/suggestion text
22-
const docText = document.getText();
22+
// Get the entire document text and the full lesson/suggestion text
23+
const docText = document.getText();
2324

2425
// Find where the cursor is in the absolute string
2526
const cursorOffset = document.offsetAt(position);
@@ -46,5 +47,10 @@ export class GhostTextProvider implements vscode.InlineCompletionItemProvider {
4647
}
4748

4849
return [];
50+
} catch (error) {
51+
// Silently handle errors like DocumentMissingInHistoryContext
52+
console.error('[Vertex] Ghost text provider error:', error);
53+
return [];
54+
}
4955
}
5056
}

src/parserService.ts

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class ParserService {
1515
// Keywords that should never be treated as variables
1616
private static EXCLUDE: Record<string, Set<string>> = {
1717
javascript: new Set(['if', 'else', 'for', 'while', 'switch', 'catch', 'function', 'const', 'let', 'var', 'class', 'return', 'console', 'require', 'import', 'export', 'new', 'this', 'typeof', 'instanceof', 'true', 'false', 'null', 'undefined', 'void']),
18-
typescript: new Set(['if', 'else', 'for', 'while', 'switch', 'catch', 'function', 'const', 'let', 'var', 'class', 'return', 'console', 'require', 'import', 'export', 'new', 'this', 'typeof', 'instanceof', 'true', 'false', 'null', 'undefined', 'void', 'interface', 'type', 'enum', 'namespace', 'abstract', 'implements', 'extends', 'readonly', 'public', 'private', 'protected', 'static', 'async', 'await', 'number', 'string', 'boolean', 'any', 'never', 'unknown', 'infer', 'keyof', 'typeof', 'declare']),
18+
typescript: new Set(['if', 'else', 'for', 'while', 'switch', 'catch', 'function', 'const', 'let', 'var', 'class', 'return', 'console', 'require', 'import', 'export', 'new', 'this', 'typeof', 'instanceof', 'true', 'false', 'null', 'undefined', 'void', 'interface', 'type', 'enum', 'namespace', 'abstract', 'implements', 'extends', 'readonly', 'public', 'private', 'protected', 'static', 'async', 'await', 'number', 'string', 'boolean', 'any', 'never', 'unknown', 'infer', 'keyof', 'declare', 'get', 'set', 'constructor', 'super', 'break', 'continue', 'do', 'try', 'finally', 'throw', 'case', 'default', 'yield', 'delete', 'with', 'debugger', 'as', 'from', 'of', 'in']),
1919
python: new Set(['if', 'else', 'elif', 'for', 'while', 'class', 'return', 'print', 'range', 'def', 'import', 'from', 'with', 'as', 'try', 'except', 'pass', 'and', 'or', 'not', 'in', 'is', 'True', 'False', 'None', 'lambda', 'yield', 'global', 'nonlocal', 'assert', 'break', 'continue', 'del', 'raise']),
2020
java: new Set(['if', 'else', 'for', 'while', 'switch', 'catch', 'new', 'return', 'class', 'throw', 'System', 'public', 'private', 'static', 'void', 'int', 'long', 'double', 'boolean', 'String', 'true', 'false', 'null']),
2121
c: new Set(['if', 'else', 'for', 'while', 'switch', 'return', 'printf', 'scanf', 'include', 'define', 'int', 'float', 'char', 'void', 'unsigned', 'long', 'short', 'struct', 'typedef', 'NULL']),
@@ -106,6 +106,32 @@ export class ParserService {
106106
}
107107

108108
} else if (lang === 'javascript' || lang === 'typescript') {
109+
// Class/Interface method: public methodName(...) or methodName(...)
110+
const methodMatch = trimmed.match(/^(?:(?:public|private|protected|static|async|readonly)\s+)*([a-zA-Z_][a-zA-Z0-9_]*)\s*\(([^)]*)\)/);
111+
if (methodMatch && !trimmed.startsWith('function ') && !trimmed.startsWith('if') && !trimmed.startsWith('for') && !trimmed.startsWith('while') && !trimmed.startsWith('switch')) {
112+
const methodName = methodMatch[1];
113+
// Only add method name if it's not a keyword
114+
if (!excludeSet.has(methodName)) {
115+
addDef(methodName, lineNum, line);
116+
}
117+
// Parse parameters
118+
const parenIdx = line.indexOf('(', line.indexOf(methodName));
119+
const paramsStr = methodMatch[2] || '';
120+
let searchFrom = parenIdx + 1;
121+
if (paramsStr.trim()) {
122+
paramsStr.split(',').forEach(rawP => {
123+
const p = rawP.trim().split('=')[0].trim().split(':')[0].trim().replace(/^\.\.\./, '').replace(/[?]/g, '');
124+
if (p && !excludeSet.has(p)) {
125+
const col = line.indexOf(p, searchFrom);
126+
if (col !== -1) {
127+
definitions.set(p, { name: p, line: lineNum, startCol: col, endCol: col + p.length });
128+
searchFrom = col + p.length;
129+
}
130+
}
131+
});
132+
}
133+
}
134+
109135
// Function declaration: function foo(a, b) or const foo = (a, b) => or const foo = async (a, b) =>
110136
const fnDeclMatch = trimmed.match(/(?:function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*|(?:const|let|var)\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(?:async\s*)?(?:function\s*)?\()\s*([^)]*)\)/);
111137
if (fnDeclMatch) {
@@ -114,16 +140,18 @@ export class ParserService {
114140
const parenIdx = line.indexOf('(');
115141
const paramsStr = fnDeclMatch[3] || '';
116142
let searchFrom = parenIdx + 1;
117-
paramsStr.split(',').forEach(rawP => {
118-
const p = rawP.trim().split('=')[0].trim().split(':')[0].trim().replace(/^\.\.\./, '');
119-
if (p) {
120-
const col = line.indexOf(p, searchFrom);
121-
if (col !== -1 && !excludeSet.has(p)) {
122-
definitions.set(p, { name: p, line: lineNum, startCol: col, endCol: col + p.length });
123-
searchFrom = col + p.length;
143+
if (paramsStr.trim()) {
144+
paramsStr.split(',').forEach(rawP => {
145+
const p = rawP.trim().split('=')[0].trim().split(':')[0].trim().replace(/^\.\.\./, '').replace(/[?]/g, '');
146+
if (p && !excludeSet.has(p)) {
147+
const col = line.indexOf(p, searchFrom);
148+
if (col !== -1) {
149+
definitions.set(p, { name: p, line: lineNum, startCol: col, endCol: col + p.length });
150+
searchFrom = col + p.length;
151+
}
124152
}
125-
}
126-
});
153+
});
154+
}
127155
}
128156

129157
// TS: interface/type/enum/class declaration
@@ -134,6 +162,10 @@ export class ParserService {
134162
const varMatch = trimmed.match(/^(?:const|let|var)\s+([a-zA-Z_][a-zA-Z0-9_]*)/);
135163
if (varMatch) addDef(varMatch[1], lineNum, line);
136164

165+
// Class properties: private _view?: Type or public name: string
166+
const propMatch = trimmed.match(/^(?:public|private|protected|readonly|static)\s+([a-zA-Z_][a-zA-Z0-9_]*)[?:]?\s*:/);
167+
if (propMatch) addDef(propMatch[1], lineNum, line);
168+
137169
// For loop: for (let i = 0...) or for (const x of arr)
138170
const forMatch = trimmed.match(/^for\s*\(\s*(?:let|const|var)?\s*([a-zA-Z_][a-zA-Z0-9_]*)/);
139171
if (forMatch) addDef(forMatch[1], lineNum, line);

src/visualizerProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export class VisualizerProvider implements vscode.WebviewViewProvider {
177177
}
178178
179179
const curve = Math.min(Math.abs(sy - ey) * 0.45, 80);
180-
const d = `M${ sx },${ sy } C${ sx - curve },${ sy } ${ ex - curve },${ ey } ${ ex },${ ey } `;
180+
const d = 'M' + sx + ',' + sy + ' C' + (sx - curve) + ',' + sy + ' ' + (ex - curve) + ',' + ey + ' ' + ex + ',' + ey;
181181
const path = document.createElementNS('http://www.w3.org/2000/svg','path');
182182
path.setAttribute('d', d);
183183
path.classList.add('arrow-path');

0 commit comments

Comments
 (0)