vzcode 0.44.0 → 0.46.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-7MNYa9sP.css → index-0U2uzpmH.css} +1 -1
- package/dist/assets/{index-f4vqBOE4.js → index-iJQOJ5Kf.js} +38 -38
- package/dist/index.html +2 -2
- package/package.json +7 -7
- package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +42 -0
- package/src/client/AIAssist/AIAssistWidget/index.tsx +96 -0
- package/src/client/AIAssist/AIAssistWidget/style.scss +19 -0
- package/src/client/AIAssist/generateFilesContext.ts +25 -0
- package/src/client/AIAssist/index.ts +3 -0
- package/src/client/AIAssist/startAIAssist.ts +93 -0
- package/src/client/CodeEditor/getOrCreateEditor.ts +9 -18
- package/src/client/CodeEditor/index.tsx +0 -16
- package/src/client/CodeEditor/typeScriptCompletions.ts +1 -5
- package/src/client/CodeEditor/typeScriptLinter.ts +2 -2
- package/src/client/CodeErrorOverlay/index.tsx +23 -18
- package/src/client/Icons/SparklesSVG.tsx +31 -0
- package/src/client/Icons/StopSVG.tsx +15 -0
- package/src/client/Icons/index.tsx +2 -0
- package/src/client/VZMiddle.tsx +20 -8
- package/src/client/generateRequestId.ts +6 -0
- package/src/client/useTypeScript/index.ts +4 -0
- package/src/server/computeInitialDocument.js +26 -37
- package/src/server/config.js +24 -0
- package/src/server/featureFlags.js +7 -1
- package/src/server/generateAIResponse.js +101 -0
- package/src/server/handleAIAssist.js +11 -100
- package/src/server/index.js +50 -58
- package/src/server/setupEnv.js +18 -0
- package/src/types.ts +23 -23
- package/src/client/AIAssist.ts +0 -133
- package/src/client/AIAssistWidget/index.tsx +0 -101
- package/src/client/AIAssistWidget/style.scss +0 -10
|
@@ -4,8 +4,10 @@ import { randomId } from '../randomId.js';
|
|
|
4
4
|
import {
|
|
5
5
|
enableDirectories,
|
|
6
6
|
debugDirectories,
|
|
7
|
+
debugIgnore,
|
|
7
8
|
} from './featureFlags.js';
|
|
8
9
|
import createIgnore from 'ignore';
|
|
10
|
+
import { ignoreFilePattern, baseIgnore } from './config.js';
|
|
9
11
|
|
|
10
12
|
const isDirectory = (file) => file.endsWith('/');
|
|
11
13
|
|
|
@@ -27,7 +29,7 @@ const parseIgnoreFile = (
|
|
|
27
29
|
);
|
|
28
30
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
29
31
|
const globs = content
|
|
30
|
-
.split(/
|
|
32
|
+
.split(/[\n\r]+/)
|
|
31
33
|
.filter(
|
|
32
34
|
// remove blank line and comments
|
|
33
35
|
(line) => line.length > 0 && !line.startsWith('#'),
|
|
@@ -40,7 +42,7 @@ const parseIgnoreFile = (
|
|
|
40
42
|
Boolean(slash) || /\/.*\S/.test(glob);
|
|
41
43
|
const relativeGlob = path.posix.join(
|
|
42
44
|
currentDirectory.replace(
|
|
43
|
-
// escape characters
|
|
45
|
+
// escape characters with special meaning in glob expressions
|
|
44
46
|
/[*?!# \[\]\\]/g,
|
|
45
47
|
(char) => '\\' + char,
|
|
46
48
|
),
|
|
@@ -48,10 +50,10 @@ const parseIgnoreFile = (
|
|
|
48
50
|
hasSlash ? '' : '**',
|
|
49
51
|
glob,
|
|
50
52
|
);
|
|
51
|
-
// preserve leading
|
|
53
|
+
// preserve leading `!` and `/` characters
|
|
52
54
|
return bang + slash + relativeGlob;
|
|
53
55
|
});
|
|
54
|
-
if (
|
|
56
|
+
if (debugIgnore) {
|
|
55
57
|
console.debug(
|
|
56
58
|
'at',
|
|
57
59
|
currentDirectory,
|
|
@@ -94,18 +96,21 @@ export const computeInitialDocument = ({ fullPath }) => {
|
|
|
94
96
|
*/
|
|
95
97
|
let files = [];
|
|
96
98
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
const ignoreFileMatcher = createIgnore().add(
|
|
100
|
+
ignoreFilePattern,
|
|
101
|
+
);
|
|
102
|
+
const isIgnoreFile = (fileName) =>
|
|
103
|
+
ignoreFileMatcher.ignores(fileName);
|
|
102
104
|
|
|
103
105
|
const unsearchedDirectories = [
|
|
104
|
-
{
|
|
106
|
+
{
|
|
107
|
+
currentDirectory: '.',
|
|
108
|
+
ignore: createIgnore().add(baseIgnore),
|
|
109
|
+
},
|
|
105
110
|
];
|
|
106
111
|
|
|
107
112
|
while (unsearchedDirectories.length !== 0) {
|
|
108
|
-
const { currentDirectory,
|
|
113
|
+
const { currentDirectory, ignore: parentIgnore } =
|
|
109
114
|
unsearchedDirectories.pop();
|
|
110
115
|
const currentDirectoryPath = path.join(
|
|
111
116
|
fullPath,
|
|
@@ -122,13 +127,10 @@ export const computeInitialDocument = ({ fullPath }) => {
|
|
|
122
127
|
const ignoreFiles = dirEntries
|
|
123
128
|
.filter(
|
|
124
129
|
(dirent) =>
|
|
125
|
-
dirent.isFile() &&
|
|
126
|
-
/^\.(?:git)?ignore$/.test(dirent.name),
|
|
130
|
+
dirent.isFile() && isIgnoreFile(dirent.name),
|
|
127
131
|
)
|
|
128
132
|
.map((file) => file.name);
|
|
129
|
-
|
|
130
|
-
let { ignore } = ignoreEntry;
|
|
131
|
-
let newIgnoreStack = ignoreStack;
|
|
133
|
+
let ignore = parentIgnore;
|
|
132
134
|
if (ignoreFiles.length > 0) {
|
|
133
135
|
const globs = ignoreFiles.flatMap((fileName) =>
|
|
134
136
|
parseIgnoreFile(
|
|
@@ -137,33 +139,20 @@ export const computeInitialDocument = ({ fullPath }) => {
|
|
|
137
139
|
fileName,
|
|
138
140
|
),
|
|
139
141
|
);
|
|
140
|
-
|
|
141
|
-
newIgnoreStack = ignoreStack.slice();
|
|
142
|
-
newIgnoreStack.push(newEntry);
|
|
143
|
-
ignore = createIgnore().add(
|
|
144
|
-
newIgnoreStack.flatMap((entry) => entry.globs),
|
|
145
|
-
);
|
|
146
|
-
newEntry.ignore = ignore;
|
|
147
|
-
if (debugDirectories) {
|
|
148
|
-
console.debug(
|
|
149
|
-
'at',
|
|
150
|
-
currentDirectory,
|
|
151
|
-
'ignoring globs',
|
|
152
|
-
newIgnoreStack.map((item) => item.globs),
|
|
153
|
-
);
|
|
154
|
-
}
|
|
142
|
+
ignore = createIgnore().add(parentIgnore).add(globs);
|
|
155
143
|
}
|
|
156
144
|
const newFiles = dirEntries
|
|
157
145
|
.filter((dirent) => {
|
|
158
|
-
|
|
159
|
-
path.posix.join(currentDirectory, dirent.name)
|
|
160
|
-
|
|
161
|
-
|
|
146
|
+
const relativePath =
|
|
147
|
+
path.posix.join(currentDirectory, dirent.name) +
|
|
148
|
+
(dirent.isDirectory() ? '/' : '');
|
|
149
|
+
const keep = !ignore.ignores(relativePath);
|
|
150
|
+
if (debugIgnore && !keep) {
|
|
162
151
|
console.debug(
|
|
163
152
|
'at',
|
|
164
153
|
currentDirectory,
|
|
165
154
|
'ignoring',
|
|
166
|
-
|
|
155
|
+
relativePath,
|
|
167
156
|
);
|
|
168
157
|
}
|
|
169
158
|
return keep;
|
|
@@ -180,7 +169,7 @@ export const computeInitialDocument = ({ fullPath }) => {
|
|
|
180
169
|
}
|
|
181
170
|
unsearchedDirectories.push({
|
|
182
171
|
currentDirectory: relativePath,
|
|
183
|
-
|
|
172
|
+
ignore,
|
|
184
173
|
});
|
|
185
174
|
return relativePath + '/';
|
|
186
175
|
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*patterns describing which files should e comsidered as ignore files when creating the file tree.
|
|
3
|
+
*
|
|
4
|
+
* Format: one pattern per line, in gitignore format as defimed by https://git-scm.com/docs/gitignore#_pattern_format
|
|
5
|
+
*/
|
|
6
|
+
export const ignoreFilePattern =
|
|
7
|
+
process.env.IGNORE_FILE_PATTERN ??
|
|
8
|
+
`
|
|
9
|
+
.vzignore
|
|
10
|
+
.ignore
|
|
11
|
+
.gitignore
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* the base ignore patterns, that should be applied before any ignore file found when creating the file tree.
|
|
16
|
+
*
|
|
17
|
+
* These patterns apply even in the absence of an ignore file.
|
|
18
|
+
*/
|
|
19
|
+
export const baseIgnore =
|
|
20
|
+
process.env.BASE_IGNORE ??
|
|
21
|
+
`
|
|
22
|
+
.git/
|
|
23
|
+
node_modules/
|
|
24
|
+
`;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
// Feature flag for directories, disabled until it's fully working.
|
|
2
2
|
export const enableDirectories = true;
|
|
3
3
|
|
|
4
|
-
export const debugDirectories =
|
|
4
|
+
export const debugDirectories = Boolean(
|
|
5
|
+
process.env.DEBUG_FILE_TREE,
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export const debugIgnore = Boolean(
|
|
9
|
+
process.env.DEBUG_IGNORE,
|
|
10
|
+
);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { json1Presence } from '../ot.js';
|
|
3
|
+
|
|
4
|
+
const { editOp, type } = json1Presence;
|
|
5
|
+
|
|
6
|
+
const debug = false;
|
|
7
|
+
|
|
8
|
+
// Feature flag to slow down AI for development/testing
|
|
9
|
+
const slowdown = false;
|
|
10
|
+
|
|
11
|
+
let openai;
|
|
12
|
+
if (process.env.OPENAI_API_KEY !== undefined) {
|
|
13
|
+
openai = new OpenAI();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const AISourceName = 'AIAssist';
|
|
17
|
+
|
|
18
|
+
function opComesFromAIAssist(ops, source) {
|
|
19
|
+
return source === AISourceName;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const streams = {};
|
|
23
|
+
|
|
24
|
+
export const generateAIResponse = async ({
|
|
25
|
+
inputText,
|
|
26
|
+
insertionCursor,
|
|
27
|
+
fileId,
|
|
28
|
+
streamId,
|
|
29
|
+
shareDBDoc,
|
|
30
|
+
}) => {
|
|
31
|
+
if (debug) {
|
|
32
|
+
console.log(
|
|
33
|
+
'[generateAIResponse] inputText:',
|
|
34
|
+
inputText,
|
|
35
|
+
);
|
|
36
|
+
console.log(
|
|
37
|
+
'[generateAIResponse] insertionCursor:',
|
|
38
|
+
insertionCursor,
|
|
39
|
+
);
|
|
40
|
+
console.log('[generateAIResponse] fileId:', fileId);
|
|
41
|
+
console.log('[generateAIResponse] streamId:', streamId);
|
|
42
|
+
console.log(
|
|
43
|
+
'[generateAIResponse] shareDBDoc:',
|
|
44
|
+
shareDBDoc,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function accomodateDocChanges(op, source) {
|
|
48
|
+
if (!opComesFromAIAssist(op, source)) {
|
|
49
|
+
if (op !== null) {
|
|
50
|
+
insertionCursor = type
|
|
51
|
+
.transformPosition(
|
|
52
|
+
['files', fileId, 'text', insertionCursor],
|
|
53
|
+
op,
|
|
54
|
+
)
|
|
55
|
+
.slice(-1)[0];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
shareDBDoc.on('op', accomodateDocChanges);
|
|
61
|
+
|
|
62
|
+
streams[streamId] = await openai.chat.completions.create({
|
|
63
|
+
// model: 'gpt-3.5-turbo',
|
|
64
|
+
model: 'gpt-4',
|
|
65
|
+
|
|
66
|
+
messages: [
|
|
67
|
+
{
|
|
68
|
+
role: 'system',
|
|
69
|
+
content:
|
|
70
|
+
'Write typescript or javascript code to continue the current file, given the other files for context. Use // for comments.',
|
|
71
|
+
},
|
|
72
|
+
{ role: 'user', content: inputText },
|
|
73
|
+
],
|
|
74
|
+
stream: true,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
for await (const part of streams[streamId]) {
|
|
78
|
+
const op = editOp(
|
|
79
|
+
['files', fileId, 'text'],
|
|
80
|
+
'text-unicode',
|
|
81
|
+
[
|
|
82
|
+
insertionCursor,
|
|
83
|
+
part.choices[0]?.delta?.content || '',
|
|
84
|
+
],
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
shareDBDoc.submitOp(op, { source: AISourceName });
|
|
88
|
+
|
|
89
|
+
// Wait for 500ms
|
|
90
|
+
if (slowdown) {
|
|
91
|
+
await new Promise((resolve) => {
|
|
92
|
+
setTimeout(resolve, 1000);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
insertionCursor += (
|
|
97
|
+
part.choices[0]?.delta?.content || ''
|
|
98
|
+
).length;
|
|
99
|
+
}
|
|
100
|
+
shareDBDoc.off('op', accomodateDocChanges);
|
|
101
|
+
};
|
|
@@ -1,109 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { json1Presence } from '../ot.js';
|
|
1
|
+
import { generateAIResponse } from './generateAIResponse.js';
|
|
3
2
|
|
|
4
|
-
const
|
|
3
|
+
const debug = false;
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let openai;
|
|
10
|
-
if (process.env.OPENAI_API_KEY !== undefined) {
|
|
11
|
-
openai = new OpenAI();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function generateAIResponse({
|
|
15
|
-
inputText,
|
|
16
|
-
insertionCursor,
|
|
17
|
-
fileId,
|
|
18
|
-
streamId,
|
|
19
|
-
shareDBDoc,
|
|
20
|
-
}) {
|
|
21
|
-
function accomodateDocChanges(op, source) {
|
|
22
|
-
if (!opComesFromAIAssist(op, source)) {
|
|
23
|
-
if (op !== null) {
|
|
24
|
-
insertionCursor = type
|
|
25
|
-
.transformPosition(
|
|
26
|
-
['files', fileId, 'text', insertionCursor],
|
|
27
|
-
op,
|
|
28
|
-
)
|
|
29
|
-
.slice(-1)[0];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
shareDBDoc.on('op', accomodateDocChanges);
|
|
35
|
-
|
|
36
|
-
streams[streamId] = await openai.chat.completions.create({
|
|
37
|
-
// model: 'gpt-3.5-turbo',
|
|
38
|
-
model: 'gpt-4',
|
|
39
|
-
|
|
40
|
-
messages: [
|
|
41
|
-
{
|
|
42
|
-
role: 'system',
|
|
43
|
-
content:
|
|
44
|
-
'Write typescript or javascript code to continue the current file, given the other files for context. Use // for comments.',
|
|
45
|
-
},
|
|
46
|
-
{ role: 'user', content: inputText },
|
|
47
|
-
],
|
|
48
|
-
stream: true,
|
|
49
|
-
});
|
|
5
|
+
export const handleAIAssist =
|
|
6
|
+
(shareDBDoc) => async (req, res) => {
|
|
7
|
+
const { inputText, insertionCursor, fileId } = req.body;
|
|
50
8
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[
|
|
9
|
+
if (debug) {
|
|
10
|
+
console.log('[handleAIAssist] inputText:', inputText);
|
|
11
|
+
console.log(
|
|
12
|
+
'[handleAIAssist] insertionCursor:',
|
|
56
13
|
insertionCursor,
|
|
57
|
-
|
|
58
|
-
],
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
shareDBDoc.submitOp(op, { source: AISourceName });
|
|
62
|
-
|
|
63
|
-
// Wait for 500ms
|
|
64
|
-
if (slowdown) {
|
|
65
|
-
await new Promise((resolve) => {
|
|
66
|
-
setTimeout(resolve, 1000);
|
|
67
|
-
});
|
|
14
|
+
);
|
|
15
|
+
console.log('[handleAIAssist] fileId:', fileId);
|
|
68
16
|
}
|
|
69
17
|
|
|
70
|
-
insertionCursor += (
|
|
71
|
-
part.choices[0]?.delta?.content || ''
|
|
72
|
-
).length;
|
|
73
|
-
}
|
|
74
|
-
shareDBDoc.off('op', accomodateDocChanges);
|
|
75
|
-
|
|
76
|
-
const confirmCompletedOperation = replaceOp(
|
|
77
|
-
[
|
|
78
|
-
'aiStreams',
|
|
79
|
-
streamId,
|
|
80
|
-
'AIStreamStatus',
|
|
81
|
-
'serverIsRunning',
|
|
82
|
-
],
|
|
83
|
-
true,
|
|
84
|
-
false,
|
|
85
|
-
);
|
|
86
|
-
shareDBDoc.submitOp(confirmCompletedOperation, {
|
|
87
|
-
source: 'AIServer',
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const AISourceName = 'AIAssist';
|
|
92
|
-
|
|
93
|
-
function opComesFromAIAssist(ops, source) {
|
|
94
|
-
return source === AISourceName;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const streams = {};
|
|
98
|
-
|
|
99
|
-
export const handleAIAssist =
|
|
100
|
-
(shareDBDoc) => async (req, res) => {
|
|
101
|
-
const {
|
|
102
|
-
text: inputText,
|
|
103
|
-
cursorLocation: insertionCursor,
|
|
104
|
-
fileId,
|
|
105
|
-
} = req.body;
|
|
106
|
-
|
|
107
18
|
try {
|
|
108
19
|
await generateAIResponse({
|
|
109
20
|
inputText,
|
package/src/server/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import './setupEnv.js';
|
|
2
3
|
import http from 'http';
|
|
3
4
|
import express from 'express';
|
|
4
5
|
import ShareDB from 'sharedb';
|
|
@@ -9,19 +10,10 @@ import path from 'path';
|
|
|
9
10
|
import { fileURLToPath } from 'url';
|
|
10
11
|
import open from 'open';
|
|
11
12
|
import ngrok from 'ngrok';
|
|
12
|
-
import dotenv from 'dotenv';
|
|
13
13
|
import bodyParser from 'body-parser';
|
|
14
14
|
import { json1Presence } from '../ot.js';
|
|
15
15
|
import { computeInitialDocument } from './computeInitialDocument.js';
|
|
16
|
-
import {
|
|
17
|
-
generateAIResponse,
|
|
18
|
-
haltGeneration,
|
|
19
|
-
handleAIAssist,
|
|
20
|
-
} from './handleAIAssist.js';
|
|
21
|
-
|
|
22
|
-
const { replaceOp } = json1Presence;
|
|
23
|
-
|
|
24
|
-
dotenv.config({ path: '../../.env' });
|
|
16
|
+
import { handleAIAssist } from './handleAIAssist.js';
|
|
25
17
|
|
|
26
18
|
// The time in milliseconds by which auto-saving is debounced.
|
|
27
19
|
const autoSaveDebounceTimeMS = 800;
|
|
@@ -105,7 +97,7 @@ shareDBDoc.create(initialDocument, json1Presence.type.uri);
|
|
|
105
97
|
|
|
106
98
|
// Handle AI Assist requests.
|
|
107
99
|
app.post(
|
|
108
|
-
'/
|
|
100
|
+
'/ai-assist',
|
|
109
101
|
bodyParser.json(),
|
|
110
102
|
handleAIAssist(shareDBDoc),
|
|
111
103
|
);
|
|
@@ -221,53 +213,53 @@ shareDBDoc.subscribe(() => {
|
|
|
221
213
|
debounceSave();
|
|
222
214
|
}
|
|
223
215
|
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
216
|
+
// if (
|
|
217
|
+
// op !== null &&
|
|
218
|
+
// op[0] == 'aiStreams' &&
|
|
219
|
+
// source !== 'AIServer' &&
|
|
220
|
+
// source !== 'AIAssist'
|
|
221
|
+
// ) {
|
|
222
|
+
// //This is an insert operation (a new request)
|
|
223
|
+
// if (
|
|
224
|
+
// op[op.length - 1]['i'] !== undefined &&
|
|
225
|
+
// op[op.length - 1]['i']['AIStreamStatus'] !==
|
|
226
|
+
// undefined
|
|
227
|
+
// ) {
|
|
228
|
+
// const input =
|
|
229
|
+
// op[op.length - 1]['i']['AIStreamStatus'];
|
|
230
|
+
|
|
231
|
+
// generateAIResponse({
|
|
232
|
+
// inputText: input.text,
|
|
233
|
+
// insertionCursor: input.insertionCursor,
|
|
234
|
+
// shareDBDoc: shareDBDoc,
|
|
235
|
+
// streamId: op[op.length - 2],
|
|
236
|
+
// fileId: input.fileId,
|
|
237
|
+
// });
|
|
238
|
+
|
|
239
|
+
// const confirmStartOperation = replaceOp(
|
|
240
|
+
// [
|
|
241
|
+
// ...op.filter(
|
|
242
|
+
// (value) => typeof value === 'string',
|
|
243
|
+
// ),
|
|
244
|
+
// 'AIStreamStatus',
|
|
245
|
+
// 'serverIsRunning',
|
|
246
|
+
// ],
|
|
247
|
+
// true,
|
|
248
|
+
// true,
|
|
249
|
+
// );
|
|
250
|
+
|
|
251
|
+
// shareDBDoc.submitOp(confirmStartOperation, {
|
|
252
|
+
// source: 'AIServer',
|
|
253
|
+
// });
|
|
254
|
+
// }
|
|
255
|
+
// if (
|
|
256
|
+
// op[op.length - 1]['r'] !== null &&
|
|
257
|
+
// op[op.length - 2] == 'clientWantsToStart'
|
|
258
|
+
// ) {
|
|
259
|
+
// //client wants to halt generation
|
|
260
|
+
// haltGeneration(op[1]);
|
|
261
|
+
// }
|
|
262
|
+
// }
|
|
271
263
|
});
|
|
272
264
|
});
|
|
273
265
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const dir = fileURLToPath(import.meta.url);
|
|
6
|
+
dotenv.config({
|
|
7
|
+
path: join(dir, '../../../.env'),
|
|
8
|
+
});
|
|
9
|
+
if (process.env.DEBUG_SETUP_ENV) {
|
|
10
|
+
console.log(
|
|
11
|
+
'environment variables set up',
|
|
12
|
+
Object.fromEntries(
|
|
13
|
+
Object.entries(process.env).filter(
|
|
14
|
+
(entry) => !entry[0].endsWith('PATH'),
|
|
15
|
+
),
|
|
16
|
+
),
|
|
17
|
+
);
|
|
18
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// FileId
|
|
2
2
|
// * A unique ID for a file.
|
|
3
3
|
|
|
4
|
-
import { JSONOp } from 'ot-json1';
|
|
5
|
-
|
|
6
4
|
// * This is a random string.
|
|
7
5
|
export type FileId = string;
|
|
8
6
|
|
|
@@ -60,6 +58,8 @@ export interface FileTreeFile {
|
|
|
60
58
|
fileId: FileId;
|
|
61
59
|
}
|
|
62
60
|
|
|
61
|
+
export type JSONOp = any;
|
|
62
|
+
|
|
63
63
|
// `ShareDBDoc`
|
|
64
64
|
// A ShareDB Document.
|
|
65
65
|
// TODO better types? Integrate with upstream how?
|
|
@@ -87,23 +87,23 @@ export type ShareDBDoc<T> = {
|
|
|
87
87
|
// Generated by the client.
|
|
88
88
|
export type AIStreamId = string;
|
|
89
89
|
|
|
90
|
-
// TODO define this interface.
|
|
91
|
-
export type AIStreamStatus = {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
// // TODO define this interface.
|
|
91
|
+
// export type AIStreamStatus = {
|
|
92
|
+
// // This field is managed by the client.
|
|
93
|
+
// // * `true` if the client wants the server to start the generation.
|
|
94
|
+
// // * `false` if the client does not want the server to start the generation.
|
|
95
|
+
// clientWantsToStart: boolean;
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
// // This field is managed by the server.
|
|
98
|
+
// // * `true` if the server is running the generation.
|
|
99
|
+
// // * `false` if the server is not running the generation.
|
|
100
|
+
// serverIsRunning: boolean;
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
// text: string;
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
};
|
|
104
|
+
// startingInsertionCursor: number;
|
|
105
|
+
// fileId: FileId;
|
|
106
|
+
// };
|
|
107
107
|
|
|
108
108
|
/// Alternative universe
|
|
109
109
|
|
|
@@ -142,7 +142,7 @@ export type AIStreamStatus = {
|
|
|
142
142
|
export type VZCodeContent = {
|
|
143
143
|
// `files`
|
|
144
144
|
// * The files in the VZCode instance.
|
|
145
|
-
files
|
|
145
|
+
files?: Files;
|
|
146
146
|
|
|
147
147
|
// `isInteracting`
|
|
148
148
|
// * `true` when the user is interacting
|
|
@@ -161,12 +161,12 @@ export type VZCodeContent = {
|
|
|
161
161
|
// client and server.
|
|
162
162
|
// * This can power the transition of the icon from
|
|
163
163
|
// lightning bolt to stop sign and back (when stream finishes)
|
|
164
|
-
aiStreams?: {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
};
|
|
164
|
+
// aiStreams?: {
|
|
165
|
+
// // These need to be removed at some point?
|
|
166
|
+
// [aiStreamId: AIStreamId]: {
|
|
167
|
+
// AIStreamStatus: AIStreamStatus;
|
|
168
|
+
// };
|
|
169
|
+
// };
|
|
170
170
|
|
|
171
171
|
// TODO consider is there a way to replace the HTTP request to
|
|
172
172
|
// the AIAssist endpoint with a manipulation of the ShareDB document?
|