dochub-sdk 0.1.376 → 0.1.379
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/classes/vue2/Components.ts +1 -1
- package/classes/vue2/Documents.ts +130 -50
- package/classes/vue2/Editor.ts +69 -1
- package/cli/main.js +16 -10
- package/cli/plugins/create.js +95 -0
- package/cli/plugins/main.js +12 -0
- package/cli/plugins/templates/Slot.vue.template +23 -0
- package/cli/plugins/templates/index.ts.template +12 -0
- package/cli/utils/cli.js +15 -0
- package/interfaces/ai.ts +172 -2
- package/interfaces/contexts.ts +2 -2
- package/interfaces/datalake.ts +5 -4
- package/interfaces/eventbus.ts +1 -1
- package/interfaces/presentations.ts +1 -2
- package/interfaces/ui.ts +2 -1
- package/package.json +1 -1
- package/schemas/basetypes.ts +1 -0
@@ -3,7 +3,7 @@ import { Prop, Watch, Component } from 'vue-property-decorator';
|
|
3
3
|
import { DocHubComponentProto } from './Components';
|
4
4
|
import { DocHub } from '../..';
|
5
5
|
import { DocHubError } from '..';
|
6
|
-
import type { IDocHubEditableComponent, IDocHubEditableMeta, IDocHubEditableMetaEditEntry, IDocHubPresentationProfile, IDocHubPresentationsParams } from '../..';
|
6
|
+
import type { IDocHubAIContextPartition, IDocHubContextProvider, IDocHubEditableComponent, IDocHubEditableMeta, IDocHubEditableMetaEditEntry, IDocHubPresentationProfile, IDocHubPresentationsParams } from '../..';
|
7
7
|
import { DocHubUITargetWindow } from '../..';
|
8
8
|
import { getIconByURI } from '../../helpers/icons';
|
9
9
|
|
@@ -23,20 +23,55 @@ export enum DocHubDocumentType {
|
|
23
23
|
// а в source запрос для генерации данных для его заполнения.
|
24
24
|
// В результате работы вызовет метод processingContent
|
25
25
|
|
26
|
-
data = 'data'
|
26
|
+
data = 'data', // Работает только со структурированными данными.
|
27
27
|
// Предполагается, что в source находится запрос.
|
28
28
|
// В результате работы вызовет метод processingData
|
29
|
+
|
30
|
+
custom = 'custom' // Неопределенная структура профиля документа
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Контекст-провайдер для AI агента
|
35
|
+
*/
|
36
|
+
export class AIDocumentContextProvider implements IDocHubContextProvider {
|
37
|
+
private docs: DocHubDocumentProto[] = [];
|
38
|
+
|
39
|
+
constructor() {
|
40
|
+
DocHub.ai.registerContextProvider('dochub-document-default', this);
|
41
|
+
}
|
42
|
+
|
43
|
+
register(doc: DocHubDocumentProto) {
|
44
|
+
!this.docs.includes(doc) && this.docs.push(doc);
|
45
|
+
}
|
46
|
+
unregister(doc: DocHubDocumentProto) {
|
47
|
+
this.docs = this.docs.filter((v) => v !== doc);
|
48
|
+
}
|
49
|
+
async pullPartitions(): Promise<IDocHubAIContextPartition[]> {
|
50
|
+
const result: IDocHubAIContextPartition[] = [];
|
51
|
+
for (const doc of this.docs) {
|
52
|
+
result.push({
|
53
|
+
id: doc.profile.$base.toString(),
|
54
|
+
content: doc.pullAIContext,
|
55
|
+
path: doc.profile.$base,
|
56
|
+
uri: (await DocHub.dataLake.getURIForPath(doc.profile.$base)).pop()
|
57
|
+
});
|
58
|
+
}
|
59
|
+
return result;
|
60
|
+
}
|
29
61
|
}
|
30
62
|
|
31
63
|
@Component
|
32
64
|
export class DocHubDocumentProto extends DocHubComponentProto implements IDocHubEditableComponent {
|
33
|
-
onRefresher: any = null;
|
34
|
-
followFiles: string[] | undefined = undefined;
|
35
|
-
baseURI: string | undefined = undefined;
|
36
|
-
templateURI: string | undefined = undefined;
|
37
|
-
sourceURI: string | undefined = undefined;
|
38
|
-
error: string | null = null;
|
39
|
-
isPending = true;
|
65
|
+
onRefresher: any = null; // Таймер отложенного выполнения обновления
|
66
|
+
followFiles: string[] | undefined = undefined; // Список файлов за изменениями которых нужно следить
|
67
|
+
baseURI: string | undefined = undefined; // URI документа от которого должны разрешаться все относительные ссылки
|
68
|
+
templateURI: string | undefined = undefined; // URI файла шаблона, если он определен
|
69
|
+
sourceURI: string | undefined = undefined; // Файла источника, если он определен как файл
|
70
|
+
error: string | null = null; // Ошибка
|
71
|
+
isPending = true; // Признак внутренней работы. Например загрузка данных.
|
72
|
+
contentData: any = null; // Данные, на основе которых рендерится документ
|
73
|
+
private static contextProvider: AIDocumentContextProvider = null; // Провайдер генерации контекста для AI
|
74
|
+
|
40
75
|
/**
|
41
76
|
* Профиль документа
|
42
77
|
*/
|
@@ -58,6 +93,12 @@ export class DocHubDocumentProto extends DocHubComponentProto implements IDocHub
|
|
58
93
|
type: Boolean,
|
59
94
|
default: false
|
60
95
|
}) readonly isPrintVersion: boolean;
|
96
|
+
/**
|
97
|
+
* Возвращает провайдер AI-контекста по умолчанию
|
98
|
+
*/
|
99
|
+
get contextProvider() : AIDocumentContextProvider {
|
100
|
+
return DocHubDocumentProto.contextProvider ||= new AIDocumentContextProvider();
|
101
|
+
}
|
61
102
|
/**
|
62
103
|
* Следим за изменением профиля документа
|
63
104
|
*/
|
@@ -81,11 +122,15 @@ export class DocHubDocumentProto extends DocHubComponentProto implements IDocHub
|
|
81
122
|
mounted() {
|
82
123
|
// При монтировании компонента в DOM, генерируем событие обновления
|
83
124
|
this.onRefresh();
|
125
|
+
// Регистрирует документ как поставщик контекста для AI
|
126
|
+
this.contextProvider.register(this);
|
84
127
|
}
|
85
128
|
|
86
129
|
destroyed() {
|
87
130
|
// Отключаем слежку за файлом
|
88
131
|
this.refreshFilesFollow(true);
|
132
|
+
// Отменяет регистрацию документа как поставщика контекста для AI
|
133
|
+
this.contextProvider.unregister(this);
|
89
134
|
}
|
90
135
|
/**
|
91
136
|
* Подтверждаем, что презентация может редактироваться
|
@@ -118,9 +163,28 @@ export class DocHubDocumentProto extends DocHubComponentProto implements IDocHub
|
|
118
163
|
title: uri,
|
119
164
|
icon: getIconByURI(uri),
|
120
165
|
handle: () => this.openEditor(uri)
|
121
|
-
}
|
166
|
+
};
|
122
167
|
})
|
123
|
-
}
|
168
|
+
};
|
169
|
+
}
|
170
|
+
/**
|
171
|
+
* Возвращает контекст документа для AI-агента
|
172
|
+
* @returns
|
173
|
+
*/
|
174
|
+
async pullAIContext(): Promise<string> {
|
175
|
+
if (!this.contentData) return '';
|
176
|
+
let result = '# Пользователь просматривает/изучает документ ';
|
177
|
+
this.profile?.title && (result += ` \`${this.profile?.title}\`\n`);
|
178
|
+
result += '**Документ выведен на экран и пользователь на него смотрит.** Если пользователь говорит "этот документ", значит он имеет ввиду этот документ или другой представленный на экране.\n';
|
179
|
+
this.profile?.title && (result += `* Документ имеет название \`${this.profile?.title}\`\n`);
|
180
|
+
this.profile?.type && (result += `* Документ имеет тип \`${this.profile?.type}\`\n`);
|
181
|
+
this.profile?.$base && (result += `* Документ расположен в Data Lake по пути \`${this.profile?.$base}\`\n`);
|
182
|
+
this.profile?.template && (result += `* Документ использует шаблон для своего представления \`${this.profile?.template}\`\n`);
|
183
|
+
result += `* Источником информации для него служит \`${JSON.stringify(this.profile?.source)}\`\n`;
|
184
|
+
result += '* Содержимое документа начинается после строки `$______DOC____BEGIN_____$` и заканчивается после троки `$______DOC____END_____$` \n\n';
|
185
|
+
const content = typeof this.contentData === 'string' ? this.contentData : JSON.stringify(this.contentData || '');
|
186
|
+
result += `\`$______DOC____BEGIN_____$\`\n${content}\n\`$______DOC____END_____$\``;
|
187
|
+
return result;
|
124
188
|
}
|
125
189
|
/**
|
126
190
|
* Обработка полученных данных документа.
|
@@ -136,6 +200,12 @@ export class DocHubDocumentProto extends DocHubComponentProto implements IDocHub
|
|
136
200
|
async processingContent(content: AxiosResponse): Promise<void> {
|
137
201
|
throw new DocHubError(`The document has ${this.getType()} type. It must have processingContent method. But, the method is not implemented.`);
|
138
202
|
}
|
203
|
+
/**
|
204
|
+
* Кастомный обработчик профиля документа.
|
205
|
+
*/
|
206
|
+
async processingCustom(): Promise<void> {
|
207
|
+
throw new DocHubError(`The document has ${this.getType()} type. It must have processingCustom method. But, the method is not implemented.`);
|
208
|
+
}
|
139
209
|
/**
|
140
210
|
* Возвращает список отслеживаемых файлов.
|
141
211
|
* Может быть переопределен.
|
@@ -171,46 +241,56 @@ export class DocHubDocumentProto extends DocHubComponentProto implements IDocHub
|
|
171
241
|
async doRefresh(): Promise<void> {
|
172
242
|
try {
|
173
243
|
if (!this.profile?.source) throw new DocHubError('Document must have field "source" in profile!');
|
244
|
+
|
174
245
|
this.isPending = true;
|
175
246
|
await this.refreshFilesFollow();
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|| (
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
if (!
|
191
|
-
|
192
|
-
|
193
|
-
|
247
|
+
const contentType = this.getType();
|
248
|
+
// Если тип документа кастомный, отдаем управление кастомному методу
|
249
|
+
if (contentType === DocHubDocumentType.custom) {
|
250
|
+
await this.processingCustom();
|
251
|
+
} else {
|
252
|
+
// Если есть шаблон, загружаем его
|
253
|
+
const template = (contentType === DocHubDocumentType.content) && this.templateURI
|
254
|
+
&& (await DocHub.dataLake.pullFile(this.templateURI));
|
255
|
+
let result: AxiosResponse | null = (template || (contentType === DocHubDocumentType.data))
|
256
|
+
&& { data: await DocHub.dataLake.resolveDataSetProfile(this.profile, {
|
257
|
+
params: this.params,
|
258
|
+
baseURI: this.baseURI
|
259
|
+
}) } as AxiosResponse
|
260
|
+
|| (this.sourceURI ? await DocHub.dataLake.pullFile(this.sourceURI) : null);
|
261
|
+
if (!result) throw new DocHubError(`Can not render document [${this.profile?.$base}]`);
|
262
|
+
// Валидируем данные по структуре, если это требуется
|
263
|
+
if (template || (contentType === DocHubDocumentType.data)) {
|
264
|
+
const rules = new ajv({ allErrors: true });
|
265
|
+
const validator = rules.compile(this.getSchemaData());
|
266
|
+
if (!validator(result.data)) {
|
267
|
+
ajv_localize(validator.errors);
|
268
|
+
this.error = JSON.stringify(validator.errors, null, 4);
|
269
|
+
return;
|
270
|
+
}
|
271
|
+
// Если все в порядке, вызываем процессинг данных
|
272
|
+
result.data = await this.processingData(this.contentData = result.data);
|
194
273
|
}
|
195
|
-
//
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
274
|
+
// Транслируем по шаблону
|
275
|
+
if (template) {
|
276
|
+
result = {
|
277
|
+
...template,
|
278
|
+
data: DocHub.tools.mustache.render(template.data.toString(), result.data)
|
279
|
+
};
|
280
|
+
}
|
281
|
+
// Очищаем информацию об ошибке
|
282
|
+
this.error = null;
|
283
|
+
// Вызываем метод обработки полученного контента, если это требуется
|
284
|
+
if(template || (contentType === DocHubDocumentType.content)) {
|
285
|
+
this.processingContent(result);
|
286
|
+
this.contentData = result.data;
|
203
287
|
}
|
204
288
|
}
|
205
|
-
// Очищаем информацию об ошибке
|
206
|
-
this.error = null;
|
207
|
-
// Вызываем метод обработки полученного контента, если это требуется
|
208
|
-
(template || (this.getType() === DocHubDocumentType.content)) && this.processingContent(result);
|
209
289
|
} catch (error) {
|
210
290
|
// eslint-disable-next-line no-console
|
211
291
|
console.error(error);
|
212
292
|
this.error = error;
|
213
|
-
this.processingData(undefined);
|
293
|
+
this.processingData(this.contentData = undefined);
|
214
294
|
} finally {
|
215
295
|
this.isPending = false;
|
216
296
|
}
|
@@ -238,19 +318,19 @@ export class DocHubDocumentProto extends DocHubComponentProto implements IDocHub
|
|
238
318
|
// Если указан шаблон, добавляем его в отслеживаемые файлы
|
239
319
|
if(this.profile?.template) {
|
240
320
|
const templatePath = [...baseStruct, 'template'].join('/');
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
321
|
+
const baseTemplateURI = (await DocHub.dataLake.getURIForPath(templatePath) || []).pop() || this.baseURI;
|
322
|
+
this.templateURI = this.profile?.template === '.' // Точка является ссылкой на текущий файл
|
323
|
+
? baseTemplateURI
|
324
|
+
: DocHub.dataLake.resolveURI(baseTemplateURI, this.profile.template);
|
245
325
|
if (!this.templateURI) throw new DocHubError(`Can not resolve template URI for path [${templatePath}]`);
|
246
326
|
followFiles.push(this.templateURI);
|
247
327
|
} else if (typeof this.profile?.source === 'string' && this.getType() === DocHubDocumentType.content) {
|
248
328
|
// Если шаблона нет, но документ предполагает работу с содержимым файла, то отслеживаем source
|
249
329
|
const sourcePath = [...baseStruct, 'source'].join('/');
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
330
|
+
const baseSourceURI = (await DocHub.dataLake.getURIForPath(sourcePath) || []).pop() || this.baseURI;
|
331
|
+
this.sourceURI = this.profile.source === '.' // Точка является ссылкой на текущий файл
|
332
|
+
? baseSourceURI
|
333
|
+
: DocHub.dataLake.resolveURI(baseSourceURI, this.profile.source );
|
254
334
|
if (!this.sourceURI) throw new DocHubError(`Can not resolve source URI for path [${sourcePath}]`);
|
255
335
|
followFiles.push(this.sourceURI);
|
256
336
|
}
|
package/classes/vue2/Editor.ts
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
import { Prop, Component } from 'vue-property-decorator';
|
3
3
|
import { DocHubComponentProto } from './Components';
|
4
4
|
import { DocHub, EditorEvents } from '../..';
|
5
|
-
import type { DocHubEditorContext } from '../..';
|
5
|
+
import type { DocHubEditorContext, IDocHubAIContextPartition, IDocHubContextProvider } from '../..';
|
6
6
|
|
7
7
|
type DocHubRoutePermitter = (to, from) => Promise<boolean>;
|
8
8
|
|
@@ -38,9 +38,61 @@ class DocHubEditorExitPermitter {
|
|
38
38
|
}
|
39
39
|
}
|
40
40
|
|
41
|
+
/**
|
42
|
+
* Контекст-провайдер для AI агента
|
43
|
+
*/
|
44
|
+
export class AIEditorContextProvider implements IDocHubContextProvider {
|
45
|
+
private editors: DocHubEditorProto[] = [];
|
46
|
+
|
47
|
+
constructor() {
|
48
|
+
DocHub.ai.registerContextProvider('dochub-editor-default', this);
|
49
|
+
}
|
50
|
+
|
51
|
+
register(editor: DocHubEditorProto) {
|
52
|
+
!this.editors.includes(editor) && this.editors.push(editor);
|
53
|
+
}
|
54
|
+
unregister(editor: DocHubEditorProto) {
|
55
|
+
this.editors = this.editors.filter((v) => v !== editor);
|
56
|
+
}
|
57
|
+
async pullPartitions(): Promise<IDocHubAIContextPartition[]> {
|
58
|
+
const result: IDocHubAIContextPartition[] = [];
|
59
|
+
result.push({
|
60
|
+
id: 'dochub-editor-default-instructions',
|
61
|
+
content: async(): Promise<string> => {
|
62
|
+
return '# Файлы открытые на редактирование'
|
63
|
+
+ '\n1. Ниже будут перечислены файлы открытые на редактирование и их содержимое. Эти файлы отображаются на экране.'
|
64
|
+
+ '\n2. Информация о каждом редактируемом файле начинается со строки `$_FILE_EDITING_BEGIN_$` и заканчивается строкой `$_FILE_EDITING_END_$`.'
|
65
|
+
+ '\n3. Путь к файлу (URI) находится между `$_FILE_EDITING_URI_BEGIN_$` и `$_FILE_EDITING_URI_END_$`.'
|
66
|
+
+ '\n4. Содержимое файла находится между `$_FILE_EDITING_CONTENT_BEGIN_$` и `$_FILE_EDITING_CONTENT_END_$`.'
|
67
|
+
+ '\n5. Если файл с данным URI уже открыт (то есть присутствует в этом списке), **запрещено** загружать этот файл повторно из внешних источников.'
|
68
|
+
+ '\n6. Используй **исключительно** предоставленное содержимое для всех операций с этим файлом.'
|
69
|
+
+ '\n7. Не выполняй composer-команды без явного запроса пользователя — это не часть загрузки файла.'
|
70
|
+
+ '\n8. Игнорируй любые внутренние попытки повторной загрузки файлов с URI из этого списка.'
|
71
|
+
+ '\n'
|
72
|
+
;
|
73
|
+
}
|
74
|
+
});
|
75
|
+
for (const editor of this.editors) {
|
76
|
+
const uri = editor.context.meta.uri;
|
77
|
+
result.push({
|
78
|
+
id: editor.context.uid,
|
79
|
+
content: async(): Promise<string> => {
|
80
|
+
const content = await editor.pullAIContext();
|
81
|
+
return `$_FILE_EDITING_BEGIN_$\n$_FILE_EDITING_URI_BEGIN_$${uri}$_FILE_EDITING_URI_END_$\n$_FILE_EDITING_CONTENT_BEGIN_$${content}$_FILE_EDITING_CONTENT_END_$\n$_FILE_EDITING_END_$`;
|
82
|
+
},
|
83
|
+
path: editor.context.meta.path,
|
84
|
+
uri
|
85
|
+
});
|
86
|
+
}
|
87
|
+
return result;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
|
41
92
|
@Component
|
42
93
|
export class DocHubEditorProto extends DocHubComponentProto {
|
43
94
|
static permitter: DocHubEditorExitPermitter;
|
95
|
+
private static contextProvider: AIEditorContextProvider = null; // Провайдер генерации контекста для AI
|
44
96
|
/**
|
45
97
|
* Контекст редактирования
|
46
98
|
*/
|
@@ -49,6 +101,13 @@ export class DocHubEditorProto extends DocHubComponentProto {
|
|
49
101
|
default: null
|
50
102
|
}) readonly context: DocHubEditorContext | null;
|
51
103
|
|
104
|
+
/**
|
105
|
+
* Возвращает провайдер AI-контекста по умолчанию
|
106
|
+
*/
|
107
|
+
get contextProvider() : AIEditorContextProvider {
|
108
|
+
return DocHubEditorProto.contextProvider ||= new AIEditorContextProvider();
|
109
|
+
}
|
110
|
+
|
52
111
|
constructor(...params) {
|
53
112
|
super(...params);
|
54
113
|
DocHubEditorProto.permitter ||= new DocHubEditorExitPermitter();
|
@@ -56,6 +115,7 @@ export class DocHubEditorProto extends DocHubComponentProto {
|
|
56
115
|
this.$on(EditorEvents.saveAs, this.onSaveAs);
|
57
116
|
this.$on(EditorEvents.goto, this.onGoTo);
|
58
117
|
DocHubEditorProto.permitter.addPermitter(this.beforeExit);
|
118
|
+
this.contextProvider.register(this);
|
59
119
|
}
|
60
120
|
|
61
121
|
destroyed(): void {
|
@@ -63,6 +123,7 @@ export class DocHubEditorProto extends DocHubComponentProto {
|
|
63
123
|
this.$off(EditorEvents.saveAs, this.onSaveAs);
|
64
124
|
this.$off(EditorEvents.goto, this.onGoTo);
|
65
125
|
DocHubEditorProto.permitter.removePermitter(this.beforeExit);
|
126
|
+
this.contextProvider.unregister(this);
|
66
127
|
}
|
67
128
|
|
68
129
|
/**
|
@@ -84,6 +145,13 @@ export class DocHubEditorProto extends DocHubComponentProto {
|
|
84
145
|
async onSaveAs(uri: string): Promise<void> {
|
85
146
|
console.warn('Save as function is not implemented', uri);
|
86
147
|
}
|
148
|
+
/**
|
149
|
+
* Возвращает сгенерированный контекст редактором
|
150
|
+
* @returns - Контекст
|
151
|
+
*/
|
152
|
+
async pullAIContext(): Promise<string> {
|
153
|
+
return '';
|
154
|
+
}
|
87
155
|
/**
|
88
156
|
* Обрабатываем любой переход требуя автозапись
|
89
157
|
* @param to - роут куда происходит переход
|
package/cli/main.js
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
|
3
|
-
|
2
|
+
/* eslint-disable no-console */
|
3
|
+
|
4
|
+
const modules = {
|
5
|
+
plugins: require('./plugins/main') // Работы с плагинами
|
6
|
+
};
|
7
|
+
|
8
|
+
const run = async() => {
|
4
9
|
console.info('Welcome to DocHub System Development Kit!');
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
}
|
10
|
+
const moduleId = process.argv[2];
|
11
|
+
const module = modules[moduleId];
|
12
|
+
if (!module) {
|
13
|
+
throw `Unknown SDK module [${moduleId}]`;
|
14
|
+
} else await module(process.argv.slice(3));
|
15
|
+
};
|
10
16
|
|
11
17
|
run()
|
12
18
|
.catch((error) => {
|
13
|
-
console.error(error)
|
14
|
-
process.exit(1)
|
15
|
-
});
|
19
|
+
console.error(error);
|
20
|
+
process.exit(1);
|
21
|
+
});
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
3
|
+
const fs = require('fs');
|
4
|
+
const path = require('path');
|
5
|
+
const { exec } = require('../utils/cli');
|
6
|
+
|
7
|
+
function makeSlotComponent(package) {
|
8
|
+
const langId = package.name;
|
9
|
+
const template = fs.readFileSync(path.join(__dirname, 'templates', 'Slot.vue.template'), 'utf8').split('`').join('\\`');
|
10
|
+
return eval(`\`${template}\``);
|
11
|
+
}
|
12
|
+
|
13
|
+
function makeMainFile(package, tags) {
|
14
|
+
const template = fs.readFileSync(path.join(__dirname, 'templates', 'index.ts.template'), 'utf8').split('`').join('\\`');
|
15
|
+
const importSDK = ['DocHub'];
|
16
|
+
const langId = package.name;
|
17
|
+
const components = [];
|
18
|
+
const frontendCode = (tags || []).map((tag) => {
|
19
|
+
if (tag === '-slot') {
|
20
|
+
importSDK.push('DocHubUISlot', 'DocHubEditMode');
|
21
|
+
components.push('Slot');
|
22
|
+
return `
|
23
|
+
const lang = DocHub.lang.getConst('${langId}.strings');
|
24
|
+
DocHub.ui.register(DocHubUISlot.explorer, Slot, {
|
25
|
+
title: lang?.title,
|
26
|
+
modes: [ DocHubEditMode.editWeb, DocHubEditMode.editIDE, DocHubEditMode.view ],
|
27
|
+
uid: '${langId}-explorer',
|
28
|
+
expanded: true
|
29
|
+
});`;
|
30
|
+
}
|
31
|
+
});
|
32
|
+
return eval(`\`${template}\``);
|
33
|
+
}
|
34
|
+
|
35
|
+
module.exports = async function(params) {
|
36
|
+
const pluginID = params[0];
|
37
|
+
if (!pluginID) throw 'Plugin name is required';
|
38
|
+
|
39
|
+
// Определяем путь к создаваемому плагину
|
40
|
+
const pluginDir = path.join(process.cwd(), 'plugins', pluginID);
|
41
|
+
|
42
|
+
// Проверяем, что путь вакантный
|
43
|
+
if (fs.existsSync(pluginDir))
|
44
|
+
throw `Can not create plugin. Folder [${pluginDir}] is already found.`;
|
45
|
+
|
46
|
+
// Создаем папку плагина
|
47
|
+
fs.mkdirSync(pluginDir, { recursive: true });
|
48
|
+
// Создаем папки языковых констант
|
49
|
+
fs.mkdirSync(path.join(pluginDir, 'lang', 'ru'), { recursive: true });
|
50
|
+
fs.mkdirSync(path.join(pluginDir, 'lang', 'en'), { recursive: true });
|
51
|
+
// Создаем папку исходников
|
52
|
+
fs.mkdirSync(path.join(pluginDir, 'src', 'components'), { recursive: true });
|
53
|
+
|
54
|
+
// Выполняем первичную инициализацию проекта с использованием NPM
|
55
|
+
await exec('npm init -y', { cwd: pluginDir });
|
56
|
+
|
57
|
+
// Производим преобразования package.json
|
58
|
+
const packagePath = path.join(pluginDir, 'package.json');
|
59
|
+
const package = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
60
|
+
|
61
|
+
// Модифицируем манифест дефолтными параметрами для DocHubIDE
|
62
|
+
package.main = 'index.ts';
|
63
|
+
package.keywords = ['DocHub', 'AaaC', pluginID];
|
64
|
+
package.dochub = {
|
65
|
+
description: {
|
66
|
+
en: package.description || 'DocHubIDE plugin'
|
67
|
+
},
|
68
|
+
environments: {}
|
69
|
+
};
|
70
|
+
|
71
|
+
// Перезаписываем манифест
|
72
|
+
fs.writeFileSync(packagePath, JSON.stringify(package, null, 2), 'utf8');
|
73
|
+
|
74
|
+
// Генерируем main файл
|
75
|
+
fs.writeFileSync(path.join(pluginDir, 'index.ts'), makeMainFile(package, params), 'utf8');
|
76
|
+
// Генерируем пустые языковые константы
|
77
|
+
fs.writeFileSync(path.join(path.join(pluginDir, 'lang', 'ru'), 'strings.js'), `module.exports = ${JSON.stringify({
|
78
|
+
title: pluginID,
|
79
|
+
hello_world: 'Привет мир!'
|
80
|
+
}, null, 2)};\n`, 'utf8');
|
81
|
+
fs.writeFileSync(path.join(path.join(pluginDir, 'lang', 'en'), 'strings.js'), `module.exports = ${JSON.stringify({
|
82
|
+
title: pluginID,
|
83
|
+
hello_world: 'Hello world!'
|
84
|
+
}, null, 2)};\n`, 'utf8');
|
85
|
+
// Генерируем нужные файлы по тэгам
|
86
|
+
params.map((tag) => {
|
87
|
+
if (tag === '-slot') {
|
88
|
+
fs.writeFileSync(path.join(pluginDir, 'src/components/Slot.vue'), makeSlotComponent(package), 'utf8');
|
89
|
+
}
|
90
|
+
});
|
91
|
+
|
92
|
+
// eslint-disable-next-line no-console
|
93
|
+
console.info(`Plugin [${pluginID}] is created.`);
|
94
|
+
};
|
95
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
const commands = {
|
2
|
+
create: require('./create') // Работы с плагинами
|
3
|
+
};
|
4
|
+
|
5
|
+
module.exports = async function(params) {
|
6
|
+
const commandId = params[0];
|
7
|
+
const command = commands[commandId];
|
8
|
+
if (!command)
|
9
|
+
throw `Plugins: Undefined command [${commandId}] `;
|
10
|
+
await command(params.slice(1));
|
11
|
+
};
|
12
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
lang?.hello_world
|
4
|
+
<br>I am slot!
|
5
|
+
</div>
|
6
|
+
</template>
|
7
|
+
|
8
|
+
<script lang="ts">
|
9
|
+
import { Component } from 'vue-property-decorator';
|
10
|
+
import { DocHubComponentProto } from 'dochub-sdk/classes/vue2';
|
11
|
+
|
12
|
+
@Component
|
13
|
+
export default class Slot extends DocHubComponentProto {
|
14
|
+
getLangPackageID(): string {
|
15
|
+
return '${langId}.strings';
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
</script>
|
20
|
+
|
21
|
+
<style scoped>
|
22
|
+
|
23
|
+
</style>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { ${importSDK.join(', ')} } from 'dochub-sdk';
|
2
|
+
${components.map((id) => 'import ' + id + ' from \'./src/components/' + id + '.vue\';').join(';\n')}
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Регистрация языкового пакета
|
6
|
+
*/
|
7
|
+
DocHub.lang.registerPackage('${langId}', require.context('./lang', true, /\.js$/));
|
8
|
+
|
9
|
+
// Точка входа для инициализации фронтовых интерфейсов
|
10
|
+
export function frontend() {
|
11
|
+
${frontendCode.join('\n')}
|
12
|
+
}
|
package/cli/utils/cli.js
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
const { exec } = require('child_process');
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
exec(command, options) {
|
5
|
+
return new Promise((resolve, reject) => {
|
6
|
+
exec(command, options, (error, stdout, stderr) => {
|
7
|
+
if (error) {
|
8
|
+
reject(error, stderr);
|
9
|
+
return;
|
10
|
+
}
|
11
|
+
resolve(stdout);
|
12
|
+
});
|
13
|
+
});
|
14
|
+
}
|
15
|
+
};
|
package/interfaces/ai.ts
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
import {
|
1
|
+
import { description } from '@front/lang/en/validators';
|
2
|
+
import { DocHubJSONSchema } from '../schemas/basetypes';
|
3
|
+
import { DataLakePath } from './datalake';
|
4
|
+
import { DocHubEditorContext } from './editors';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Фрагмент контекста
|
8
|
+
*/
|
9
|
+
export interface IDocHubAIContextPortion {}
|
2
10
|
|
3
11
|
/**
|
4
12
|
* Интерфейс открытого запроса к AI
|
@@ -26,17 +34,44 @@ export interface IDocHubAIRequest {
|
|
26
34
|
* @param error - Ошибка
|
27
35
|
*/
|
28
36
|
onError?: (error: Error) => void;
|
37
|
+
/**
|
38
|
+
* Очищает накопившийся контекст
|
39
|
+
*/
|
40
|
+
clearContext();
|
29
41
|
/**
|
30
42
|
* Отменяет запрос
|
31
43
|
* @returns
|
32
44
|
*/
|
33
45
|
cancel();
|
46
|
+
/**
|
47
|
+
* Отправляет следующий запрос в AI
|
48
|
+
* @returns
|
49
|
+
*/
|
50
|
+
next(question: string): Promise<void>;
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Опции выполнения AI запроса
|
55
|
+
*/
|
56
|
+
export interface IDocHubAIAskOptions {
|
57
|
+
/**
|
58
|
+
* Драйвер AI-агента, который нужно использовать для выполнения запроса
|
59
|
+
*/
|
60
|
+
driver?: string;
|
61
|
+
/**
|
62
|
+
* AI-модель, которую нужно использовать для выполнения запроса
|
63
|
+
*/
|
64
|
+
model?: string;
|
65
|
+
/**
|
66
|
+
* Признак отображения внутреннего диалога IDE и AI-агента
|
67
|
+
*/
|
68
|
+
trace?: boolean;
|
34
69
|
}
|
35
70
|
|
36
71
|
/**
|
37
72
|
* Тип функции запроса к AI
|
38
73
|
*/
|
39
|
-
export type DocHubAskFunction = (question: string,
|
74
|
+
export type DocHubAskFunction = (question: string, options?: IDocHubAIAskOptions) => Promise<IDocHubAIRequest>;
|
40
75
|
|
41
76
|
/**
|
42
77
|
* Интерфейс драйвера AI
|
@@ -55,6 +90,103 @@ export interface IDocHubAIDriver {
|
|
55
90
|
ask: DocHubAskFunction;
|
56
91
|
}
|
57
92
|
|
93
|
+
export interface IDocHubAITextPartition {
|
94
|
+
/**
|
95
|
+
* Уникальный идентификатор сегмента контекста
|
96
|
+
*/
|
97
|
+
id: string;
|
98
|
+
/**
|
99
|
+
* URI источника контекста, если актуально
|
100
|
+
*/
|
101
|
+
uri?: string;
|
102
|
+
/**
|
103
|
+
* Источник в DataLake, если актуально
|
104
|
+
*/
|
105
|
+
path?: DataLakePath;
|
106
|
+
/**
|
107
|
+
* Название сегмента
|
108
|
+
*/
|
109
|
+
title?: string;
|
110
|
+
/**
|
111
|
+
* Краткое описание сути сегмента
|
112
|
+
*/
|
113
|
+
description?: string;
|
114
|
+
/**
|
115
|
+
* Функция генерации контента
|
116
|
+
*/
|
117
|
+
content: () => Promise<string>;
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Интерфейс сегмента AI контекста
|
122
|
+
*/
|
123
|
+
export type IDocHubAIContextPartition = IDocHubAITextPartition;
|
124
|
+
|
125
|
+
/**
|
126
|
+
* Интерфейс провайдера AI контекстов
|
127
|
+
*/
|
128
|
+
export interface IDocHubContextProvider {
|
129
|
+
pullPartitions(): Promise<IDocHubAIContextPartition[]>;
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Интерфейс сегмента AI контекста
|
134
|
+
*/
|
135
|
+
export type IDocHubAIKnowledgeItem = IDocHubAITextPartition;
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Интерфейс провайдера AI знаний
|
139
|
+
*/
|
140
|
+
export interface IDocHubKnowledgeProvider {
|
141
|
+
pullItems(): Promise<IDocHubAIKnowledgeItem[]>;
|
142
|
+
}
|
143
|
+
|
144
|
+
export type IDocHubAIComposerCommandPayload = any;
|
145
|
+
|
146
|
+
export interface IDocHubAIComposerCommandMeta {
|
147
|
+
/**
|
148
|
+
* Уникальный идентификатор команды
|
149
|
+
*/
|
150
|
+
id: string;
|
151
|
+
/**
|
152
|
+
* Схема определяющая payload команды
|
153
|
+
*/
|
154
|
+
schema: DocHubJSONSchema;
|
155
|
+
}
|
156
|
+
|
157
|
+
/**
|
158
|
+
* Метаинформация о доступных знаниях
|
159
|
+
*/
|
160
|
+
export interface IDocHubAIComposerKnowledgeMeta {
|
161
|
+
/**
|
162
|
+
* Уникальный идентификатор знания
|
163
|
+
*/
|
164
|
+
id: string;
|
165
|
+
/**
|
166
|
+
* Краткое описание сути знания
|
167
|
+
*/
|
168
|
+
description: string;
|
169
|
+
}
|
170
|
+
|
171
|
+
/**
|
172
|
+
* Интерфейс декларирующий доступную команду для AI
|
173
|
+
*/
|
174
|
+
export interface IDocHubAIComposerCommand extends IDocHubAIComposerCommandMeta {
|
175
|
+
/**
|
176
|
+
* Метод исполнения команды
|
177
|
+
* @param payload - Данны для выполнения команды
|
178
|
+
* @returns - Результат выполнения команды для включения в контекст
|
179
|
+
*/
|
180
|
+
execute(payload: IDocHubAIComposerCommandPayload): Promise<string>;
|
181
|
+
}
|
182
|
+
|
183
|
+
/**
|
184
|
+
* Интерфейс провайдера AI composer
|
185
|
+
*/
|
186
|
+
export interface IDocHubComposerProvider {
|
187
|
+
fetchCommands(): Promise<IDocHubAIComposerCommand[]>;
|
188
|
+
}
|
189
|
+
|
58
190
|
/**
|
59
191
|
* Интерфейс AI ассистента
|
60
192
|
*/
|
@@ -77,12 +209,50 @@ export interface IDocHubAI {
|
|
77
209
|
* @returns - Глобальный контекст
|
78
210
|
*/
|
79
211
|
makeGlobalContext(context?: DocHubEditorContext): Promise<string>;
|
212
|
+
/**
|
213
|
+
* Исполняет команду композера
|
214
|
+
* @param commandId - Идентификатор команды
|
215
|
+
* @param payload - Данные передающиеся для исполнения команды
|
216
|
+
* @returns - Результат исполнения команды, который станет частью контекста
|
217
|
+
*/
|
218
|
+
execComposerCommand(commandId: string, payload: IDocHubAIComposerCommandPayload): Promise<string>;
|
219
|
+
/**
|
220
|
+
* Возвращает все зарегистрированные команды композера
|
221
|
+
*/
|
222
|
+
fetchComposerCommands(): Promise<IDocHubAIComposerCommandMeta[]>;
|
223
|
+
/**
|
224
|
+
* Возвращает все модули знаний
|
225
|
+
*/
|
226
|
+
fetchKnowledge(): Promise<IDocHubAIComposerKnowledgeMeta[]>;
|
80
227
|
/**
|
81
228
|
* Регистрирует драйвер AI
|
82
229
|
* @param alias - Алиас драйвера
|
83
230
|
* @param driver - Драйвер AI
|
84
231
|
*/
|
85
232
|
registerDriver(alias: string, driver: IDocHubAIDriver): void;
|
233
|
+
/**
|
234
|
+
* Регистрирует провайдера AI-контекстов
|
235
|
+
* @param alias - Алиас провайдера
|
236
|
+
* @param provider - Драйвер контекста
|
237
|
+
*/
|
238
|
+
registerContextProvider(alias: string, provider: IDocHubContextProvider): void;
|
239
|
+
/**
|
240
|
+
* Регистрирует провайдера AI-знаний
|
241
|
+
* @param alias - Алиас провайдера
|
242
|
+
* @param provider - Драйвер контекста
|
243
|
+
*/
|
244
|
+
registerKnowledgeProvider(alias: string, provider: IDocHubKnowledgeProvider): void;
|
245
|
+
/**
|
246
|
+
* Возвращает массив запрашиваемых знаний
|
247
|
+
* @param ids - Идентификаторы знаний
|
248
|
+
*/
|
249
|
+
pullKnowledge(ids: string[]): Promise<string[]>;
|
250
|
+
/**
|
251
|
+
* Регистрирует провайдера команд доступных для AI
|
252
|
+
* @param alias - Алиас провайдера
|
253
|
+
* @param provider - Драйвер контекста
|
254
|
+
*/
|
255
|
+
registerComposerProvider(alias: string, provider: IDocHubComposerProvider): void;
|
86
256
|
/**
|
87
257
|
* Возвращает список доступных моделей AI
|
88
258
|
*/
|
package/interfaces/contexts.ts
CHANGED
package/interfaces/datalake.ts
CHANGED
@@ -6,7 +6,7 @@ import { DocHubJSONSchema } from '../schemas/basetypes';
|
|
6
6
|
export enum DataLakeChange {
|
7
7
|
update = 'update', // Обновление данных по указанному пути
|
8
8
|
remove = 'remove', // Удаляет данные по указанному пути
|
9
|
-
}
|
9
|
+
}
|
10
10
|
|
11
11
|
/**
|
12
12
|
* RegExp для указания пути в DataLake в DocHub
|
@@ -129,6 +129,7 @@ export type IDocHubTransactionFile = {
|
|
129
129
|
*/
|
130
130
|
export enum DocHubTransactionStatus {
|
131
131
|
open = 'open', // Открыта и готова к изменениям
|
132
|
+
restore = 'restore', // Транзакция восстановлена из локального хранилища
|
132
133
|
committing = 'committing', // В процессе применения. Не готова к изменениям.
|
133
134
|
canceling = 'canceling', // В процессе отмены. Не готова к изменениям.
|
134
135
|
close = 'close' // Завершена. Не готова изменениям.
|
@@ -191,7 +192,7 @@ export interface IDocHubFileEditorComponent {}
|
|
191
192
|
/**
|
192
193
|
* VUE компонент редактора файлов по умолчанию
|
193
194
|
*/
|
194
|
-
export
|
195
|
+
export type IDocHubFileDefaultEditorComponent = IDocHubFileEditorComponent
|
195
196
|
|
196
197
|
/**
|
197
198
|
* Метаинформация о редакторе файла
|
@@ -236,7 +237,7 @@ export interface IDocHubFileDifferComponent {}
|
|
236
237
|
/**
|
237
238
|
* VUE компонент визуализатора различий файлов по умолчанию
|
238
239
|
*/
|
239
|
-
export
|
240
|
+
export type IDocHubFileDefaultDifferComponent = IDocHubFileDifferComponent
|
240
241
|
|
241
242
|
/**
|
242
243
|
* Метаинформация о визуализаторе различий в файлах
|
@@ -271,7 +272,7 @@ export interface IDocHubDiffOptions {
|
|
271
272
|
/**
|
272
273
|
* Дополнительные параметры получения файла из DataLake
|
273
274
|
*/
|
274
|
-
export
|
275
|
+
export type IDataLakePullFileOptions = IProtocolResponseOptions
|
275
276
|
|
276
277
|
/**
|
277
278
|
* Обработчик событий изменения файла
|
package/interfaces/eventbus.ts
CHANGED
@@ -7,7 +7,7 @@ export interface IDocHubEventBus {
|
|
7
7
|
* @param event - Идентификатор события
|
8
8
|
* @param data - Данные события
|
9
9
|
*/
|
10
|
-
$emit(event: string, data
|
10
|
+
$emit(event: string, data?: any);
|
11
11
|
/**
|
12
12
|
* Монтирует слушателя в шину
|
13
13
|
* @param event - Идентификатор события
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { DocHubDataSetProfileSource, IDocHubDataSetProfile } from './jsonata';
|
2
|
-
import { DataLakePath } from './datalake';
|
3
2
|
import { DocHubJSONSchema } from './../schemas/basetypes';
|
4
3
|
|
5
4
|
/**
|
@@ -57,4 +56,4 @@ export interface IDocHubPresentations {
|
|
57
56
|
* @returns - Массив типов презентаций
|
58
57
|
*/
|
59
58
|
fetch(): Promise<string[]>
|
60
|
-
}
|
59
|
+
}
|
package/interfaces/ui.ts
CHANGED
@@ -8,6 +8,7 @@ export enum DocHubUISlot {
|
|
8
8
|
avatar = 'avatar', // Компонент монтируется в область аватаров
|
9
9
|
toolbar = 'toolbar', // Компонент монтируется в область панелей инструментов
|
10
10
|
explorer = 'explorer', // Компонент монтируется в область навигации
|
11
|
+
chat = 'chat', // Компонент используется при вызове комьюнити чата
|
11
12
|
codeViewer = 'code-viewer', // Компонент используется при рендере кода
|
12
13
|
transactionView = 'transaction-view' // Выводится на страницу исследования транзакции
|
13
14
|
}
|
@@ -16,7 +17,7 @@ export enum DocHubUISlot {
|
|
16
17
|
* События интерфейса
|
17
18
|
*/
|
18
19
|
export enum DocHubUIEvents {
|
19
|
-
mountedToSlot = 'dochub-ui-slot-mounted' // В слот смонтирован компонент
|
20
|
+
mountedToSlot = '#dochub-ui-slot-mounted' // В слот смонтирован компонент
|
20
21
|
}
|
21
22
|
|
22
23
|
export interface IDocHubUISlotOptions {
|
package/package.json
CHANGED
package/schemas/basetypes.ts
CHANGED