vzcode 1.24.0 → 1.26.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/dist/assets/{index-C8aUgAEA.js → index-CT7aAJ4z.js} +49 -49
- package/dist/assets/{worker-D_cpKtcn.js → worker-3LvmQt1g.js} +11 -11
- package/dist/index.html +1 -1
- package/package.json +13 -9
- package/src/client/App/index.tsx +4 -1
- package/src/client/CodeEditor/Copilot/index.ts +50 -4
- package/src/client/CodeEditor/getOrCreateEditor.ts +16 -7
- package/src/client/CodeEditor/index.tsx +1 -1
- package/src/client/VZMiddle.tsx +1 -1
- package/src/client/themes/uiwImports.ts +9 -9
- package/src/server/handleAICopilot.js +60 -42
- package/src/server/index.js +1 -1
package/dist/index.html
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
|
21
21
|
rel="stylesheet"
|
|
22
22
|
/>
|
|
23
|
-
<script type="module" crossorigin src="/assets/index-
|
|
23
|
+
<script type="module" crossorigin src="/assets/index-CT7aAJ4z.js"></script>
|
|
24
24
|
<link rel="stylesheet" crossorigin href="/assets/index-zzK6rRiK.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vzcode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -113,6 +113,8 @@
|
|
|
113
113
|
"@codemirror/state": "^6.5.2",
|
|
114
114
|
"@codemirror/theme-one-dark": "^6.1.2",
|
|
115
115
|
"@codemirror/view": "^6.36.3",
|
|
116
|
+
"@langchain/core": "^0.3.40",
|
|
117
|
+
"@langchain/openai": "^0.4.4",
|
|
116
118
|
"@lezer/highlight": "^1.2.1",
|
|
117
119
|
"@livekit/components-react": "^2.8.1",
|
|
118
120
|
"@livekit/components-styles": "^1.1.4",
|
|
@@ -140,23 +142,25 @@
|
|
|
140
142
|
"diff-match-patch": "^1.0.5",
|
|
141
143
|
"dotenv": "^16.4.7",
|
|
142
144
|
"express": "^4.21.2",
|
|
145
|
+
"i": "^0.3.7",
|
|
143
146
|
"ignore": "^7.0.3",
|
|
144
147
|
"json0-ot-diff": "^1.1.2",
|
|
145
|
-
"livekit-client": "^2.9.
|
|
148
|
+
"livekit-client": "^2.9.4",
|
|
146
149
|
"livekit-server-sdk": "^2.10.1",
|
|
147
150
|
"ngrok": "^4.3.3",
|
|
151
|
+
"npm": "^11.1.0",
|
|
148
152
|
"open": "^10.1.0",
|
|
149
|
-
"openai": "^4.85.
|
|
153
|
+
"openai": "^4.85.4",
|
|
150
154
|
"prettier-plugin-svelte": "^3.3.3",
|
|
151
155
|
"react": "^18",
|
|
152
156
|
"react-bootstrap": "^2.10.9",
|
|
153
157
|
"react-dom": "^18",
|
|
154
|
-
"react-router-dom": "^7.
|
|
158
|
+
"react-router-dom": "^7.2.0",
|
|
155
159
|
"sharedb": "^5.1.1",
|
|
156
160
|
"sharedb-client-browser": "^5.1.1",
|
|
157
|
-
"uuid": "^11.0
|
|
161
|
+
"uuid": "^11.1.0",
|
|
158
162
|
"vizhub-ui": "^3.23.0",
|
|
159
|
-
"ws": "^8.18.
|
|
163
|
+
"ws": "^8.18.1"
|
|
160
164
|
},
|
|
161
165
|
"devDependencies": {
|
|
162
166
|
"@types/react": "^18",
|
|
@@ -164,11 +168,11 @@
|
|
|
164
168
|
"@vitejs/plugin-react": "^4.3.4",
|
|
165
169
|
"concurrently": "^9.1.2",
|
|
166
170
|
"cross-env": "^7.0.3",
|
|
167
|
-
"prettier": "^3.5.
|
|
171
|
+
"prettier": "^3.5.2",
|
|
168
172
|
"sass": "^1.85.0",
|
|
169
173
|
"typescript": "^5.7.3",
|
|
170
|
-
"vite": "^6.1.
|
|
171
|
-
"vitest": "^3.0.
|
|
174
|
+
"vite": "^6.1.1",
|
|
175
|
+
"vitest": "^3.0.7"
|
|
172
176
|
},
|
|
173
177
|
"optionalDependencies": {
|
|
174
178
|
"@rollup/rollup-darwin-arm64": "^4.34.8",
|
package/src/client/App/index.tsx
CHANGED
|
@@ -122,7 +122,10 @@ function App() {
|
|
|
122
122
|
>
|
|
123
123
|
<div className="app">
|
|
124
124
|
<VZLeft />
|
|
125
|
-
<VZMiddle
|
|
125
|
+
<VZMiddle
|
|
126
|
+
allowGlobals={true}
|
|
127
|
+
aiCopilotEndpoint={'/ai-copilot'}
|
|
128
|
+
/>
|
|
126
129
|
{enableRightPanel ? <VZRight /> : null}
|
|
127
130
|
<VZResizer side="left" />
|
|
128
131
|
{enableRightPanel ? (
|
|
@@ -2,25 +2,71 @@ import { inlineCopilot } from 'codemirror-copilot';
|
|
|
2
2
|
|
|
3
3
|
const defaultAICopilotEndpoint = '/ai-copilot';
|
|
4
4
|
|
|
5
|
+
const DEBUG = false;
|
|
6
|
+
|
|
7
|
+
// If the endpoint is broken, we don't want to keep sending requests
|
|
8
|
+
// to it. This flag will be set to true if we get an error from the
|
|
9
|
+
// server.
|
|
10
|
+
let isEndpointBroken = false;
|
|
11
|
+
|
|
5
12
|
export const copilot = ({
|
|
6
13
|
aiCopilotEndpoint = defaultAICopilotEndpoint,
|
|
7
14
|
}: {
|
|
8
15
|
aiCopilotEndpoint: string;
|
|
9
16
|
}) => {
|
|
10
17
|
return inlineCopilot(async (prefix, suffix) => {
|
|
18
|
+
DEBUG &&
|
|
19
|
+
console.log('[copilot] Executing AI completion...');
|
|
20
|
+
if (isEndpointBroken) {
|
|
21
|
+
DEBUG &&
|
|
22
|
+
console.log(
|
|
23
|
+
'[copilot] Endpoint is broken, not sending request',
|
|
24
|
+
);
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
DEBUG &&
|
|
29
|
+
console.log('[copilot] Sending request to server...');
|
|
11
30
|
const response = await fetch(aiCopilotEndpoint, {
|
|
12
31
|
method: 'POST',
|
|
13
32
|
headers: { 'Content-Type': 'application/json' },
|
|
14
33
|
body: JSON.stringify({ prefix, suffix }),
|
|
15
34
|
});
|
|
16
35
|
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
DEBUG &&
|
|
38
|
+
console.error(
|
|
39
|
+
'[copilot] Error from server:',
|
|
40
|
+
response.statusText,
|
|
41
|
+
);
|
|
42
|
+
DEBUG &&
|
|
43
|
+
console.error(
|
|
44
|
+
'[copilot] Disabling future requests to the server',
|
|
45
|
+
);
|
|
46
|
+
isEndpointBroken = true;
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
|
|
17
50
|
const responseJson = await response.json();
|
|
18
51
|
|
|
19
|
-
|
|
20
|
-
console.
|
|
21
|
-
'[copilot]
|
|
22
|
-
|
|
52
|
+
DEBUG &&
|
|
53
|
+
console.log(
|
|
54
|
+
'[copilot] Response from server:',
|
|
55
|
+
response,
|
|
23
56
|
);
|
|
57
|
+
|
|
58
|
+
if (responseJson.error) {
|
|
59
|
+
DEBUG &&
|
|
60
|
+
console.error(
|
|
61
|
+
'[copilot] error from server:',
|
|
62
|
+
responseJson.error,
|
|
63
|
+
);
|
|
64
|
+
DEBUG &&
|
|
65
|
+
console.error(
|
|
66
|
+
'[copilot] Disabling future requests to the server',
|
|
67
|
+
);
|
|
68
|
+
isEndpointBroken = true;
|
|
69
|
+
return '';
|
|
24
70
|
}
|
|
25
71
|
|
|
26
72
|
return responseJson.text;
|
|
@@ -50,10 +50,14 @@ import { javascriptLanguage } from '@codemirror/lang-javascript';
|
|
|
50
50
|
import { copilot } from './Copilot';
|
|
51
51
|
|
|
52
52
|
// Feature flag to enable TypeScript completions & TypeScript Linter.
|
|
53
|
-
|
|
53
|
+
// This is disabled by default because it's buggy and glitchy.
|
|
54
|
+
// It's overly aggressive and shows warnings where it should not.
|
|
55
|
+
// Path forward:
|
|
56
|
+
// * Remove this entire TypeScript linter implementation
|
|
57
|
+
// * Use val-town/codemirror-ts: https://github.com/vizhub-core/vzcode/issues/844
|
|
58
|
+
const enableTypeScriptLinter = false;
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
const enableCopilot = true;
|
|
60
|
+
const DEBUG = false;
|
|
57
61
|
|
|
58
62
|
// Enables TypeScript +JSX support in CodeMirror.
|
|
59
63
|
const tsx = () =>
|
|
@@ -135,7 +139,7 @@ export const getOrCreateEditor = ({
|
|
|
135
139
|
enableAutoFollowRef,
|
|
136
140
|
openTab,
|
|
137
141
|
aiCopilotEndpoint,
|
|
138
|
-
rainbowBracketsEnabled = true,
|
|
142
|
+
rainbowBracketsEnabled = true,
|
|
139
143
|
}: {
|
|
140
144
|
// TODO pass this in from the outside
|
|
141
145
|
paneId?: PaneId;
|
|
@@ -172,7 +176,7 @@ export const getOrCreateEditor = ({
|
|
|
172
176
|
// enable auto-following the cursors of remote users.
|
|
173
177
|
enableAutoFollowRef: React.MutableRefObject<boolean>;
|
|
174
178
|
openTab: (tabState: TabState) => void;
|
|
175
|
-
aiCopilotEndpoint
|
|
179
|
+
aiCopilotEndpoint?: string;
|
|
176
180
|
rainbowBracketsEnabled?: boolean; // New parameter type
|
|
177
181
|
}): ExtendedEditorCacheValue => {
|
|
178
182
|
// Cache hit
|
|
@@ -411,8 +415,13 @@ export const getOrCreateEditor = ({
|
|
|
411
415
|
),
|
|
412
416
|
);
|
|
413
417
|
|
|
414
|
-
//
|
|
415
|
-
|
|
418
|
+
// Adds copilot completions
|
|
419
|
+
DEBUG &&
|
|
420
|
+
console.log(
|
|
421
|
+
'[getOrCreateEditor] aiCopilotEndpoint: ',
|
|
422
|
+
aiCopilotEndpoint,
|
|
423
|
+
);
|
|
424
|
+
if (aiCopilotEndpoint) {
|
|
416
425
|
extensions.push(copilot({ aiCopilotEndpoint }));
|
|
417
426
|
}
|
|
418
427
|
|
package/src/client/VZMiddle.tsx
CHANGED
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
// because there is no "type": "module" field in the package.json
|
|
10
10
|
// of any of these `@uiw/codemirror-theme-*` packages.
|
|
11
11
|
|
|
12
|
-
import { okaidia } from '@uiw/codemirror-theme-okaidia
|
|
13
|
-
import { abcdef } from '@uiw/codemirror-theme-abcdef
|
|
14
|
-
import { dracula } from '@uiw/codemirror-theme-dracula
|
|
15
|
-
import { eclipse } from '@uiw/codemirror-theme-eclipse
|
|
16
|
-
import { githubDark } from '@uiw/codemirror-theme-github
|
|
17
|
-
import { material } from '@uiw/codemirror-theme-material
|
|
18
|
-
import { nord } from '@uiw/codemirror-theme-nord
|
|
19
|
-
import { xcodeLight } from '@uiw/codemirror-theme-xcode
|
|
20
|
-
import { createTheme } from '@uiw/codemirror-themes
|
|
12
|
+
import { okaidia } from '@uiw/codemirror-theme-okaidia';
|
|
13
|
+
import { abcdef } from '@uiw/codemirror-theme-abcdef';
|
|
14
|
+
import { dracula } from '@uiw/codemirror-theme-dracula';
|
|
15
|
+
import { eclipse } from '@uiw/codemirror-theme-eclipse';
|
|
16
|
+
import { githubDark } from '@uiw/codemirror-theme-github';
|
|
17
|
+
import { material } from '@uiw/codemirror-theme-material';
|
|
18
|
+
import { nord } from '@uiw/codemirror-theme-nord';
|
|
19
|
+
import { xcodeLight } from '@uiw/codemirror-theme-xcode';
|
|
20
|
+
import { createTheme } from '@uiw/codemirror-themes';
|
|
21
21
|
|
|
22
22
|
export {
|
|
23
23
|
okaidia,
|
|
@@ -1,45 +1,52 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
2
|
+
import { StringOutputParser } from '@langchain/core/output_parsers';
|
|
2
3
|
|
|
3
|
-
// This module implements the generation of the copilot response
|
|
4
|
-
// using the OpenAI client (but not necessarily the OpenAI service).
|
|
4
|
+
// This module implements the generation of the copilot response.
|
|
5
5
|
|
|
6
6
|
// Debug flag to log more information during development.
|
|
7
7
|
const debug = false;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
export const handleAICopilot = () => {
|
|
10
|
+
// These environment variables are used to configure the OpenAI client.
|
|
11
|
+
// See `.env.sample` for the expected values.
|
|
12
|
+
const {
|
|
13
|
+
VZCODE_AI_COPILOT_API_KEY,
|
|
14
|
+
VZCODE_AI_COPILOT_BASE_URL,
|
|
15
|
+
VZCODE_AI_COPILOT_MODEL,
|
|
16
|
+
} = process.env;
|
|
16
17
|
|
|
17
|
-
// If neither of these are not set, the OpenAI client will not be initialized,
|
|
18
|
-
// e.g. for local development where no AI is needed.
|
|
19
|
-
const isCopilotEnabled =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
// If neither of these are not set, the OpenAI client will not be initialized,
|
|
19
|
+
// e.g. for local development where no AI is needed.
|
|
20
|
+
const isCopilotEnabled =
|
|
21
|
+
VZCODE_AI_COPILOT_API_KEY !== undefined &&
|
|
22
|
+
VZCODE_AI_COPILOT_BASE_URL !== undefined &&
|
|
23
|
+
VZCODE_AI_COPILOT_MODEL !== undefined;
|
|
23
24
|
|
|
24
|
-
debug &&
|
|
25
|
-
|
|
25
|
+
debug &&
|
|
26
|
+
console.log('isCopilotEnabled: ' + isCopilotEnabled);
|
|
26
27
|
|
|
27
|
-
let openai;
|
|
28
|
-
if (isCopilotEnabled) {
|
|
29
|
-
const openAIOptions = {
|
|
30
|
-
apiKey: VZCODE_AI_COPILOT_API_KEY,
|
|
31
|
-
baseURL: VZCODE_AI_COLIPOT_BASE_URL,
|
|
32
|
-
};
|
|
33
28
|
debug &&
|
|
34
|
-
console.log(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
console.log({
|
|
30
|
+
VZCODE_AI_COPILOT_API_KEY,
|
|
31
|
+
VZCODE_AI_COPILOT_BASE_URL,
|
|
32
|
+
VZCODE_AI_COPILOT_MODEL,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
let chatModel;
|
|
36
|
+
if (isCopilotEnabled) {
|
|
37
|
+
const options = {
|
|
38
|
+
modelName: VZCODE_AI_COPILOT_MODEL,
|
|
39
|
+
configuration: {
|
|
40
|
+
apiKey: VZCODE_AI_COPILOT_API_KEY,
|
|
41
|
+
baseURL: VZCODE_AI_COPILOT_BASE_URL,
|
|
42
|
+
},
|
|
43
|
+
streaming: false,
|
|
44
|
+
};
|
|
45
|
+
debug && console.log('chatModel options:', options);
|
|
46
|
+
chatModel = new ChatOpenAI(options);
|
|
47
|
+
}
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
async (req, res) => {
|
|
49
|
+
return async (req, res) => {
|
|
43
50
|
// Don't break if the AI is not enabled.
|
|
44
51
|
// This is useful for local development.
|
|
45
52
|
if (!isCopilotEnabled) {
|
|
@@ -48,23 +55,33 @@ export const handleAICopilot = (/*TODO shareDBDoc*/) =>
|
|
|
48
55
|
}
|
|
49
56
|
const { prefix, suffix } = req.body;
|
|
50
57
|
|
|
51
|
-
const
|
|
52
|
-
|
|
58
|
+
const messages = [
|
|
59
|
+
{
|
|
60
|
+
role: 'user',
|
|
61
|
+
content: [
|
|
62
|
+
'Complete the missing part of the text below:\n\n',
|
|
63
|
+
'\`\`\`\n',
|
|
64
|
+
prefix,
|
|
65
|
+
'<MISSING_PART>',
|
|
66
|
+
suffix,
|
|
67
|
+
'\`\`\`\n\n',
|
|
68
|
+
'ONLY output the text that replaces <MISSING_PART>.\n\n',
|
|
69
|
+
'NEVER include \`\`\`javascript or similar code blocks.\n\n',
|
|
70
|
+
].join(''),
|
|
71
|
+
},
|
|
72
|
+
];
|
|
53
73
|
if (debug) {
|
|
54
74
|
console.log(
|
|
55
75
|
'[generateAIResponse] prompt:\n```\n' +
|
|
56
|
-
|
|
76
|
+
messages[0].content +
|
|
57
77
|
'\n```\n',
|
|
58
78
|
);
|
|
59
79
|
}
|
|
60
80
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
stop: ['<|fim_pad|>', '<|file_sep|>'],
|
|
66
|
-
});
|
|
67
|
-
const text = completion.choices[0].text;
|
|
81
|
+
console.log(messages);
|
|
82
|
+
const result = await chatModel.invoke(messages);
|
|
83
|
+
const parser = new StringOutputParser();
|
|
84
|
+
const text = await parser.invoke(result);
|
|
68
85
|
|
|
69
86
|
res.status(200).send({ text });
|
|
70
87
|
} catch (error) {
|
|
@@ -75,3 +92,4 @@ export const handleAICopilot = (/*TODO shareDBDoc*/) =>
|
|
|
75
92
|
});
|
|
76
93
|
}
|
|
77
94
|
};
|
|
95
|
+
};
|