@promptbook/cli 0.112.0-135 → 0.112.0-137
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/README.md +20 -0
- package/apps/agents-server/README.md +0 -1
- package/apps/agents-server/src/app/admin/metadata/MetadataClient.tsx +246 -15
- package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +237 -4
- package/apps/agents-server/src/app/api/admin/update/log/route.ts +42 -0
- package/apps/agents-server/src/app/api/agents/export/route.ts +41 -0
- package/apps/agents-server/src/app/api/agents/import/route.ts +168 -0
- package/apps/agents-server/src/app/api/federated-agents/route.ts +1 -1
- package/apps/agents-server/src/app/api/internal/agent-runner-limits/route.ts +2 -1
- package/apps/agents-server/src/app/api/internal/user-chat-jobs/run/route.ts +2 -1
- package/apps/agents-server/src/app/api/metadata/export/route.ts +34 -0
- package/apps/agents-server/src/app/api/metadata/import/route.ts +46 -0
- package/apps/agents-server/src/app/layout.tsx +1 -1
- package/apps/agents-server/src/components/Homepage/AgentsList.tsx +31 -1
- package/apps/agents-server/src/components/Homepage/AgentsListHeader.tsx +60 -1
- package/apps/agents-server/src/components/Homepage/useAgentsListImportExportState.ts +523 -0
- package/apps/agents-server/src/components/Homepage/useAgentsListState.ts +16 -0
- package/apps/agents-server/src/database/metadataDefaults.ts +0 -21
- package/apps/agents-server/src/database/seedCoreAgents.ts +235 -0
- package/apps/agents-server/src/database/seedDefaultAgents.ts +32 -1
- package/apps/agents-server/src/search/createDefaultServerSearchProviders/createFederatedAgentsSearchProvider.ts +1 -1
- package/apps/agents-server/src/tools/$provideAgentCollectionForServer.ts +2 -9
- package/apps/agents-server/src/utils/agentsTransfer/createAgentsExportZipStream.ts +68 -0
- package/apps/agents-server/src/utils/agentsTransfer/importAgentsFromFiles.ts +852 -0
- package/apps/agents-server/src/utils/backup/createBooksBackupZipStream.ts +15 -2
- package/apps/agents-server/src/utils/defaultAgents/loadDefaultAgentBooks.ts +46 -4
- package/apps/agents-server/src/utils/getFederatedServers.ts +3 -74
- package/apps/agents-server/src/utils/getWellKnownAgentUrl.ts +10 -4
- package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
- package/apps/agents-server/src/utils/metadataConfigurationTransfer.ts +426 -0
- package/apps/agents-server/src/utils/serverManagement/createManagedServer/bootstrapManagedServer.ts +2 -5
- package/apps/agents-server/src/utils/serverManagement/createManagedServer/seedServerCoreAgents.ts +162 -0
- package/apps/agents-server/src/utils/session.ts +2 -1
- package/apps/agents-server/src/utils/vpsSelfUpdate.ts +110 -0
- package/esm/index.es.js +1 -1
- package/esm/index.es.js.map +1 -1
- package/esm/src/_packages/core.index.d.ts +0 -2
- package/esm/src/utils/isTimingSafeEqualString.d.ts +25 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/servers.ts +1 -16
- package/src/_packages/core.index.ts +0 -2
- package/src/commitments/_common/teamInternalAgentAccess.ts +2 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +789 -716
- package/src/utils/isTimingSafeEqualString.ts +43 -0
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +1 -1
- package/umd/index.umd.js.map +1 -1
- package/umd/src/_packages/core.index.d.ts +0 -2
- package/umd/src/utils/isTimingSafeEqualString.d.ts +25 -0
- package/umd/src/version.d.ts +1 -1
- package/apps/agents-server/src/utils/defaultFederatedAgents/DefaultFederatedAgentsSyncOptions.ts +0 -9
- package/apps/agents-server/src/utils/defaultFederatedAgents/ensureDefaultFederatedAgentExists.ts +0 -277
- package/apps/agents-server/src/utils/defaultFederatedAgents/fetchCoreOrganizationPayload.ts +0 -39
- package/apps/agents-server/src/utils/defaultFederatedAgents/fetchFederatedAgentBook.ts +0 -43
- package/apps/agents-server/src/utils/defaultFederatedAgents/fetchWithDefaultFederatedAgentTimeout.ts +0 -28
- package/apps/agents-server/src/utils/defaultFederatedAgents/getDefaultFederatedAgentSyncPool.ts +0 -38
- package/apps/agents-server/src/utils/defaultFederatedAgents/loadActiveLocalAgentIdsByNormalizedName.ts +0 -41
- package/apps/agents-server/src/utils/defaultFederatedAgents/loadDefaultFederatedAgentSyncMetadata.ts +0 -76
- package/apps/agents-server/src/utils/defaultFederatedAgents/quoteIdentifier.ts +0 -11
- package/apps/agents-server/src/utils/defaultFederatedAgents/scheduleDefaultFederatedAgentsSync.ts +0 -88
- package/apps/agents-server/src/utils/defaultFederatedAgents/selectDefaultFederatedAgentsFromOrganizationPayload.ts +0 -181
- package/apps/agents-server/src/utils/defaultFederatedAgents/synchronizeDefaultFederatedAgents.ts +0 -77
|
@@ -221,7 +221,6 @@ import { normalizeChatAttachments } from '../utils/chat/chatAttachments/normaliz
|
|
|
221
221
|
import { resolveChatAttachmentContents } from '../utils/chat/chatAttachments/resolveChatAttachmentContents';
|
|
222
222
|
import { aboutPromptbookInformation } from '../utils/misc/aboutPromptbookInformation';
|
|
223
223
|
import { $generateBookBoilerplate } from '../utils/random/$generateBookBoilerplate';
|
|
224
|
-
import { CORE_AGENTS_SERVER } from '../../servers';
|
|
225
224
|
import { CORE_AGENTS_SERVER_WELL_KNOWN_AGENT_NAMES } from '../../servers';
|
|
226
225
|
import { PUBLIC_AGENTS_SERVERS } from '../../servers';
|
|
227
226
|
export { BOOK_LANGUAGE_VERSION, PROMPTBOOK_ENGINE_VERSION };
|
|
@@ -447,6 +446,5 @@ export { normalizeChatAttachments };
|
|
|
447
446
|
export { resolveChatAttachmentContents };
|
|
448
447
|
export { aboutPromptbookInformation };
|
|
449
448
|
export { $generateBookBoilerplate };
|
|
450
|
-
export { CORE_AGENTS_SERVER };
|
|
451
449
|
export { CORE_AGENTS_SERVER_WELL_KNOWN_AGENT_NAMES };
|
|
452
450
|
export { PUBLIC_AGENTS_SERVERS };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two strings in constant time to prevent timing attacks.
|
|
3
|
+
*
|
|
4
|
+
* Plain JavaScript `===` / `!==` string comparisons short-circuit on the first
|
|
5
|
+
* byte that differs, which lets a remote attacker who can measure response
|
|
6
|
+
* timing recover the expected value one byte at a time. This helper performs
|
|
7
|
+
* the comparison through Node's `timingSafeEqual`, which always inspects every
|
|
8
|
+
* byte of the equal-length buffers.
|
|
9
|
+
*
|
|
10
|
+
* Returning `false` early when the byte lengths differ does not expose
|
|
11
|
+
* character content — only length — which is an acceptable trade-off, since
|
|
12
|
+
* `timingSafeEqual` requires equal-length buffers and length is typically not
|
|
13
|
+
* secret.
|
|
14
|
+
*
|
|
15
|
+
* `null` and `undefined` inputs are treated as non-matching so callers can
|
|
16
|
+
* forward raw request values (for example `request.headers.get(name)`) without
|
|
17
|
+
* an extra guard.
|
|
18
|
+
*
|
|
19
|
+
* @param candidate - Value supplied by the caller (for example a request header or cookie).
|
|
20
|
+
* @param expected - Value to compare against (for example a configured secret).
|
|
21
|
+
* @returns `true` when both values are strings of equal length with identical bytes.
|
|
22
|
+
*
|
|
23
|
+
* @private internal helper function
|
|
24
|
+
*/
|
|
25
|
+
export declare function isTimingSafeEqualString(candidate: string | null | undefined, expected: string | null | undefined): boolean;
|
package/umd/src/version.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
|
16
16
|
/**
|
|
17
17
|
* Represents the version string of the Promptbook engine.
|
|
18
|
-
* It follows semantic versioning (e.g., `0.112.0-
|
|
18
|
+
* It follows semantic versioning (e.g., `0.112.0-136`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/apps/agents-server/src/utils/defaultFederatedAgents/DefaultFederatedAgentsSyncOptions.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal context needed to schedule or execute one default federated-agent sync pass.
|
|
3
|
-
*
|
|
4
|
-
* @private shared type for `scheduleDefaultFederatedAgentsSync`
|
|
5
|
-
*/
|
|
6
|
-
export type DefaultFederatedAgentsSyncOptions = {
|
|
7
|
-
readonly tablePrefix: string;
|
|
8
|
-
readonly localServerUrl: string;
|
|
9
|
-
};
|
package/apps/agents-server/src/utils/defaultFederatedAgents/ensureDefaultFederatedAgentExists.ts
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import { type Pool, type PoolClient } from 'pg';
|
|
2
|
-
import { prepareAgentSourceForPersistence } from '../../../../../src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence';
|
|
3
|
-
import type { string_book } from '../../../../../src/book-2.0/agent-source/string_book';
|
|
4
|
-
import { normalizeAgentName } from '../../../../../src/book-2.0/agent-source/normalizeAgentName';
|
|
5
|
-
import { ZERO_USAGE } from '../../../../../src/execution/utils/usage-constants';
|
|
6
|
-
import { $randomBase58 } from '../../../../../src/utils/random/$randomBase58';
|
|
7
|
-
import { PROMPTBOOK_ENGINE_VERSION } from '../../../../../src/version';
|
|
8
|
-
import type { AgentVisibility } from '../agentVisibility';
|
|
9
|
-
import type { DefaultFederatedAgentCandidate } from './selectDefaultFederatedAgentsFromOrganizationPayload';
|
|
10
|
-
import { quoteIdentifier } from './quoteIdentifier';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Table basename storing per-server sync state and locking rows.
|
|
14
|
-
*/
|
|
15
|
-
const DEFAULT_FEDERATED_AGENT_TABLE_BASENAME = 'DefaultFederatedAgent';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Length of generated local permanent ids for cloned default agents.
|
|
19
|
-
*/
|
|
20
|
-
const DEFAULT_FEDERATED_AGENT_PERMANENT_ID_LENGTH = 14;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Ensures one Core default agent exists locally while serializing writes through a DB row lock.
|
|
24
|
-
*
|
|
25
|
-
* @param options - Current sync inputs.
|
|
26
|
-
* @returns Existing or newly created local permanent id.
|
|
27
|
-
*
|
|
28
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
29
|
-
*/
|
|
30
|
-
export async function ensureDefaultFederatedAgentExists(options: {
|
|
31
|
-
readonly pool: Pool;
|
|
32
|
-
readonly tablePrefix: string;
|
|
33
|
-
readonly defaultVisibility: AgentVisibility;
|
|
34
|
-
readonly candidate: DefaultFederatedAgentCandidate;
|
|
35
|
-
readonly remoteAgentSource: string_book;
|
|
36
|
-
}): Promise<string> {
|
|
37
|
-
const client = await options.pool.connect();
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
await client.query('BEGIN');
|
|
41
|
-
await upsertDefaultFederatedAgentSyncRow(client, options.tablePrefix, options.candidate);
|
|
42
|
-
await lockAgentWrites(client, options.tablePrefix);
|
|
43
|
-
|
|
44
|
-
const existingPermanentId = await findActiveLocalPermanentIdByNormalizedName(
|
|
45
|
-
client,
|
|
46
|
-
options.tablePrefix,
|
|
47
|
-
options.candidate.normalizedName,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
if (existingPermanentId) {
|
|
51
|
-
await updateDefaultFederatedAgentLocalPermanentId(
|
|
52
|
-
client,
|
|
53
|
-
options.tablePrefix,
|
|
54
|
-
options.candidate.normalizedName,
|
|
55
|
-
existingPermanentId,
|
|
56
|
-
);
|
|
57
|
-
await client.query('COMMIT');
|
|
58
|
-
return existingPermanentId;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const newPermanentId = await insertClonedDefaultFederatedAgent(client, {
|
|
62
|
-
tablePrefix: options.tablePrefix,
|
|
63
|
-
defaultVisibility: options.defaultVisibility,
|
|
64
|
-
remoteAgentSource: options.remoteAgentSource,
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
await updateDefaultFederatedAgentLocalPermanentId(
|
|
68
|
-
client,
|
|
69
|
-
options.tablePrefix,
|
|
70
|
-
options.candidate.normalizedName,
|
|
71
|
-
newPermanentId,
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
await client.query('COMMIT');
|
|
75
|
-
return newPermanentId;
|
|
76
|
-
} catch (error) {
|
|
77
|
-
try {
|
|
78
|
-
await client.query('ROLLBACK');
|
|
79
|
-
} catch {
|
|
80
|
-
// Keep the original error visible.
|
|
81
|
-
}
|
|
82
|
-
throw error;
|
|
83
|
-
} finally {
|
|
84
|
-
client.release();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Inserts or updates the sync-state row for one normalized default agent name.
|
|
90
|
-
*
|
|
91
|
-
* The `ON CONFLICT ... DO UPDATE` path keeps the row locked for the current transaction.
|
|
92
|
-
*
|
|
93
|
-
* @param client - Transaction-bound PostgreSQL client.
|
|
94
|
-
* @param tablePrefix - Current server table prefix.
|
|
95
|
-
* @param candidate - Candidate being synchronized.
|
|
96
|
-
*/
|
|
97
|
-
async function upsertDefaultFederatedAgentSyncRow(
|
|
98
|
-
client: PoolClient,
|
|
99
|
-
tablePrefix: string,
|
|
100
|
-
candidate: DefaultFederatedAgentCandidate,
|
|
101
|
-
): Promise<void> {
|
|
102
|
-
const syncTableName = quoteIdentifier(`${tablePrefix}${DEFAULT_FEDERATED_AGENT_TABLE_BASENAME}`);
|
|
103
|
-
|
|
104
|
-
await client.query(
|
|
105
|
-
`
|
|
106
|
-
INSERT INTO ${syncTableName} (
|
|
107
|
-
"normalizedName",
|
|
108
|
-
"sourceServerUrl",
|
|
109
|
-
"sourceAgentIdentifier",
|
|
110
|
-
"updatedAt"
|
|
111
|
-
)
|
|
112
|
-
VALUES ($1, $2, $3, now())
|
|
113
|
-
ON CONFLICT ("normalizedName")
|
|
114
|
-
DO UPDATE
|
|
115
|
-
SET
|
|
116
|
-
"sourceServerUrl" = EXCLUDED."sourceServerUrl",
|
|
117
|
-
"sourceAgentIdentifier" = EXCLUDED."sourceAgentIdentifier",
|
|
118
|
-
"updatedAt" = now()
|
|
119
|
-
`,
|
|
120
|
-
[candidate.normalizedName, new URL(candidate.sourceAgentUrl).origin, candidate.sourceAgentIdentifier],
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Blocks concurrent writes to the current server's agent table during the critical recheck/create section.
|
|
126
|
-
*
|
|
127
|
-
* @param client - Transaction-bound PostgreSQL client.
|
|
128
|
-
* @param tablePrefix - Current server table prefix.
|
|
129
|
-
*/
|
|
130
|
-
async function lockAgentWrites(client: PoolClient, tablePrefix: string): Promise<void> {
|
|
131
|
-
const agentTableName = quoteIdentifier(`${tablePrefix}Agent`);
|
|
132
|
-
await client.query(`LOCK TABLE ${agentTableName} IN SHARE ROW EXCLUSIVE MODE`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Finds the oldest active local agent whose normalized name matches the requested value.
|
|
137
|
-
*
|
|
138
|
-
* @param client - Transaction-bound PostgreSQL client.
|
|
139
|
-
* @param tablePrefix - Current server table prefix.
|
|
140
|
-
* @param normalizedName - Stable normalized lookup key.
|
|
141
|
-
* @returns Matching permanent id or `null`.
|
|
142
|
-
*/
|
|
143
|
-
async function findActiveLocalPermanentIdByNormalizedName(
|
|
144
|
-
client: PoolClient,
|
|
145
|
-
tablePrefix: string,
|
|
146
|
-
normalizedName: string,
|
|
147
|
-
): Promise<string | null> {
|
|
148
|
-
const agentTableName = quoteIdentifier(`${tablePrefix}Agent`);
|
|
149
|
-
const result = await client.query<{ agentName: string; permanentId: string | null }>(
|
|
150
|
-
`
|
|
151
|
-
SELECT "agentName", "permanentId"
|
|
152
|
-
FROM ${agentTableName}
|
|
153
|
-
WHERE "deletedAt" IS NULL
|
|
154
|
-
ORDER BY "createdAt" ASC
|
|
155
|
-
`,
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
for (const row of result.rows) {
|
|
159
|
-
if (!row.permanentId) {
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (normalizeAgentName(row.agentName) === normalizedName) {
|
|
164
|
-
return row.permanentId;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Persists a freshly cloned default agent together with its initial history snapshot.
|
|
173
|
-
*
|
|
174
|
-
* @param client - Transaction-bound PostgreSQL client.
|
|
175
|
-
* @param options - Insert inputs.
|
|
176
|
-
* @returns Permanent id of the stored local agent.
|
|
177
|
-
*/
|
|
178
|
-
async function insertClonedDefaultFederatedAgent(
|
|
179
|
-
client: PoolClient,
|
|
180
|
-
options: {
|
|
181
|
-
readonly tablePrefix: string;
|
|
182
|
-
readonly defaultVisibility: AgentVisibility;
|
|
183
|
-
readonly remoteAgentSource: string_book;
|
|
184
|
-
},
|
|
185
|
-
): Promise<string> {
|
|
186
|
-
const preparedAgentSource = prepareAgentSourceForPersistence(options.remoteAgentSource);
|
|
187
|
-
const permanentId = preparedAgentSource.permanentId || $randomBase58(DEFAULT_FEDERATED_AGENT_PERMANENT_ID_LENGTH);
|
|
188
|
-
const createdAt = new Date().toISOString();
|
|
189
|
-
const agentTableName = quoteIdentifier(`${options.tablePrefix}Agent`);
|
|
190
|
-
const agentHistoryTableName = quoteIdentifier(`${options.tablePrefix}AgentHistory`);
|
|
191
|
-
|
|
192
|
-
await client.query(
|
|
193
|
-
`
|
|
194
|
-
INSERT INTO ${agentTableName} (
|
|
195
|
-
"agentName",
|
|
196
|
-
"createdAt",
|
|
197
|
-
"updatedAt",
|
|
198
|
-
"permanentId",
|
|
199
|
-
"agentHash",
|
|
200
|
-
"agentSource",
|
|
201
|
-
"agentProfile",
|
|
202
|
-
"promptbookEngineVersion",
|
|
203
|
-
"usage",
|
|
204
|
-
"visibility"
|
|
205
|
-
)
|
|
206
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9::jsonb, $10)
|
|
207
|
-
`,
|
|
208
|
-
[
|
|
209
|
-
preparedAgentSource.agentProfile.agentName,
|
|
210
|
-
createdAt,
|
|
211
|
-
null,
|
|
212
|
-
permanentId,
|
|
213
|
-
preparedAgentSource.agentProfile.agentHash,
|
|
214
|
-
preparedAgentSource.agentSource,
|
|
215
|
-
JSON.stringify(preparedAgentSource.agentProfile),
|
|
216
|
-
PROMPTBOOK_ENGINE_VERSION,
|
|
217
|
-
JSON.stringify(ZERO_USAGE),
|
|
218
|
-
options.defaultVisibility,
|
|
219
|
-
],
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
await client.query(
|
|
223
|
-
`
|
|
224
|
-
INSERT INTO ${agentHistoryTableName} (
|
|
225
|
-
"createdAt",
|
|
226
|
-
"agentName",
|
|
227
|
-
"permanentId",
|
|
228
|
-
"agentHash",
|
|
229
|
-
"previousAgentHash",
|
|
230
|
-
"agentSource",
|
|
231
|
-
"promptbookEngineVersion",
|
|
232
|
-
"versionName"
|
|
233
|
-
)
|
|
234
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
235
|
-
`,
|
|
236
|
-
[
|
|
237
|
-
createdAt,
|
|
238
|
-
preparedAgentSource.agentProfile.agentName,
|
|
239
|
-
permanentId,
|
|
240
|
-
preparedAgentSource.agentProfile.agentHash,
|
|
241
|
-
null,
|
|
242
|
-
preparedAgentSource.agentSource,
|
|
243
|
-
PROMPTBOOK_ENGINE_VERSION,
|
|
244
|
-
null,
|
|
245
|
-
],
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
return permanentId;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Stores the resolved local permanent id back into the sync-state table.
|
|
253
|
-
*
|
|
254
|
-
* @param client - Transaction-bound PostgreSQL client.
|
|
255
|
-
* @param tablePrefix - Current server table prefix.
|
|
256
|
-
* @param normalizedName - Stable normalized lookup key.
|
|
257
|
-
* @param localPermanentId - Local permanent id to store.
|
|
258
|
-
*/
|
|
259
|
-
async function updateDefaultFederatedAgentLocalPermanentId(
|
|
260
|
-
client: PoolClient,
|
|
261
|
-
tablePrefix: string,
|
|
262
|
-
normalizedName: string,
|
|
263
|
-
localPermanentId: string,
|
|
264
|
-
): Promise<void> {
|
|
265
|
-
const syncTableName = quoteIdentifier(`${tablePrefix}${DEFAULT_FEDERATED_AGENT_TABLE_BASENAME}`);
|
|
266
|
-
|
|
267
|
-
await client.query(
|
|
268
|
-
`
|
|
269
|
-
UPDATE ${syncTableName}
|
|
270
|
-
SET
|
|
271
|
-
"localPermanentId" = $2,
|
|
272
|
-
"updatedAt" = now()
|
|
273
|
-
WHERE "normalizedName" = $1
|
|
274
|
-
`,
|
|
275
|
-
[normalizedName, localPermanentId],
|
|
276
|
-
);
|
|
277
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { spaceTrim } from '@promptbook-local/utils';
|
|
2
|
-
import { DatabaseError } from '../../../../../src/errors/DatabaseError';
|
|
3
|
-
import type { FederatedOrganizationPayload } from './selectDefaultFederatedAgentsFromOrganizationPayload';
|
|
4
|
-
import { fetchWithDefaultFederatedAgentTimeout } from './fetchWithDefaultFederatedAgentTimeout';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Fetches the Core public organization snapshot.
|
|
8
|
-
*
|
|
9
|
-
* @param coreServerUrl - Base URL of the Core server.
|
|
10
|
-
* @returns Parsed organization payload.
|
|
11
|
-
*
|
|
12
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
13
|
-
*/
|
|
14
|
-
export async function fetchCoreOrganizationPayload(coreServerUrl: string): Promise<FederatedOrganizationPayload> {
|
|
15
|
-
const endpoint = new URL('/api/agent-organization', ensureTrailingSlash(coreServerUrl)).href;
|
|
16
|
-
const response = await fetchWithDefaultFederatedAgentTimeout(endpoint);
|
|
17
|
-
|
|
18
|
-
if (!response.ok) {
|
|
19
|
-
throw new DatabaseError(
|
|
20
|
-
spaceTrim(`
|
|
21
|
-
Failed to fetch default federated agents metadata from \`${endpoint}\`.
|
|
22
|
-
|
|
23
|
-
Received \`${response.status} ${response.statusText}\`.
|
|
24
|
-
`),
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return (await response.json()) as FederatedOrganizationPayload;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Normalizes a server base URL so relative `URL` construction stays predictable.
|
|
33
|
-
*
|
|
34
|
-
* @param value - Raw base URL.
|
|
35
|
-
* @returns Base URL with exactly one trailing slash.
|
|
36
|
-
*/
|
|
37
|
-
function ensureTrailingSlash(value: string): string {
|
|
38
|
-
return `${value.replace(/\/+$/g, '')}/`;
|
|
39
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { spaceTrim } from '@promptbook-local/utils';
|
|
2
|
-
import type { string_book } from '../../../../../src/book-2.0/agent-source/string_book';
|
|
3
|
-
import { DatabaseError } from '../../../../../src/errors/DatabaseError';
|
|
4
|
-
import { fetchWithDefaultFederatedAgentTimeout } from './fetchWithDefaultFederatedAgentTimeout';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Fetches the effective book source of one remote public agent.
|
|
8
|
-
*
|
|
9
|
-
* @param agentRouteUrl - Canonical remote agent route.
|
|
10
|
-
* @returns Remote book content as plain text.
|
|
11
|
-
*
|
|
12
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
13
|
-
*/
|
|
14
|
-
export async function fetchFederatedAgentBook(agentRouteUrl: string): Promise<string_book> {
|
|
15
|
-
const endpoint = buildFederatedAgentBookUrl(agentRouteUrl);
|
|
16
|
-
const response = await fetchWithDefaultFederatedAgentTimeout(endpoint);
|
|
17
|
-
|
|
18
|
-
if (!response.ok) {
|
|
19
|
-
throw new DatabaseError(
|
|
20
|
-
spaceTrim(`
|
|
21
|
-
Failed to fetch default federated agent source from \`${endpoint}\`.
|
|
22
|
-
|
|
23
|
-
Received \`${response.status} ${response.statusText}\`.
|
|
24
|
-
`),
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return (await response.text()) as string_book;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Builds the public book endpoint URL for one remote agent route.
|
|
33
|
-
*
|
|
34
|
-
* @param agentRouteUrl - Canonical remote agent route.
|
|
35
|
-
* @returns Absolute remote `/api/book` URL.
|
|
36
|
-
*/
|
|
37
|
-
function buildFederatedAgentBookUrl(agentRouteUrl: string): string {
|
|
38
|
-
const routeUrl = new URL(agentRouteUrl);
|
|
39
|
-
routeUrl.search = '';
|
|
40
|
-
routeUrl.hash = '';
|
|
41
|
-
routeUrl.pathname = `${routeUrl.pathname.replace(/\/+$/g, '')}/api/book`;
|
|
42
|
-
return routeUrl.href;
|
|
43
|
-
}
|
package/apps/agents-server/src/utils/defaultFederatedAgents/fetchWithDefaultFederatedAgentTimeout.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Timeout used for remote Core HTTP requests.
|
|
3
|
-
*/
|
|
4
|
-
const DEFAULT_FEDERATED_AGENT_FETCH_TIMEOUT_MS = 10_000;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Executes one HTTP request with a fixed abort timeout.
|
|
8
|
-
*
|
|
9
|
-
* @param url - Absolute request URL.
|
|
10
|
-
* @returns Successful or unsuccessful fetch response.
|
|
11
|
-
*
|
|
12
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
13
|
-
*/
|
|
14
|
-
export async function fetchWithDefaultFederatedAgentTimeout(url: string): Promise<Response> {
|
|
15
|
-
const abortController = new AbortController();
|
|
16
|
-
const timeout = setTimeout(() => abortController.abort(), DEFAULT_FEDERATED_AGENT_FETCH_TIMEOUT_MS);
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
return await fetch(url, {
|
|
20
|
-
method: 'GET',
|
|
21
|
-
cache: 'no-store',
|
|
22
|
-
headers: { Accept: 'application/json, text/plain;q=0.9, */*;q=0.1' },
|
|
23
|
-
signal: abortController.signal,
|
|
24
|
-
});
|
|
25
|
-
} finally {
|
|
26
|
-
clearTimeout(timeout);
|
|
27
|
-
}
|
|
28
|
-
}
|
package/apps/agents-server/src/utils/defaultFederatedAgents/getDefaultFederatedAgentSyncPool.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { spaceTrim } from '@promptbook-local/utils';
|
|
2
|
-
import { Pool } from 'pg';
|
|
3
|
-
import { DatabaseError } from '../../../../../src/errors/DatabaseError';
|
|
4
|
-
import { resolveDatabaseMigrationConnectionStringFromEnvironment } from '../../database/runDatabaseMigrations';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Shared PostgreSQL pool reused by default-agent sync helpers.
|
|
8
|
-
*/
|
|
9
|
-
let defaultFederatedAgentSyncPool: Pool | null = null;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Resolves the shared PostgreSQL pool used by this feature.
|
|
13
|
-
*
|
|
14
|
-
* @returns Shared PostgreSQL pool.
|
|
15
|
-
*
|
|
16
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
17
|
-
*/
|
|
18
|
-
export function getDefaultFederatedAgentSyncPool(): Pool {
|
|
19
|
-
if (defaultFederatedAgentSyncPool) {
|
|
20
|
-
return defaultFederatedAgentSyncPool;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const connectionString = resolveDatabaseMigrationConnectionStringFromEnvironment();
|
|
24
|
-
if (!connectionString) {
|
|
25
|
-
throw new DatabaseError(
|
|
26
|
-
spaceTrim(`
|
|
27
|
-
Cannot synchronize default federated agents because \`POSTGRES_URL\` or \`DATABASE_URL\` is missing.
|
|
28
|
-
`),
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
defaultFederatedAgentSyncPool = new Pool({
|
|
33
|
-
connectionString,
|
|
34
|
-
ssl: { rejectUnauthorized: false },
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
return defaultFederatedAgentSyncPool;
|
|
38
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Pool } from 'pg';
|
|
2
|
-
import { normalizeAgentName } from '../../../../../src/book-2.0/agent-source/normalizeAgentName';
|
|
3
|
-
import { quoteIdentifier } from './quoteIdentifier';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Loads active local agents and indexes them by normalized name.
|
|
7
|
-
*
|
|
8
|
-
* @param pool - Shared PostgreSQL pool.
|
|
9
|
-
* @param tablePrefix - Current server table prefix.
|
|
10
|
-
* @returns Normalized-name lookup of active local permanent ids.
|
|
11
|
-
*
|
|
12
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
13
|
-
*/
|
|
14
|
-
export async function loadActiveLocalAgentIdsByNormalizedName(
|
|
15
|
-
pool: Pool,
|
|
16
|
-
tablePrefix: string,
|
|
17
|
-
): Promise<Map<string, string>> {
|
|
18
|
-
const agentTableName = quoteIdentifier(`${tablePrefix}Agent`);
|
|
19
|
-
const result = await pool.query<{ agentName: string; permanentId: string | null }>(
|
|
20
|
-
`
|
|
21
|
-
SELECT "agentName", "permanentId"
|
|
22
|
-
FROM ${agentTableName}
|
|
23
|
-
WHERE "deletedAt" IS NULL
|
|
24
|
-
ORDER BY "createdAt" ASC
|
|
25
|
-
`,
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
const activeAgentsByNormalizedName = new Map<string, string>();
|
|
29
|
-
for (const row of result.rows) {
|
|
30
|
-
if (!row.permanentId) {
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const normalizedName = normalizeAgentName(row.agentName);
|
|
35
|
-
if (!activeAgentsByNormalizedName.has(normalizedName)) {
|
|
36
|
-
activeAgentsByNormalizedName.set(normalizedName, row.permanentId);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return activeAgentsByNormalizedName;
|
|
41
|
-
}
|
package/apps/agents-server/src/utils/defaultFederatedAgents/loadDefaultFederatedAgentSyncMetadata.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { Pool } from 'pg';
|
|
2
|
-
import {
|
|
3
|
-
DEFAULT_AGENT_VISIBILITY,
|
|
4
|
-
DEFAULT_VISIBILITY_METADATA_KEY,
|
|
5
|
-
LEGACY_DEFAULT_VISIBILITY_METADATA_KEY,
|
|
6
|
-
parseAgentVisibility,
|
|
7
|
-
type AgentVisibility,
|
|
8
|
-
} from '../agentVisibility';
|
|
9
|
-
import { quoteIdentifier } from './quoteIdentifier';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Metadata key storing the canonical Core server URL.
|
|
13
|
-
*/
|
|
14
|
-
const CORE_SERVER_METADATA_KEY = 'CORE_SERVER';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Loads the small metadata subset needed by the sync logic.
|
|
18
|
-
*
|
|
19
|
-
* @param pool - Shared PostgreSQL pool.
|
|
20
|
-
* @param tablePrefix - Current server table prefix.
|
|
21
|
-
* @returns Core server URL and effective default visibility.
|
|
22
|
-
*
|
|
23
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
24
|
-
*/
|
|
25
|
-
export async function loadDefaultFederatedAgentSyncMetadata(
|
|
26
|
-
pool: Pool,
|
|
27
|
-
tablePrefix: string,
|
|
28
|
-
): Promise<{ coreServerUrl: string | null; defaultVisibility: AgentVisibility }> {
|
|
29
|
-
const metadataTableName = quoteIdentifier(`${tablePrefix}Metadata`);
|
|
30
|
-
const result = await pool.query<{ key: string; value: string | null }>(
|
|
31
|
-
`
|
|
32
|
-
SELECT "key", "value"
|
|
33
|
-
FROM ${metadataTableName}
|
|
34
|
-
WHERE "key" = ANY($1)
|
|
35
|
-
`,
|
|
36
|
-
[[CORE_SERVER_METADATA_KEY, DEFAULT_VISIBILITY_METADATA_KEY, LEGACY_DEFAULT_VISIBILITY_METADATA_KEY]],
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const metadataByKey = new Map<string, string | null>();
|
|
40
|
-
for (const row of result.rows) {
|
|
41
|
-
metadataByKey.set(row.key, row.value);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
coreServerUrl: normalizeOptionalServerUrl(metadataByKey.get(CORE_SERVER_METADATA_KEY) || null),
|
|
46
|
-
defaultVisibility: parseAgentVisibility(
|
|
47
|
-
metadataByKey.get(DEFAULT_VISIBILITY_METADATA_KEY) || metadataByKey.get(LEGACY_DEFAULT_VISIBILITY_METADATA_KEY),
|
|
48
|
-
DEFAULT_AGENT_VISIBILITY,
|
|
49
|
-
),
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Normalizes an optional server URL so equality checks ignore trailing slashes.
|
|
55
|
-
*
|
|
56
|
-
* @param value - Raw server URL.
|
|
57
|
-
* @returns Normalized URL or `null`.
|
|
58
|
-
*/
|
|
59
|
-
function normalizeOptionalServerUrl(value: string | null): string | null {
|
|
60
|
-
if (!value) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const normalizedValue = value.trim();
|
|
65
|
-
return normalizedValue === '' ? null : ensureTrailingSlash(normalizedValue);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Ensures a server base URL always ends with a single slash.
|
|
70
|
-
*
|
|
71
|
-
* @param value - Raw server URL.
|
|
72
|
-
* @returns Base URL with one trailing slash.
|
|
73
|
-
*/
|
|
74
|
-
function ensureTrailingSlash(value: string): string {
|
|
75
|
-
return `${value.replace(/\/+$/g, '')}/`;
|
|
76
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Quotes one PostgreSQL identifier safely.
|
|
3
|
-
*
|
|
4
|
-
* @param identifier - Raw SQL identifier.
|
|
5
|
-
* @returns Quoted identifier.
|
|
6
|
-
*
|
|
7
|
-
* @private internal utility of `scheduleDefaultFederatedAgentsSync`
|
|
8
|
-
*/
|
|
9
|
-
export function quoteIdentifier(identifier: string): string {
|
|
10
|
-
return `"${identifier.replace(/"/g, '""')}"`;
|
|
11
|
-
}
|