@promptbook/cli 0.112.0-111 → 0.112.0-112
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/apps/agents-server/src/app/admin/servers/CreateServerDialog.tsx +16 -0
- package/apps/agents-server/src/app/admin/servers/useCreateServerWizard.ts +31 -5
- package/apps/agents-server/src/app/api/admin/servers/route.ts +5 -0
- package/apps/agents-server/src/app/api/metadata/route.ts +4 -0
- package/apps/agents-server/src/database/customJavascript.ts +62 -1
- package/apps/agents-server/src/database/customStylesheet.ts +60 -1
- package/apps/agents-server/src/database/getMetadata.ts +84 -3
- package/apps/agents-server/src/instrumentation.ts +3 -0
- package/apps/agents-server/src/utils/errorReporting/registerServerErrorSentryLogging.ts +331 -0
- package/apps/agents-server/src/utils/errorReporting/sendApplicationErrorReportToSentry.ts +8 -153
- package/apps/agents-server/src/utils/errorReporting/sentryStore.ts +177 -0
- package/apps/agents-server/src/utils/serverManagement/createManagedServer/bootstrapManagedServer.ts +3 -1
- package/apps/agents-server/src/utils/serverManagement/createManagedServer/normalizeCreateServerInput.ts +6 -0
- package/apps/agents-server/src/utils/serverManagement/createManagedServer/seedServerDefaultAgents.ts +7 -3
- package/apps/agents-server/src/utils/serverManagement/createManagedServer.ts +5 -0
- package/apps/agents-server/src/utils/userChat/listUserChats.ts +109 -0
- package/esm/index.es.js +23 -4
- package/esm/index.es.js.map +1 -1
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +2 -1
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/cli/cli-commands/agents-server/startAgentsServer.ts +17 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +724 -878
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +23 -4
- package/umd/index.umd.js.map +1 -1
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +2 -1
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -203,6 +203,22 @@ function CreateServerForm(props: {
|
|
|
203
203
|
) : null}
|
|
204
204
|
</div>
|
|
205
205
|
|
|
206
|
+
<div className="rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm text-gray-600">
|
|
207
|
+
<label htmlFor="create-server-default-agents" className="flex items-start gap-3">
|
|
208
|
+
<input
|
|
209
|
+
id="create-server-default-agents"
|
|
210
|
+
type="checkbox"
|
|
211
|
+
checked={wizardState.isDefaultAgentsInstalled}
|
|
212
|
+
onChange={(event) => updateWizardField('isDefaultAgentsInstalled', event.target.checked)}
|
|
213
|
+
className="mt-0.5 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
214
|
+
/>
|
|
215
|
+
<span>
|
|
216
|
+
<span className="block font-semibold text-gray-900">Install default agents</span>
|
|
217
|
+
<span className="mt-1 block">Create bundled starter agents from agents/default.</span>
|
|
218
|
+
</span>
|
|
219
|
+
</label>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
206
222
|
<div className="rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm text-gray-600">
|
|
207
223
|
<p className="font-semibold text-gray-900">Admin user exists</p>
|
|
208
224
|
<p className="mt-1">
|
|
@@ -121,6 +121,11 @@ export type CreateServerWizardState = {
|
|
|
121
121
|
*/
|
|
122
122
|
additionalUsers: WizardUser[];
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Whether bundled default agents should be installed during server creation.
|
|
126
|
+
*/
|
|
127
|
+
isDefaultAgentsInstalled: boolean;
|
|
128
|
+
|
|
124
129
|
/**
|
|
125
130
|
* Initial metadata values.
|
|
126
131
|
*/
|
|
@@ -155,7 +160,10 @@ export type CreateServerWizardError = {
|
|
|
155
160
|
* @private function of <ServersClient/>
|
|
156
161
|
*/
|
|
157
162
|
export type UpdateCreateServerWizardField = <
|
|
158
|
-
TFieldName extends keyof Pick<
|
|
163
|
+
TFieldName extends keyof Pick<
|
|
164
|
+
CreateServerWizardState,
|
|
165
|
+
'name' | 'domain' | 'iconUrl' | 'isDefaultAgentsInstalled'
|
|
166
|
+
>,
|
|
159
167
|
>(
|
|
160
168
|
fieldName: TFieldName,
|
|
161
169
|
value: CreateServerWizardState[TFieldName],
|
|
@@ -262,6 +270,7 @@ function createInitialWizardState(): CreateServerWizardState {
|
|
|
262
270
|
password: '',
|
|
263
271
|
},
|
|
264
272
|
additionalUsers: [],
|
|
273
|
+
isDefaultAgentsInstalled: true,
|
|
265
274
|
initialSettings: {
|
|
266
275
|
language: 'en',
|
|
267
276
|
homepageMessage: '',
|
|
@@ -345,7 +354,8 @@ function hasCreateServerWizardChanges(wizardState: CreateServerWizardState): boo
|
|
|
345
354
|
wizardState.name !== initialWizardState.name ||
|
|
346
355
|
wizardState.identifier !== initialWizardState.identifier ||
|
|
347
356
|
wizardState.domain !== initialWizardState.domain ||
|
|
348
|
-
wizardState.iconUrl !== initialWizardState.iconUrl
|
|
357
|
+
wizardState.iconUrl !== initialWizardState.iconUrl ||
|
|
358
|
+
wizardState.isDefaultAgentsInstalled !== initialWizardState.isDefaultAgentsInstalled
|
|
349
359
|
);
|
|
350
360
|
}
|
|
351
361
|
|
|
@@ -402,16 +412,32 @@ export function useCreateServerWizard(options: UseCreateServerWizardOptions): Us
|
|
|
402
412
|
const updateWizardField = useCallback<UpdateCreateServerWizardField>((fieldName, value) => {
|
|
403
413
|
setWizardState((previous) => {
|
|
404
414
|
if (fieldName === 'name') {
|
|
415
|
+
const name = value as CreateServerWizardState['name'];
|
|
416
|
+
|
|
417
|
+
return {
|
|
418
|
+
...previous,
|
|
419
|
+
name,
|
|
420
|
+
identifier: createServerIdentifierFromName(name),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (fieldName === 'domain') {
|
|
425
|
+
return {
|
|
426
|
+
...previous,
|
|
427
|
+
domain: value as CreateServerWizardState['domain'],
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (fieldName === 'iconUrl') {
|
|
405
432
|
return {
|
|
406
433
|
...previous,
|
|
407
|
-
|
|
408
|
-
identifier: createServerIdentifierFromName(value),
|
|
434
|
+
iconUrl: value as CreateServerWizardState['iconUrl'],
|
|
409
435
|
};
|
|
410
436
|
}
|
|
411
437
|
|
|
412
438
|
return {
|
|
413
439
|
...previous,
|
|
414
|
-
|
|
440
|
+
isDefaultAgentsInstalled: value as CreateServerWizardState['isDefaultAgentsInstalled'],
|
|
415
441
|
};
|
|
416
442
|
});
|
|
417
443
|
}, []);
|
|
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server';
|
|
|
2
2
|
import { spaceTrim } from 'spacetrim';
|
|
3
3
|
import { DatabaseError } from '../../../../../../../src/errors/DatabaseError';
|
|
4
4
|
import { isAgentsServerSqliteMode } from '../../../../database/agentsServerDatabaseMode';
|
|
5
|
+
import { seedDefaultAgents } from '../../../../database/seedDefaultAgents';
|
|
5
6
|
import { resolveCurrentServerRegistryContext } from '../../../../utils/currentServerRegistryContext';
|
|
6
7
|
import { isUserAdmin } from '../../../../utils/isUserAdmin';
|
|
7
8
|
import { isUserGlobalAdmin } from '../../../../utils/isUserGlobalAdmin';
|
|
@@ -97,6 +98,7 @@ export async function POST(request: Request) {
|
|
|
97
98
|
|
|
98
99
|
const body = withEnvironmentAdminUser((await request.json()) as CreateServerInput);
|
|
99
100
|
if (isAgentsServerSqliteMode()) {
|
|
101
|
+
const isDefaultAgentsInstalled = body.isDefaultAgentsInstalled !== false;
|
|
100
102
|
const normalizedDomain = normalizeServerDomain(body.domain);
|
|
101
103
|
if (!normalizedDomain) {
|
|
102
104
|
return NextResponse.json({ error: 'A valid domain is required.' }, { status: 400 });
|
|
@@ -114,6 +116,9 @@ export async function POST(request: Request) {
|
|
|
114
116
|
iconUrl: body.iconUrl,
|
|
115
117
|
});
|
|
116
118
|
}
|
|
119
|
+
if (isDefaultAgentsInstalled) {
|
|
120
|
+
await seedDefaultAgents({ tablePrefix });
|
|
121
|
+
}
|
|
117
122
|
|
|
118
123
|
return NextResponse.json(
|
|
119
124
|
{
|
|
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import { keepUnused } from '../../../../../../src/utils/organization/keepUnused';
|
|
3
3
|
import { $getTableName } from '../../../database/$getTableName';
|
|
4
4
|
import { $provideSupabase } from '../../../database/$provideSupabase';
|
|
5
|
+
import { invalidateMetadataCache } from '../../../database/getMetadata';
|
|
5
6
|
import { validateMetadataValue } from '../../../database/metadataDefaults';
|
|
6
7
|
import { isUserAdmin } from '../../../utils/isUserAdmin';
|
|
7
8
|
|
|
@@ -121,6 +122,7 @@ export async function POST(request: NextRequest) {
|
|
|
121
122
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
122
123
|
}
|
|
123
124
|
|
|
125
|
+
invalidateMetadataCache();
|
|
124
126
|
return NextResponse.json(data);
|
|
125
127
|
}
|
|
126
128
|
|
|
@@ -152,6 +154,7 @@ export async function PUT(request: NextRequest) {
|
|
|
152
154
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
153
155
|
}
|
|
154
156
|
|
|
157
|
+
invalidateMetadataCache();
|
|
155
158
|
return NextResponse.json(data);
|
|
156
159
|
}
|
|
157
160
|
|
|
@@ -179,5 +182,6 @@ export async function DELETE(request: NextRequest) {
|
|
|
179
182
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
180
183
|
}
|
|
181
184
|
|
|
185
|
+
invalidateMetadataCache();
|
|
182
186
|
return NextResponse.json({ success: true });
|
|
183
187
|
}
|
|
@@ -14,6 +14,13 @@ export const MAX_CUSTOM_JAVASCRIPT_LENGTH = 100_000;
|
|
|
14
14
|
*/
|
|
15
15
|
const CUSTOM_JAVASCRIPT_TABLE_BASENAME = 'CustomJavascript';
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Process-level cache lifetime for custom JavaScript rows.
|
|
19
|
+
*
|
|
20
|
+
* @private
|
|
21
|
+
*/
|
|
22
|
+
const CUSTOM_JAVASCRIPT_CACHE_TTL_MS = 30_000;
|
|
23
|
+
|
|
17
24
|
/**
|
|
18
25
|
* Stored `CustomJavascript` row shape.
|
|
19
26
|
*
|
|
@@ -90,6 +97,28 @@ type DynamicSupabaseClient = {
|
|
|
90
97
|
from: (tableName: string) => DynamicCustomJavascriptTableQuery;
|
|
91
98
|
};
|
|
92
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Cached custom JavaScript rows keyed by the resolved table name.
|
|
102
|
+
*
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
const cachedCustomJavascriptByTableName = new Map<
|
|
106
|
+
string,
|
|
107
|
+
{
|
|
108
|
+
readonly loadedAt: number;
|
|
109
|
+
readonly rowsPromise: Promise<CustomJavascriptRow[]>;
|
|
110
|
+
}
|
|
111
|
+
>();
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Clears process-level custom JavaScript cache after admin writes.
|
|
115
|
+
*
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
118
|
+
export function invalidateCustomJavascriptCache(): void {
|
|
119
|
+
cachedCustomJavascriptByTableName.clear();
|
|
120
|
+
}
|
|
121
|
+
|
|
93
122
|
/**
|
|
94
123
|
* Resolves the prefixed table name for `CustomJavascript`.
|
|
95
124
|
*
|
|
@@ -137,8 +166,37 @@ function getCustomJavascriptClient() {
|
|
|
137
166
|
*/
|
|
138
167
|
export async function getCustomJavascriptFiles(): Promise<CustomJavascriptRow[]> {
|
|
139
168
|
const table = await getCustomJavascriptTableName();
|
|
140
|
-
const
|
|
169
|
+
const cachedJavascript = cachedCustomJavascriptByTableName.get(table);
|
|
170
|
+
if (cachedJavascript && Date.now() - cachedJavascript.loadedAt < CUSTOM_JAVASCRIPT_CACHE_TTL_MS) {
|
|
171
|
+
return cachedJavascript.rowsPromise;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const rowsPromise = loadCustomJavascriptFilesFromDatabase(table);
|
|
175
|
+
cachedCustomJavascriptByTableName.set(table, {
|
|
176
|
+
loadedAt: Date.now(),
|
|
177
|
+
rowsPromise,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
return await rowsPromise;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (cachedCustomJavascriptByTableName.get(table)?.rowsPromise === rowsPromise) {
|
|
184
|
+
cachedCustomJavascriptByTableName.delete(table);
|
|
185
|
+
}
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
141
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Reads custom JavaScript rows from the database.
|
|
192
|
+
*
|
|
193
|
+
* @param table - Resolved CustomJavascript table name.
|
|
194
|
+
* @returns Stored JavaScript rows.
|
|
195
|
+
*
|
|
196
|
+
* @private
|
|
197
|
+
*/
|
|
198
|
+
async function loadCustomJavascriptFilesFromDatabase(table: string): Promise<CustomJavascriptRow[]> {
|
|
199
|
+
const supabase = getCustomJavascriptClient();
|
|
142
200
|
const { data, error } = await supabase.from(table).select('*').order('scope', { ascending: true });
|
|
143
201
|
|
|
144
202
|
if (error) {
|
|
@@ -234,6 +292,7 @@ export async function saveCustomJavascriptFile({
|
|
|
234
292
|
throw new Error(`Failed to save custom JavaScript: ${error.message || String(error)}`);
|
|
235
293
|
}
|
|
236
294
|
|
|
295
|
+
invalidateCustomJavascriptCache();
|
|
237
296
|
return data as CustomJavascriptRow;
|
|
238
297
|
}
|
|
239
298
|
|
|
@@ -255,4 +314,6 @@ export async function deleteCustomJavascriptFile(id: number): Promise<void> {
|
|
|
255
314
|
|
|
256
315
|
throw new Error(`Failed to delete custom JavaScript: ${error.message || String(error)}`);
|
|
257
316
|
}
|
|
317
|
+
|
|
318
|
+
invalidateCustomJavascriptCache();
|
|
258
319
|
}
|
|
@@ -7,6 +7,11 @@ import { $provideSupabase } from './$provideSupabase';
|
|
|
7
7
|
*/
|
|
8
8
|
const CUSTOM_STYLESHEET_TABLE_BASENAME = 'CustomStylesheet';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Process-level cache lifetime for custom stylesheet rows.
|
|
12
|
+
*/
|
|
13
|
+
const CUSTOM_STYLESHEET_CACHE_TTL_MS = 30_000;
|
|
14
|
+
|
|
10
15
|
/**
|
|
11
16
|
* Stored CustomStylesheet row shape.
|
|
12
17
|
*
|
|
@@ -82,6 +87,28 @@ type DynamicSupabaseClient = {
|
|
|
82
87
|
from: (tableName: string) => DynamicCustomStylesheetTableQuery;
|
|
83
88
|
};
|
|
84
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Cached custom stylesheet rows keyed by the resolved table name.
|
|
92
|
+
*
|
|
93
|
+
* @private
|
|
94
|
+
*/
|
|
95
|
+
const cachedCustomStylesheetsByTableName = new Map<
|
|
96
|
+
string,
|
|
97
|
+
{
|
|
98
|
+
readonly loadedAt: number;
|
|
99
|
+
readonly rowsPromise: Promise<CustomStylesheetRow[]>;
|
|
100
|
+
}
|
|
101
|
+
>();
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Clears process-level stylesheet cache after admin writes.
|
|
105
|
+
*
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
export function invalidateCustomStylesheetCache(): void {
|
|
109
|
+
cachedCustomStylesheetsByTableName.clear();
|
|
110
|
+
}
|
|
111
|
+
|
|
85
112
|
/**
|
|
86
113
|
* Resolves the prefixed table name for CustomStylesheet.
|
|
87
114
|
*
|
|
@@ -127,8 +154,37 @@ function getCustomStylesheetClient(): DynamicSupabaseClient {
|
|
|
127
154
|
*/
|
|
128
155
|
export async function listCustomStylesheets(): Promise<CustomStylesheetRow[]> {
|
|
129
156
|
const table = await getCustomStylesheetTableName();
|
|
130
|
-
const
|
|
157
|
+
const cachedStylesheets = cachedCustomStylesheetsByTableName.get(table);
|
|
158
|
+
if (cachedStylesheets && Date.now() - cachedStylesheets.loadedAt < CUSTOM_STYLESHEET_CACHE_TTL_MS) {
|
|
159
|
+
return cachedStylesheets.rowsPromise;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const rowsPromise = loadCustomStylesheetsFromDatabase(table);
|
|
163
|
+
cachedCustomStylesheetsByTableName.set(table, {
|
|
164
|
+
loadedAt: Date.now(),
|
|
165
|
+
rowsPromise,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
return await rowsPromise;
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (cachedCustomStylesheetsByTableName.get(table)?.rowsPromise === rowsPromise) {
|
|
172
|
+
cachedCustomStylesheetsByTableName.delete(table);
|
|
173
|
+
}
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
131
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Reads custom stylesheet rows from the database.
|
|
180
|
+
*
|
|
181
|
+
* @param table - Resolved CustomStylesheet table name.
|
|
182
|
+
* @returns Stored stylesheet rows.
|
|
183
|
+
*
|
|
184
|
+
* @private
|
|
185
|
+
*/
|
|
186
|
+
async function loadCustomStylesheetsFromDatabase(table: string): Promise<CustomStylesheetRow[]> {
|
|
187
|
+
const supabase = getCustomStylesheetClient();
|
|
132
188
|
const { data, error } = await supabase.from(table).select('*').order('createdAt', { ascending: true });
|
|
133
189
|
|
|
134
190
|
if (error) {
|
|
@@ -206,6 +262,7 @@ export async function saveCustomStylesheetFile({
|
|
|
206
262
|
throw new Error(`Failed to save custom stylesheet: ${error.message || String(error)}`);
|
|
207
263
|
}
|
|
208
264
|
|
|
265
|
+
invalidateCustomStylesheetCache();
|
|
209
266
|
return data as CustomStylesheetRow;
|
|
210
267
|
}
|
|
211
268
|
|
|
@@ -229,4 +286,6 @@ export async function deleteCustomStylesheetFile(id: number): Promise<void> {
|
|
|
229
286
|
|
|
230
287
|
throw new Error(`Failed to delete custom stylesheet: ${error.message || String(error)}`);
|
|
231
288
|
}
|
|
289
|
+
|
|
290
|
+
invalidateCustomStylesheetCache();
|
|
232
291
|
}
|
|
@@ -10,6 +10,45 @@ import { cache } from 'react';
|
|
|
10
10
|
*/
|
|
11
11
|
const metadataDefaultsMap = new Map<string, string>(metadataDefaults.map((metadata) => [metadata.key, metadata.value]));
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Process-level cache lifetime for metadata reads.
|
|
15
|
+
*
|
|
16
|
+
* @private Internal helper for metadata lookups in `apps/agents-server`.
|
|
17
|
+
*/
|
|
18
|
+
const METADATA_CACHE_TTL_MS = 30_000;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Cached metadata table payload keyed by the resolved table name.
|
|
22
|
+
*
|
|
23
|
+
* @private Internal helper for metadata lookups in `apps/agents-server`.
|
|
24
|
+
*/
|
|
25
|
+
const cachedMetadataValuesByTableName = new Map<
|
|
26
|
+
string,
|
|
27
|
+
{
|
|
28
|
+
readonly loadedAt: number;
|
|
29
|
+
readonly valuesPromise: Promise<Map<string, string | null>>;
|
|
30
|
+
}
|
|
31
|
+
>();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Metadata row shape loaded by the lightweight metadata select.
|
|
35
|
+
*
|
|
36
|
+
* @private Internal helper for metadata lookups in `apps/agents-server`.
|
|
37
|
+
*/
|
|
38
|
+
type MetadataValueRow = {
|
|
39
|
+
readonly key: string;
|
|
40
|
+
readonly value: string | null;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Clears process-level metadata cache after admin metadata writes.
|
|
45
|
+
*
|
|
46
|
+
* @public exported from `apps/agents-server`
|
|
47
|
+
*/
|
|
48
|
+
export function invalidateMetadataCache(): void {
|
|
49
|
+
cachedMetadataValuesByTableName.clear();
|
|
50
|
+
}
|
|
51
|
+
|
|
13
52
|
/**
|
|
14
53
|
* Loads the full metadata table once per request so callers can cheaply project subsets.
|
|
15
54
|
*
|
|
@@ -18,17 +57,59 @@ const metadataDefaultsMap = new Map<string, string>(metadataDefaults.map((metada
|
|
|
18
57
|
* @private Internal helper for batched metadata lookups in `apps/agents-server`.
|
|
19
58
|
*/
|
|
20
59
|
const loadAllMetadataValues = cache(async (): Promise<Map<string, string | null>> => {
|
|
21
|
-
const supabase = $provideSupabase();
|
|
22
60
|
const table = await $getTableName('Metadata');
|
|
61
|
+
return loadCachedMetadataValues(table);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Loads metadata values using a short process-level cache shared by consecutive requests.
|
|
66
|
+
*
|
|
67
|
+
* @param table - Resolved metadata table name.
|
|
68
|
+
* @returns Metadata values keyed by metadata key.
|
|
69
|
+
*
|
|
70
|
+
* @private Internal helper for metadata lookups in `apps/agents-server`.
|
|
71
|
+
*/
|
|
72
|
+
async function loadCachedMetadataValues(table: string): Promise<Map<string, string | null>> {
|
|
73
|
+
const cachedMetadataValues = cachedMetadataValuesByTableName.get(table);
|
|
74
|
+
if (cachedMetadataValues && Date.now() - cachedMetadataValues.loadedAt < METADATA_CACHE_TTL_MS) {
|
|
75
|
+
return cachedMetadataValues.valuesPromise;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const valuesPromise = loadMetadataValuesFromDatabase(table);
|
|
79
|
+
cachedMetadataValuesByTableName.set(table, {
|
|
80
|
+
loadedAt: Date.now(),
|
|
81
|
+
valuesPromise,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
return await valuesPromise;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (cachedMetadataValuesByTableName.get(table)?.valuesPromise === valuesPromise) {
|
|
88
|
+
cachedMetadataValuesByTableName.delete(table);
|
|
89
|
+
}
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Reads all persisted metadata values from the database.
|
|
96
|
+
*
|
|
97
|
+
* @param table - Resolved metadata table name.
|
|
98
|
+
* @returns Metadata values keyed by metadata key.
|
|
99
|
+
*
|
|
100
|
+
* @private Internal helper for metadata lookups in `apps/agents-server`.
|
|
101
|
+
*/
|
|
102
|
+
async function loadMetadataValuesFromDatabase(table: string): Promise<Map<string, string | null>> {
|
|
103
|
+
const supabase = $provideSupabase();
|
|
23
104
|
const { data } = await supabase.from(table).select('key, value');
|
|
24
105
|
|
|
25
106
|
const loadedMap = new Map<string, string | null>();
|
|
26
|
-
for (const row of data ?? []) {
|
|
107
|
+
for (const row of (data ?? []) as Array<MetadataValueRow>) {
|
|
27
108
|
loadedMap.set(row.key, row.value);
|
|
28
109
|
}
|
|
29
110
|
|
|
30
111
|
return loadedMap;
|
|
31
|
-
}
|
|
112
|
+
}
|
|
32
113
|
|
|
33
114
|
/**
|
|
34
115
|
* Get metadata value by key
|
|
@@ -10,6 +10,9 @@ export async function register(): Promise<void> {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
|
+
const { registerServerErrorSentryLogging } = await import('./utils/errorReporting/registerServerErrorSentryLogging');
|
|
14
|
+
registerServerErrorSentryLogging();
|
|
15
|
+
|
|
13
16
|
const { registerNodeRuntimeInstrumentation } = await import('./instrumentation-node');
|
|
14
17
|
await registerNodeRuntimeInstrumentation();
|
|
15
18
|
} catch (error) {
|