@christianriedl/utils 1.0.139 → 1.0.140

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/iOpenAI.d.ts CHANGED
@@ -113,6 +113,7 @@ export interface IOpenAIServiceWithTools extends IOpenAIService {
113
113
  getToolFunctions(tool: string): Promise<IResponseResult>;
114
114
  }
115
115
  export interface IVectorFile {
116
+ id: string;
116
117
  filename: string;
117
118
  attributes: Dictionary<ItemType> | null;
118
119
  }
@@ -135,8 +136,8 @@ export interface IVectorSearchResult {
135
136
  }
136
137
  export interface IOpenAIServiceWithVectorStore extends IOpenAIServiceWithTools {
137
138
  vectorStore?: Dictionary<IVectorStore>;
138
- schemaMetadata: IDataItem[];
139
- fileMetadata: IDataItem[];
139
+ vsMetadata: IDataItem[];
140
+ fileAttributes: IDataItem[];
140
141
  initializeVectorStore(): Promise<boolean>;
141
142
  getVectorStore(vectorStoreId: string): IVectorStore | undefined;
142
143
  addVectorStore(vectorStoreName: string, metadata?: Dictionary<string>): Promise<boolean>;
@@ -145,7 +146,7 @@ export interface IOpenAIServiceWithVectorStore extends IOpenAIServiceWithTools {
145
146
  deleteFile(fileId: string): Promise<boolean>;
146
147
  deleteVectorStore(vectorStoreName: string): Promise<boolean>;
147
148
  searchVectoreStore(vectorStoreName: string, query: string | string[], rewriteQuery?: boolean, maxNumResults?: number, filters?: ICompoundFilter | IComparisonFilter): Promise<IVectorSearchResult[]>;
148
- getFileId(fileUrl: string): string | undefined;
149
+ getFile(fileUrl: string): IVectorFile | undefined;
149
150
  }
150
151
  export interface IOpenAIAppConfig {
151
152
  officeAITools: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/utils",
3
- "version": "1.0.139",
3
+ "version": "1.0.140",
4
4
  "description": "Interfaces, local storage, service worker, configuration, application state",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -2,6 +2,7 @@
2
2
  import { inject, ref, reactive } from 'vue';
3
3
  import { appConfigSymbol, AppConfig, Dictionary } from '@christianriedl/utils';
4
4
  import { getOpenAISymbol, IOpenAIServiceWithVectorStore, IOpenAIAppConfig, IOpenAIOptions, ITool, IMcpTool, IFileSearchTool } from '@christianriedl/utils';
5
+ import OpenAIMetaData from '@christianriedl/utils/src/components/OpenAIMetaData.vue';
5
6
 
6
7
  interface IFunction {
7
8
  name: string;
@@ -30,6 +31,9 @@
30
31
  const selectedVectorStoreName = ref('');
31
32
  const selectedVectorStoreFile = ref('');
32
33
  const showFunctions = ref(false);
34
+ const showMetaData = ref(false);
35
+ const editVectorStore = ref(false);
36
+ const metadata = ref<Dictionary<ItemType>>({});
33
37
  const toolName = ref('');
34
38
  const toolFunctions = reactive<IFunction[]>([]);
35
39
  let fileHandle: FileSystemFileHandle | null = null;
@@ -172,8 +176,16 @@
172
176
  }
173
177
  initializeTools();
174
178
  }
179
+ async function editVectorStore() {
180
+ const vs = openAI.vectorStore![selectedVectorStoreName.value];
181
+ if (vs) {
182
+ editVectorStore.value = true;
183
+ metadata.value = vs.metadata ? vs.metadata : openAI.vsMetadata;
184
+ showMetaData.value = true;
185
+ }
186
+ }
175
187
  async function addFile() {
176
- if (openAI.getFileId(selectedVectorStoreFile.value)) {
188
+ if (openAI.getFile(selectedVectorStoreFile.value)) {
177
189
  alert('File already exists, add a new file path or url !');
178
190
  return;
179
191
  }
@@ -189,30 +201,42 @@
189
201
  }
190
202
  }
191
203
  async function deleteFile() {
192
- const fileId = openAI.getFileId(selectedVectorStoreFile.value);
193
- if (!fileId) {
204
+ const file = openAI.getFile(selectedVectorStoreFile.value);
205
+ if (!file) {
194
206
  alert('File not existing !');
195
207
  return;
196
208
  }
197
- if (!await openAI.deleteFile(fileId)) {
209
+ if (!await openAI.deleteFile(file.id)) {
198
210
  alert('File not deleted, error ! ');
199
211
  }
200
212
  else {
201
213
  vectorStoreSelected();
202
214
  }
203
215
  }
204
- async function searchFile() {
205
- let files: FileSystemFileHandle[] = [];
206
- try {
207
- files = await (window as any).showOpenFilePicker();
208
- if (files.length > 0) {
209
- fileHandle = files[0];
210
- selectedVectorStoreFile.value = fileHandle.name;
211
- }
216
+ async function editFile() {
217
+ const file = openAI.getFile(selectedVectorStoreFile.value);
218
+ if (file) {
219
+ editVectorStore.value = false;
220
+ metadata.value = file.attributes ? file.attributes : openAI.fileAttributes;
221
+ showMetaData.value = true;
212
222
  }
213
- catch (e) {
214
- console.error('Error opening file picker:', e);
215
- return;
223
+ }
224
+ async function saveMetaData(items?: Dictionary<ItemType>) {
225
+ showMetaData.value = false;
226
+ if (items) {
227
+ if (editVectorStore.value) {
228
+ if (await openAI.setAttributes(selectedVectorStoreName.value, null, items as Dictionary<string>)) {
229
+ vs.metadata = items;
230
+ }
231
+ }
232
+ else {
233
+ const file = openAI.getFile(selectedVectorStoreFile.value);
234
+ if (file) {
235
+ if (await openAI.setAttributes(selectedVectorStoreName.value, file.id, items)) {
236
+ file.attributes = items;
237
+ }
238
+ }
239
+ }
216
240
  }
217
241
  }
218
242
  </script>
@@ -222,7 +246,7 @@
222
246
  <h4>OpenAI Settings</h4>
223
247
  <v-row dense align="center">
224
248
  <v-col cols="3">
225
- <v-select v-model="options.model" :items="openAI.modelNames" hide-details density="compact"
249
+ <v-select v-model="options.model" :items="openAI.modelNames" hide-details density="compact"
226
250
  label="Model" @update:modelValue="onOptionChange">
227
251
  </v-select>
228
252
  </v-col>
@@ -312,27 +336,32 @@
312
336
  </template>
313
337
  <v-row dense align="center">
314
338
  <v-col cols="2">
315
- <v-btn class="bg-office" @click="emits('back')">BACK
339
+ <v-btn class="bg-office" @click="emits('back')">
340
+ BACK
316
341
  <v-icon icon="$back"></v-icon>
317
342
  </v-btn>
318
343
  </v-col>
319
344
  <v-col cols="2">
320
- <v-btn :disabled="!optionsChanged && !toolsChanged" class="bg-office" @click="onSave">SAVE
345
+ <v-btn :disabled="!optionsChanged && !toolsChanged" class="bg-office" @click="onSave">
346
+ SAVE
321
347
  <v-icon icon="$save"></v-icon>
322
348
  </v-btn>
323
349
  </v-col>
324
350
  <v-col cols="2">
325
- <v-btn :disabled="!useChanged" class="bg-office" @click="onSaveUsage">SAVE TOOL USE
351
+ <v-btn :disabled="!useChanged" class="bg-office" @click="onSaveUsage">
352
+ SAVE TOOL USE
326
353
  <v-icon icon="$save"></v-icon>
327
354
  </v-btn>
328
355
  </v-col>
329
356
  <v-col cols="2">
330
- <v-btn class="bg-office" @click="onAddMcp">ADD MCP
357
+ <v-btn class="bg-office" @click="onAddMcp">
358
+ ADD MCP
331
359
  <v-icon icon="$plus"></v-icon>
332
360
  </v-btn>
333
361
  </v-col>
334
362
  <v-col cols="2">
335
- <v-btn class="bg-office" @click="onAddSearch">ADD SEARCH
363
+ <v-btn class="bg-office" @click="onAddSearch">
364
+ ADD SEARCH
336
365
  <v-icon icon="$plus"></v-icon>
337
366
  </v-btn>
338
367
  </v-col>
@@ -345,11 +374,10 @@
345
374
  <v-col cols="2">
346
375
  <v-combobox v-model="selectedVectorStoreName" :items="vectorStoreNames" hide-details density="compact" @update:modelValue="vectorStoreSelected()"></v-combobox>
347
376
  </v-col>
348
- <v-col cols="1">
349
- <v-btn variant="text" prepend-icon="$delete" @click="deleteVectorStore">VS</v-btn>
350
- </v-col>
351
- <v-col cols="1">
352
- <v-btn variant="text" prepend-icon="$plus" @click="addVectorStore">VS</v-btn>
377
+ <v-col cols="2">
378
+ <v-btn disabled="!selectedVectorStoreName" variant="text" prepend-icon="$delete" @click="deleteVectorStore">VS</v-btn>
379
+ <v-btn disabled="!selectedVectorStoreName" variant="text" prepend-icon="$plus" @click="addVectorStore">VS</v-btn>
380
+ <v-btn disabled="!selectedVectorStoreName" variant="text" prepend-icon="$pencil" @click="editVectorStore">VS</v-btn>
353
381
  </v-col>
354
382
  <v-col cols="5">
355
383
  <v-combobox v-model="selectedVectorStoreFile" :items="vectorStoreFiles" hide-details density="compact"></v-combobox>
@@ -358,13 +386,15 @@
358
386
  <v-btn variant="text" prepend-icon="$search" @click="searchFile">FILE</v-btn>
359
387
  </v-col>
360
388
  <v-col cols="1">
361
- <v-btn variant="text" prepend-icon="$delete" @click="deleteFile">FILE</v-btn>
362
- </v-col>
363
- <v-col cols="1">
364
- <v-btn variant="text" prepend-icon="$plus" @click="addFile">FILE</v-btn>
389
+ <v-btn disabled="!selectedVectorStoreFile" variant="text" prepend-icon="$delete" @click="deleteFile">FILE</v-btn>
390
+ <v-btn disabled="!selectedVectorStoreFile" variant="text" prepend-icon="$plus" @click="addFile">FILE</v-btn>
391
+ <v-btn disabled="!selectedVectorStoreFile" variant="text" prepend-icon="$pencil" @click="editFile">VS</v-btn>
365
392
  </v-col>
366
393
  </v-row>
367
394
  </template>
395
+ <v-dialog v-model="showMetaData">
396
+ <OpenAIMetaData :items="metadata" :vectorstore="editVectorStore" @back="saveMetaData"></OpenAIMetaData>
397
+ </v-dialog>
368
398
  <v-dialog v-model="showFunctions">
369
399
  <v-container fluid class="bg-office overflow-y-auto">
370
400
  <h4>{{toolName + " functions"}}</h4>
@@ -374,7 +404,8 @@
374
404
  </v-row>
375
405
  <v-row dense align="center">
376
406
  <v-col cols="2">
377
- <v-btn class="bg-office" @click="showFunctions = false">BACK
407
+ <v-btn class="bg-office" @click="showFunctions = false">
408
+ BACK
378
409
  <v-icon icon="$back"></v-icon>
379
410
  </v-btn>
380
411
  </v-col>
@@ -0,0 +1,55 @@
1
+ <script setup lang="ts">
2
+ import { inject, computed, ref, StyleValue } from 'vue';
3
+ import { IDataItem, Dictionary } from '@christianriedl/utils'
4
+ import SettingsLine from '../components/SettingsLine.vue';
5
+
6
+ const props = defineProps<{ items: IDataItem[], vectorstore: boolean }>();
7
+ const emits = defineEmits<{ (e: 'back', items?: IDataItem[]): void }>();
8
+ const items: IDataItem[] = [];
9
+ for (const it of props.items) {
10
+ items.push(Object.assign({}, it);
11
+ }
12
+ const header = props.vectorstore ? "Vector Store Metadata" : "File Attributes";
13
+ const changedItems = new Set<string>();
14
+ const changed = ref(false);
15
+
16
+ function onChange(item: IDataItem, changed: boolean) {
17
+ if (changed)
18
+ changedItems.add(item.name);
19
+ else
20
+ changedItems.delete(item.name);
21
+ changed.value = changedItems.size > 0;
22
+ }
23
+ function onBack(save: boolean) {
24
+ if (save) {
25
+ emits('back', items);
26
+ }
27
+ else {
28
+ emits('back');
29
+ }
30
+
31
+ </script>
32
+
33
+ <template>
34
+ <v-container fluid >
35
+ <h4>{{header}}</h4>
36
+ <v-table>
37
+ <thead>
38
+ <tr>
39
+ <th style="width:50%">Name</th>
40
+ <th style="width:50%">Value</th>
41
+ </tr>
42
+ </thead>
43
+ <tbody>
44
+ <settings-line v-for="item in items" :key="item.name" :item="item" @change="onChange(item, true)" @clear="onChange(item, false)"></settings-line>
45
+ <tr>
46
+ <td style="width:50%">
47
+ <v-btn @click="onBack(false)">BACK</v-btn>
48
+ <v-btn v-if="changed" @click="onBack(true)">SAVE</v-btn>
49
+ </td>
50
+ <td style="width:50%"></td>
51
+ </tr>
52
+ </tbody>
53
+ </v-table>
54
+ </v-container>
55
+ </template>
@@ -2,8 +2,8 @@
2
2
  import { reactive } from 'vue';
3
3
  import { IConfigItem, IDataItem, ItemType, EScope } from '@christianriedl/utils';
4
4
 
5
- const props = defineProps<{ item: IConfigItem | IDataItem; scopes?: EScope }>();
6
- const emits = defineEmits<{ (e: 'change', value: any): void }>();
5
+ const props = defineProps<{ item: IConfigItem | IDataItem; scopes?: EScope, clearable?: boolean }>();
6
+ const emits = defineEmits<{ (e: 'change'): void, (e: 'clear'): void }>();
7
7
 
8
8
  const item = reactive(props.item);
9
9
  const isString = typeof item.default === 'string' && !item.values;
@@ -16,7 +16,11 @@
16
16
  const description = (item as IConfigItem).description || item.name;
17
17
 
18
18
  function onChange() {
19
- emits('change', true);
19
+ emits('change');
20
+ }
21
+ function onClear() {
22
+ item.value = item.default;
23
+ emits('clear');
20
24
  }
21
25
  </script>
22
26
 
@@ -24,14 +28,14 @@
24
28
  <tr v-if="isVisible" class="settingsline">
25
29
  <td style="width:50%">{{description}}</td>
26
30
  <td style="width:50%">
27
- <v-switch v-if="isBoolean" v-model="item.value" :disabled="isDisabled" density="compact" hide-details marg color="primary" @change="onChange"></v-switch>
28
- <v-text-field v-if="isString" v-model="item.value" :disabled="isDisabled" density="compact" hide-details type="string" @change="onChange"></v-text-field>
29
- <v-text-field v-if="isNumber" v-model="item.value" :disabled="isDisabled" density="compact" hide-details type="number" @change="onChange"></v-text-field>
30
- <v-select v-if="isEnum" name="enum" density="compact" v-model="item.value" :disabled="isDisabled"
31
- :items="enumValues"
32
- persistent-hint
33
- @update:modelValue="onChange"
34
- dense solo hide-details single-line>
31
+ <v-switch v-if="isBoolean" v-model="item.value" :disabled="isDisabled" density="compact" hide-details color="primary"
32
+ :append-icon="props.clearable ? '$clear' : undefined" @update:modelValue="onChange" @click:append="onClear"></v-switch>
33
+ <v-text-field v-if="isString" v-model="item.value" :disabled="isDisabled" :clearable="props.clearable" density="compact"
34
+ hide-details type="string" @update:modelValue="onChange" @click:clear="onClear"></v-text-field>
35
+ <v-text-field v-if="isNumber" v-model="item.value" :disabled="isDisabled" :clearable="props.clearable" density="compact"
36
+ hide-details type="number" @update:modelValue="onChange" @click:clear="onClear"></v-text-field>
37
+ <v-select v-if="isEnum" name="enum" density="compact" v-model="item.value" :disabled="isDisabled" :clearable="props.clearable"
38
+ :items="enumValues" persistent-hint @update:modelValue="onChange" @click:clear="onClear" dense solo hide-details single-line>
35
39
  </v-select>
36
40
  </td>
37
41
  </tr>