@things-factory/ai-assistant 10.1.254 → 10.1.257
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/client/settings/ai-agent-setting-let.ts +46 -63
- package/client/settings/ai-usage-setting-let.ts +18 -30
- package/dist-client/settings/ai-agent-setting-let.d.ts +8 -7
- package/dist-client/settings/ai-agent-setting-let.js +47 -79
- package/dist-client/settings/ai-agent-setting-let.js.map +1 -1
- package/dist-client/settings/ai-usage-setting-let.d.ts +4 -5
- package/dist-client/settings/ai-usage-setting-let.js +19 -37
- package/dist-client/settings/ai-usage-setting-let.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
|
@@ -4,7 +4,7 @@ import '@things-factory/setting-base/dist-client/layout/settinglet.js'
|
|
|
4
4
|
import gql from 'graphql-tag'
|
|
5
5
|
import { css, html, LitElement, nothing } from 'lit'
|
|
6
6
|
import { customElement, state } from 'lit/decorators.js'
|
|
7
|
-
import {
|
|
7
|
+
import { MutationController, QueryController } from '@operato/graphql'
|
|
8
8
|
import { i18next, localize } from '@operato/i18n'
|
|
9
9
|
import { OxPrompt } from '@operato/popup'
|
|
10
10
|
import '@operato/popup/ox-popup-menu.js'
|
|
@@ -265,28 +265,36 @@ export class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
|
265
265
|
`
|
|
266
266
|
]
|
|
267
267
|
|
|
268
|
-
@state() private settings?: AgentSettings
|
|
269
|
-
@state() private loadFailed?: string
|
|
270
268
|
@state() private draft?: AgentDraft
|
|
271
|
-
|
|
272
|
-
@state() private
|
|
269
|
+
/* The provider, key and address the model list is read for - set when the editor asks, not on every keystroke. */
|
|
270
|
+
@state() private modelsAsk?: Record<string, string>
|
|
273
271
|
@state() private saveError?: string
|
|
274
272
|
@state() private keyFor?: string
|
|
275
273
|
@state() private keyDraft = ''
|
|
276
274
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
275
|
+
/* The agents of this domain and the domains above (ADR-0190). */
|
|
276
|
+
private agents = new QueryController(this, SETTINGS_QUERY, { fetchPolicy: 'network-only' })
|
|
277
|
+
private modelList = new QueryController(this, MODELS_QUERY, { variables: () => this.modelsAsk, fetchPolicy: 'network-only' })
|
|
278
|
+
/* A refusal is drawn beside the editor or in a prompt here, so the link does not report it again. */
|
|
279
|
+
private saver = new MutationController(this, SAVE_MUTATION, { refetch: () => [this.agents], showsError: true })
|
|
280
|
+
|
|
281
|
+
private get settings(): AgentSettings | undefined {
|
|
282
|
+
return this.agents.data?.aiAgentSettings
|
|
280
283
|
}
|
|
281
284
|
|
|
282
|
-
private
|
|
283
|
-
this.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
285
|
+
private get loadFailed(): string | undefined {
|
|
286
|
+
return this.agents.error ? messageOf(this.agents.error) : undefined
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private get models(): ModelList {
|
|
290
|
+
if (!this.modelsAsk) return { state: 'idle', models: [] }
|
|
291
|
+
if (this.modelList.loading || !(this.modelList.data || this.modelList.error)) return { state: 'loading', models: [] }
|
|
292
|
+
if (this.modelList.error) return { state: 'failed', models: [], reason: messageOf(this.modelList.error) }
|
|
293
|
+
return { state: 'ready', models: this.modelList.data.aiProviderModels ?? [] }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private get saving() {
|
|
297
|
+
return this.saver.pending
|
|
290
298
|
}
|
|
291
299
|
|
|
292
300
|
render() {
|
|
@@ -303,7 +311,7 @@ export class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
|
303
311
|
return html`
|
|
304
312
|
<div class="head">
|
|
305
313
|
<span class="status off">${t('load-failed', 'Could not read the AI agents.')} ${this.loadFailed}</span>
|
|
306
|
-
<button type="button" @click=${() => this.
|
|
314
|
+
<button type="button" @click=${() => this.agents.refetch()}><md-icon>refresh</md-icon>${t('retry', 'Try again')}</button>
|
|
307
315
|
</div>
|
|
308
316
|
`
|
|
309
317
|
}
|
|
@@ -532,7 +540,7 @@ export class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
|
532
540
|
private startNew() {
|
|
533
541
|
this.saveError = undefined
|
|
534
542
|
this.draft = draftOf()
|
|
535
|
-
this.
|
|
543
|
+
this.modelsAsk = undefined
|
|
536
544
|
}
|
|
537
545
|
|
|
538
546
|
private startEdit(agent: AgentView) {
|
|
@@ -544,7 +552,7 @@ export class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
|
544
552
|
private cancelEdit() {
|
|
545
553
|
this.draft = undefined
|
|
546
554
|
this.saveError = undefined
|
|
547
|
-
this.
|
|
555
|
+
this.modelsAsk = undefined
|
|
548
556
|
}
|
|
549
557
|
|
|
550
558
|
private patch(change: Partial<AgentDraft>) {
|
|
@@ -554,40 +562,28 @@ export class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
|
554
562
|
/** A provider decides the model list, so changing it empties the model. */
|
|
555
563
|
private onProvider(provider: string) {
|
|
556
564
|
this.patch({ provider, model: '', organization: provider === 'openai' ? this.draft!.organization : '' })
|
|
557
|
-
this.
|
|
565
|
+
this.modelsAsk = undefined
|
|
558
566
|
this.loadModels()
|
|
559
567
|
}
|
|
560
568
|
|
|
561
|
-
private
|
|
562
|
-
|
|
563
|
-
private async loadModels() {
|
|
569
|
+
private loadModels() {
|
|
564
570
|
const draft = this.draft
|
|
565
571
|
if (!draft) return
|
|
566
572
|
const stored = this.settings?.agents.find(one => one.id === draft.id && !one.inherited)
|
|
567
573
|
const useStored = !draft.apiKey.trim() && stored?.keyState === 'own' && stored.provider === draft.provider
|
|
568
574
|
if (!draft.apiKey.trim() && !useStored) {
|
|
569
|
-
this.
|
|
575
|
+
this.modelsAsk = undefined
|
|
570
576
|
return
|
|
571
577
|
}
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
fetchPolicy: 'network-only',
|
|
578
|
-
variables: {
|
|
579
|
-
provider: draft.provider,
|
|
580
|
-
...(draft.apiKey.trim() ? { apiKey: draft.apiKey.trim() } : { agentId: draft.id }),
|
|
581
|
-
...(draft.baseURL.trim() && { baseURL: draft.baseURL.trim() }),
|
|
582
|
-
...(draft.organization.trim() && { organization: draft.organization.trim() })
|
|
583
|
-
}
|
|
584
|
-
})
|
|
585
|
-
if (token !== this.modelsToken) return
|
|
586
|
-
this.models = { state: 'ready', models: answered(response, 'aiProviderModels') ?? [] }
|
|
587
|
-
} catch (error: any) {
|
|
588
|
-
if (token !== this.modelsToken) return
|
|
589
|
-
this.models = { state: 'failed', models: [], reason: messageOf(error) }
|
|
578
|
+
const ask: Record<string, string> = {
|
|
579
|
+
provider: draft.provider,
|
|
580
|
+
...(draft.apiKey.trim() ? { apiKey: draft.apiKey.trim() } : { agentId: draft.id! }),
|
|
581
|
+
...(draft.baseURL.trim() && { baseURL: draft.baseURL.trim() }),
|
|
582
|
+
...(draft.organization.trim() && { organization: draft.organization.trim() })
|
|
590
583
|
}
|
|
584
|
+
/* The same ask again (the reload button) reads the list again. */
|
|
585
|
+
if (JSON.stringify(ask) === JSON.stringify(this.modelsAsk)) this.modelList.refetch()
|
|
586
|
+
else this.modelsAsk = ask
|
|
591
587
|
}
|
|
592
588
|
|
|
593
589
|
private startKeyOverride(agent: AgentView) {
|
|
@@ -640,34 +636,21 @@ export class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
|
640
636
|
}
|
|
641
637
|
|
|
642
638
|
private async save(change: SaveChange) {
|
|
643
|
-
this.saving = true
|
|
644
639
|
this.saveError = undefined
|
|
645
|
-
|
|
646
|
-
answered(await client.mutate({ mutation: SAVE_MUTATION, variables: { input: saveInput(this.settings!, change) } }), 'saveAiAgents')
|
|
640
|
+
if (await this.saver.run({ input: saveInput(this.settings!, change) })) {
|
|
647
641
|
if (change.kind === 'upsert') this.cancelEdit()
|
|
648
642
|
if (change.kind === 'key-override') ((this.keyFor = undefined), (this.keyDraft = ''))
|
|
649
|
-
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
} finally {
|
|
657
|
-
this.saving = false
|
|
643
|
+
return
|
|
644
|
+
}
|
|
645
|
+
this.saveError = messageOf(this.saver.error)
|
|
646
|
+
if (change.kind !== 'upsert' && change.kind !== 'key-override') {
|
|
647
|
+
await OxPrompt.open({ type: 'error', title: t('save-failed', 'Not saved'), text: this.saveError, confirmButton: { text: t('close', 'Close') } })
|
|
648
|
+
/* The switch flipped on screen goes back to what is stored. */
|
|
649
|
+
await this.agents.refetch()
|
|
658
650
|
}
|
|
659
651
|
}
|
|
660
652
|
}
|
|
661
653
|
|
|
662
|
-
/**
|
|
663
|
-
* The data of a query or mutation. This client answers a refusal in `errors` (errorPolicy 'all') instead of
|
|
664
|
-
* throwing, so it is turned into a throw here - the server's sentence, already in the person's language.
|
|
665
|
-
*/
|
|
666
|
-
function answered(result: any, field: string): any {
|
|
667
|
-
if (result?.errors?.length) throw new Error(result.errors[0].message)
|
|
668
|
-
return result?.data?.[field]
|
|
669
|
-
}
|
|
670
|
-
|
|
671
654
|
async function confirm(title: string, text: string): Promise<boolean> {
|
|
672
655
|
return !!(await OxPrompt.open({
|
|
673
656
|
type: 'warning',
|
|
@@ -4,7 +4,7 @@ import '@operato/input/ox-input-select-buttons.js'
|
|
|
4
4
|
import gql from 'graphql-tag'
|
|
5
5
|
import { css, html, LitElement, nothing } from 'lit'
|
|
6
6
|
import { customElement, state } from 'lit/decorators.js'
|
|
7
|
-
import {
|
|
7
|
+
import { QueryController } from '@operato/graphql'
|
|
8
8
|
import { i18next, localize } from '@operato/i18n'
|
|
9
9
|
import { FormFieldStyles, ScrollbarStyles } from '@operato/styles'
|
|
10
10
|
|
|
@@ -121,35 +121,23 @@ export class AiUsageSettingLet extends localize(i18next)(LitElement) {
|
|
|
121
121
|
@state() private includeDescendants = false
|
|
122
122
|
@state() private agentFilter = ''
|
|
123
123
|
@state() private userFilter = ''
|
|
124
|
-
|
|
125
|
-
@state() private
|
|
124
|
+
/* The range is fixed when the period is chosen, so it stays the same variables until the next choice. */
|
|
125
|
+
@state() private range = periodRange(this.period, new Date())
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
/* The usage for the chosen period (ADR-0190); the agent and person choices are drawn from it, so they stay while
|
|
128
|
+
another period is read. */
|
|
129
|
+
private usage = new QueryController(this, USAGE_QUERY, {
|
|
130
|
+
variables: () => ({ ...this.range, bucket: this.bucket, includeDescendants: this.includeDescendants }),
|
|
131
|
+
keepPrevious: true
|
|
132
|
+
})
|
|
131
133
|
|
|
132
|
-
private
|
|
134
|
+
private get rows(): UsageRow[] | undefined {
|
|
135
|
+
return this.usage.data?.aiUsageSummary ?? undefined
|
|
136
|
+
}
|
|
133
137
|
|
|
134
|
-
private
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
this.rows = undefined
|
|
138
|
-
const { from, to } = periodRange(this.period, new Date())
|
|
139
|
-
try {
|
|
140
|
-
const response = await client.query({
|
|
141
|
-
query: USAGE_QUERY,
|
|
142
|
-
fetchPolicy: 'network-only',
|
|
143
|
-
variables: { from, to, bucket: this.bucket, includeDescendants: this.includeDescendants }
|
|
144
|
-
})
|
|
145
|
-
if (token !== this.loadToken) return
|
|
146
|
-
/* This client answers a refusal in `errors` (errorPolicy 'all') instead of throwing. */
|
|
147
|
-
if ((response as any).errors?.length) throw new Error((response as any).errors[0].message)
|
|
148
|
-
this.rows = response.data?.aiUsageSummary ?? []
|
|
149
|
-
} catch (error: any) {
|
|
150
|
-
if (token !== this.loadToken) return
|
|
151
|
-
this.failed = error?.graphQLErrors?.[0]?.message ?? error?.message ?? String(error)
|
|
152
|
-
}
|
|
138
|
+
private get failed(): string | undefined {
|
|
139
|
+
const error: any = this.usage.error
|
|
140
|
+
return error ? (error.graphQLErrors?.[0]?.message ?? error.message ?? String(error)) : undefined
|
|
153
141
|
}
|
|
154
142
|
|
|
155
143
|
render() {
|
|
@@ -174,7 +162,7 @@ export class AiUsageSettingLet extends localize(i18next)(LitElement) {
|
|
|
174
162
|
{ display: t('7d', '7 days'), value: '7d' },
|
|
175
163
|
{ display: t('30d', '30 days'), value: '30d' }
|
|
176
164
|
]}
|
|
177
|
-
@change=${(e: CustomEvent) => e.detail && ((this.period = e.detail), this.
|
|
165
|
+
@change=${(e: CustomEvent) => e.detail && ((this.period = e.detail), (this.range = periodRange(e.detail, new Date())))}></ox-input-select-buttons>
|
|
178
166
|
<ox-input-select-buttons
|
|
179
167
|
.value=${this.bucket}
|
|
180
168
|
.options=${[
|
|
@@ -182,7 +170,7 @@ export class AiUsageSettingLet extends localize(i18next)(LitElement) {
|
|
|
182
170
|
{ display: t('by-day', 'Day'), value: 'day' },
|
|
183
171
|
{ display: t('by-month', 'Month'), value: 'month' }
|
|
184
172
|
]}
|
|
185
|
-
@change=${(e: CustomEvent) => e.detail && (
|
|
173
|
+
@change=${(e: CustomEvent) => e.detail && (this.bucket = e.detail)}></ox-input-select-buttons>
|
|
186
174
|
<select aria-label=${t('agent', 'Agent')} @change=${(e: Event) => (this.agentFilter = (e.target as HTMLSelectElement).value)}>
|
|
187
175
|
<option value="">${t('all-agents', 'All agents')}</option>
|
|
188
176
|
${agents.map(([id, name]) => html`<option value=${id} ?selected=${id === this.agentFilter}>${name}</option>`)}
|
|
@@ -192,7 +180,7 @@ export class AiUsageSettingLet extends localize(i18next)(LitElement) {
|
|
|
192
180
|
${users.map(([id, name]) => html`<option value=${id} ?selected=${id === this.userFilter}>${name}</option>`)}
|
|
193
181
|
</select>
|
|
194
182
|
<label>
|
|
195
|
-
<input type="checkbox" .checked=${this.includeDescendants} @change=${(e: Event) => (
|
|
183
|
+
<input type="checkbox" .checked=${this.includeDescendants} @change=${(e: Event) => (this.includeDescendants = (e.target as HTMLInputElement).checked)} />
|
|
196
184
|
${t('include-below', 'Domains below')}
|
|
197
185
|
</label>
|
|
198
186
|
</div>
|
|
@@ -12,16 +12,18 @@ declare const AiAgentSettingLet_base: (new (...args: any[]) => LitElement) & typ
|
|
|
12
12
|
*/
|
|
13
13
|
export declare class AiAgentSettingLet extends AiAgentSettingLet_base {
|
|
14
14
|
static styles: import("lit").CSSResult[];
|
|
15
|
-
private settings?;
|
|
16
|
-
private loadFailed?;
|
|
17
15
|
private draft?;
|
|
18
|
-
private
|
|
19
|
-
private saving;
|
|
16
|
+
private modelsAsk?;
|
|
20
17
|
private saveError?;
|
|
21
18
|
private keyFor?;
|
|
22
19
|
private keyDraft;
|
|
23
|
-
|
|
24
|
-
private
|
|
20
|
+
private agents;
|
|
21
|
+
private modelList;
|
|
22
|
+
private saver;
|
|
23
|
+
private get settings();
|
|
24
|
+
private get loadFailed();
|
|
25
|
+
private get models();
|
|
26
|
+
private get saving();
|
|
25
27
|
render(): import("lit-html").TemplateResult<1>;
|
|
26
28
|
private renderContent;
|
|
27
29
|
private renderStatus;
|
|
@@ -38,7 +40,6 @@ export declare class AiAgentSettingLet extends AiAgentSettingLet_base {
|
|
|
38
40
|
private patch;
|
|
39
41
|
/** A provider decides the model list, so changing it empties the model. */
|
|
40
42
|
private onProvider;
|
|
41
|
-
private modelsToken;
|
|
42
43
|
private loadModels;
|
|
43
44
|
private startKeyOverride;
|
|
44
45
|
private clearKeyOverride;
|
|
@@ -4,7 +4,7 @@ import '@things-factory/setting-base/dist-client/layout/settinglet.js';
|
|
|
4
4
|
import gql from 'graphql-tag';
|
|
5
5
|
import { css, html, LitElement, nothing } from 'lit';
|
|
6
6
|
import { customElement, state } from 'lit/decorators.js';
|
|
7
|
-
import {
|
|
7
|
+
import { MutationController, QueryController } from '@operato/graphql';
|
|
8
8
|
import { i18next, localize } from '@operato/i18n';
|
|
9
9
|
import { OxPrompt } from '@operato/popup';
|
|
10
10
|
import '@operato/popup/ox-popup-menu.js';
|
|
@@ -75,10 +75,12 @@ const PROVIDERS = ['openai', 'anthropic', 'gemini'];
|
|
|
75
75
|
let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitElement) {
|
|
76
76
|
constructor() {
|
|
77
77
|
super(...arguments);
|
|
78
|
-
this.models = { state: 'idle', models: [] };
|
|
79
|
-
this.saving = false;
|
|
80
78
|
this.keyDraft = '';
|
|
81
|
-
this.
|
|
79
|
+
/* The agents of this domain and the domains above (ADR-0190). */
|
|
80
|
+
this.agents = new QueryController(this, SETTINGS_QUERY, { fetchPolicy: 'network-only' });
|
|
81
|
+
this.modelList = new QueryController(this, MODELS_QUERY, { variables: () => this.modelsAsk, fetchPolicy: 'network-only' });
|
|
82
|
+
/* A refusal is drawn beside the editor or in a prompt here, so the link does not report it again. */
|
|
83
|
+
this.saver = new MutationController(this, SAVE_MUTATION, { refetch: () => [this.agents], showsError: true });
|
|
82
84
|
}
|
|
83
85
|
static { this.styles = [
|
|
84
86
|
/* The button look comes from the action bar's styles, which also restyle select and text inputs - the form
|
|
@@ -252,19 +254,23 @@ let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitEle
|
|
|
252
254
|
}
|
|
253
255
|
`
|
|
254
256
|
]; }
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
this.load();
|
|
257
|
+
get settings() {
|
|
258
|
+
return this.agents.data?.aiAgentSettings;
|
|
258
259
|
}
|
|
259
|
-
|
|
260
|
-
this.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
260
|
+
get loadFailed() {
|
|
261
|
+
return this.agents.error ? messageOf(this.agents.error) : undefined;
|
|
262
|
+
}
|
|
263
|
+
get models() {
|
|
264
|
+
if (!this.modelsAsk)
|
|
265
|
+
return { state: 'idle', models: [] };
|
|
266
|
+
if (this.modelList.loading || !(this.modelList.data || this.modelList.error))
|
|
267
|
+
return { state: 'loading', models: [] };
|
|
268
|
+
if (this.modelList.error)
|
|
269
|
+
return { state: 'failed', models: [], reason: messageOf(this.modelList.error) };
|
|
270
|
+
return { state: 'ready', models: this.modelList.data.aiProviderModels ?? [] };
|
|
271
|
+
}
|
|
272
|
+
get saving() {
|
|
273
|
+
return this.saver.pending;
|
|
268
274
|
}
|
|
269
275
|
render() {
|
|
270
276
|
return html `
|
|
@@ -279,7 +285,7 @@ let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitEle
|
|
|
279
285
|
return html `
|
|
280
286
|
<div class="head">
|
|
281
287
|
<span class="status off">${t('load-failed', 'Could not read the AI agents.')} ${this.loadFailed}</span>
|
|
282
|
-
<button type="button" @click=${() => this.
|
|
288
|
+
<button type="button" @click=${() => this.agents.refetch()}><md-icon>refresh</md-icon>${t('retry', 'Try again')}</button>
|
|
283
289
|
</div>
|
|
284
290
|
`;
|
|
285
291
|
}
|
|
@@ -496,7 +502,7 @@ let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitEle
|
|
|
496
502
|
startNew() {
|
|
497
503
|
this.saveError = undefined;
|
|
498
504
|
this.draft = draftOf();
|
|
499
|
-
this.
|
|
505
|
+
this.modelsAsk = undefined;
|
|
500
506
|
}
|
|
501
507
|
startEdit(agent) {
|
|
502
508
|
this.saveError = undefined;
|
|
@@ -506,7 +512,7 @@ let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitEle
|
|
|
506
512
|
cancelEdit() {
|
|
507
513
|
this.draft = undefined;
|
|
508
514
|
this.saveError = undefined;
|
|
509
|
-
this.
|
|
515
|
+
this.modelsAsk = undefined;
|
|
510
516
|
}
|
|
511
517
|
patch(change) {
|
|
512
518
|
this.draft = { ...this.draft, ...change };
|
|
@@ -514,41 +520,30 @@ let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitEle
|
|
|
514
520
|
/** A provider decides the model list, so changing it empties the model. */
|
|
515
521
|
onProvider(provider) {
|
|
516
522
|
this.patch({ provider, model: '', organization: provider === 'openai' ? this.draft.organization : '' });
|
|
517
|
-
this.
|
|
523
|
+
this.modelsAsk = undefined;
|
|
518
524
|
this.loadModels();
|
|
519
525
|
}
|
|
520
|
-
|
|
526
|
+
loadModels() {
|
|
521
527
|
const draft = this.draft;
|
|
522
528
|
if (!draft)
|
|
523
529
|
return;
|
|
524
530
|
const stored = this.settings?.agents.find(one => one.id === draft.id && !one.inherited);
|
|
525
531
|
const useStored = !draft.apiKey.trim() && stored?.keyState === 'own' && stored.provider === draft.provider;
|
|
526
532
|
if (!draft.apiKey.trim() && !useStored) {
|
|
527
|
-
this.
|
|
533
|
+
this.modelsAsk = undefined;
|
|
528
534
|
return;
|
|
529
535
|
}
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
if (token !== this.modelsToken)
|
|
544
|
-
return;
|
|
545
|
-
this.models = { state: 'ready', models: answered(response, 'aiProviderModels') ?? [] };
|
|
546
|
-
}
|
|
547
|
-
catch (error) {
|
|
548
|
-
if (token !== this.modelsToken)
|
|
549
|
-
return;
|
|
550
|
-
this.models = { state: 'failed', models: [], reason: messageOf(error) };
|
|
551
|
-
}
|
|
536
|
+
const ask = {
|
|
537
|
+
provider: draft.provider,
|
|
538
|
+
...(draft.apiKey.trim() ? { apiKey: draft.apiKey.trim() } : { agentId: draft.id }),
|
|
539
|
+
...(draft.baseURL.trim() && { baseURL: draft.baseURL.trim() }),
|
|
540
|
+
...(draft.organization.trim() && { organization: draft.organization.trim() })
|
|
541
|
+
};
|
|
542
|
+
/* The same ask again (the reload button) reads the list again. */
|
|
543
|
+
if (JSON.stringify(ask) === JSON.stringify(this.modelsAsk))
|
|
544
|
+
this.modelList.refetch();
|
|
545
|
+
else
|
|
546
|
+
this.modelsAsk = ask;
|
|
552
547
|
}
|
|
553
548
|
startKeyOverride(agent) {
|
|
554
549
|
this.saveError = undefined;
|
|
@@ -589,36 +584,22 @@ let AiAgentSettingLet = class AiAgentSettingLet extends localize(i18next)(LitEle
|
|
|
589
584
|
});
|
|
590
585
|
}
|
|
591
586
|
async save(change) {
|
|
592
|
-
this.saving = true;
|
|
593
587
|
this.saveError = undefined;
|
|
594
|
-
|
|
595
|
-
answered(await client.mutate({ mutation: SAVE_MUTATION, variables: { input: saveInput(this.settings, change) } }), 'saveAiAgents');
|
|
588
|
+
if (await this.saver.run({ input: saveInput(this.settings, change) })) {
|
|
596
589
|
if (change.kind === 'upsert')
|
|
597
590
|
this.cancelEdit();
|
|
598
591
|
if (change.kind === 'key-override')
|
|
599
592
|
((this.keyFor = undefined), (this.keyDraft = ''));
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
catch (error) {
|
|
603
|
-
this.saveError = messageOf(error);
|
|
604
|
-
if (change.kind !== 'upsert' && change.kind !== 'key-override') {
|
|
605
|
-
await OxPrompt.open({ type: 'error', title: t('save-failed', 'Not saved'), text: this.saveError, confirmButton: { text: t('close', 'Close') } });
|
|
606
|
-
await this.load();
|
|
607
|
-
}
|
|
593
|
+
return;
|
|
608
594
|
}
|
|
609
|
-
|
|
610
|
-
|
|
595
|
+
this.saveError = messageOf(this.saver.error);
|
|
596
|
+
if (change.kind !== 'upsert' && change.kind !== 'key-override') {
|
|
597
|
+
await OxPrompt.open({ type: 'error', title: t('save-failed', 'Not saved'), text: this.saveError, confirmButton: { text: t('close', 'Close') } });
|
|
598
|
+
/* The switch flipped on screen goes back to what is stored. */
|
|
599
|
+
await this.agents.refetch();
|
|
611
600
|
}
|
|
612
601
|
}
|
|
613
602
|
};
|
|
614
|
-
__decorate([
|
|
615
|
-
state(),
|
|
616
|
-
__metadata("design:type", Object)
|
|
617
|
-
], AiAgentSettingLet.prototype, "settings", void 0);
|
|
618
|
-
__decorate([
|
|
619
|
-
state(),
|
|
620
|
-
__metadata("design:type", String)
|
|
621
|
-
], AiAgentSettingLet.prototype, "loadFailed", void 0);
|
|
622
603
|
__decorate([
|
|
623
604
|
state(),
|
|
624
605
|
__metadata("design:type", Object)
|
|
@@ -626,11 +607,7 @@ __decorate([
|
|
|
626
607
|
__decorate([
|
|
627
608
|
state(),
|
|
628
609
|
__metadata("design:type", Object)
|
|
629
|
-
], AiAgentSettingLet.prototype, "
|
|
630
|
-
__decorate([
|
|
631
|
-
state(),
|
|
632
|
-
__metadata("design:type", Object)
|
|
633
|
-
], AiAgentSettingLet.prototype, "saving", void 0);
|
|
610
|
+
], AiAgentSettingLet.prototype, "modelsAsk", void 0);
|
|
634
611
|
__decorate([
|
|
635
612
|
state(),
|
|
636
613
|
__metadata("design:type", String)
|
|
@@ -647,15 +624,6 @@ AiAgentSettingLet = __decorate([
|
|
|
647
624
|
customElement('ai-agent-setting-let')
|
|
648
625
|
], AiAgentSettingLet);
|
|
649
626
|
export { AiAgentSettingLet };
|
|
650
|
-
/**
|
|
651
|
-
* The data of a query or mutation. This client answers a refusal in `errors` (errorPolicy 'all') instead of
|
|
652
|
-
* throwing, so it is turned into a throw here - the server's sentence, already in the person's language.
|
|
653
|
-
*/
|
|
654
|
-
function answered(result, field) {
|
|
655
|
-
if (result?.errors?.length)
|
|
656
|
-
throw new Error(result.errors[0].message);
|
|
657
|
-
return result?.data?.[field];
|
|
658
|
-
}
|
|
659
627
|
async function confirm(title, text) {
|
|
660
628
|
return !!(await OxPrompt.open({
|
|
661
629
|
type: 'warning',
|