@promptbook/core 0.104.0-0 → 0.104.0-2

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.
Files changed (29) hide show
  1. package/esm/index.es.js +281 -82
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/src/_packages/types.index.d.ts +6 -2
  4. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +6 -1
  5. package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
  6. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
  7. package/esm/typings/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +13 -0
  8. package/esm/typings/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +1 -0
  9. package/esm/typings/src/book-components/_common/Dropdown/Dropdown.d.ts +2 -2
  10. package/esm/typings/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +56 -0
  11. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +13 -7
  12. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +6 -0
  13. package/esm/typings/src/commitments/DICTIONARY/DICTIONARY.d.ts +46 -0
  14. package/esm/typings/src/commitments/index.d.ts +2 -1
  15. package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +1 -1
  16. package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +1 -1
  17. package/esm/typings/src/types/typeAliases.d.ts +12 -0
  18. package/esm/typings/src/utils/environment/$detectRuntimeEnvironment.d.ts +4 -4
  19. package/esm/typings/src/utils/environment/$isRunningInBrowser.d.ts +1 -1
  20. package/esm/typings/src/utils/environment/$isRunningInJest.d.ts +1 -1
  21. package/esm/typings/src/utils/environment/$isRunningInNode.d.ts +1 -1
  22. package/esm/typings/src/utils/environment/$isRunningInWebWorker.d.ts +1 -1
  23. package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
  24. package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
  25. package/esm/typings/src/utils/random/$randomBase58.d.ts +12 -0
  26. package/esm/typings/src/version.d.ts +1 -1
  27. package/package.json +1 -1
  28. package/umd/index.umd.js +287 -88
  29. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -27,7 +27,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
27
27
  * @generated
28
28
  * @see https://github.com/webgptorg/promptbook
29
29
  */
30
- const PROMPTBOOK_ENGINE_VERSION = '0.104.0-0';
30
+ const PROMPTBOOK_ENGINE_VERSION = '0.104.0-2';
31
31
  /**
32
32
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
33
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -7964,6 +7964,114 @@ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
7964
7964
  * Note: [💞] Ignore a discrepancy between file name and entity name
7965
7965
  */
7966
7966
 
7967
+ /**
7968
+ * DICTIONARY commitment definition
7969
+ *
7970
+ * The DICTIONARY commitment defines specific terms and their meanings that the agent should use correctly
7971
+ * in its reasoning and responses. This ensures consistent terminology usage.
7972
+ *
7973
+ * Key features:
7974
+ * - Multiple DICTIONARY commitments are automatically merged into one
7975
+ * - Content is placed in a dedicated section of the system message
7976
+ * - Terms and definitions are stored in metadata.DICTIONARY for debugging
7977
+ * - Agent should use the defined terms correctly in responses
7978
+ *
7979
+ * Example usage in agent source:
7980
+ *
7981
+ * ```book
7982
+ * Legal Assistant
7983
+ *
7984
+ * PERSONA You are a knowledgeable legal assistant
7985
+ * DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
7986
+ * DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
7987
+ * DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
7988
+ * ```
7989
+ *
7990
+ * @private [🪔] Maybe export the commitments through some package
7991
+ */
7992
+ class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
7993
+ constructor() {
7994
+ super('DICTIONARY');
7995
+ }
7996
+ /**
7997
+ * Short one-line description of DICTIONARY.
7998
+ */
7999
+ get description() {
8000
+ return 'Define terms and their meanings for consistent terminology usage.';
8001
+ }
8002
+ /**
8003
+ * Icon for this commitment.
8004
+ */
8005
+ get icon() {
8006
+ return '📚';
8007
+ }
8008
+ /**
8009
+ * Markdown documentation for DICTIONARY commitment.
8010
+ */
8011
+ get documentation() {
8012
+ return spaceTrim$1(`
8013
+ # DICTIONARY
8014
+
8015
+ Defines specific terms and their meanings that the agent should use correctly in reasoning and responses.
8016
+
8017
+ ## Key aspects
8018
+
8019
+ - Multiple \`DICTIONARY\` commitments are merged together.
8020
+ - Terms are defined in the format: "Term is definition"
8021
+ - The agent should use these terms consistently in responses.
8022
+ - Definitions help ensure accurate and consistent terminology.
8023
+
8024
+ ## Examples
8025
+
8026
+ \`\`\`book
8027
+ Legal Assistant
8028
+
8029
+ PERSONA You are a knowledgeable legal assistant specializing in criminal law
8030
+ DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
8031
+ DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
8032
+ DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
8033
+ \`\`\`
8034
+
8035
+ \`\`\`book
8036
+ Medical Assistant
8037
+
8038
+ PERSONA You are a helpful medical assistant
8039
+ DICTIONARY Hypertension is persistently high blood pressure
8040
+ DICTIONARY Diabetes is a chronic condition that affects how the body processes blood sugar
8041
+ DICTIONARY Vaccine is a biological preparation that provides active immunity to a particular disease
8042
+ \`\`\`
8043
+ `);
8044
+ }
8045
+ applyToAgentModelRequirements(requirements, content) {
8046
+ var _a;
8047
+ const trimmedContent = content.trim();
8048
+ if (!trimmedContent) {
8049
+ return requirements;
8050
+ }
8051
+ // Get existing dictionary entries from metadata
8052
+ const existingDictionary = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
8053
+ // Merge the new dictionary entry with existing entries
8054
+ const mergedDictionary = existingDictionary
8055
+ ? `${existingDictionary}\n${trimmedContent}`
8056
+ : trimmedContent;
8057
+ // Store the merged dictionary in metadata for debugging and inspection
8058
+ const updatedMetadata = {
8059
+ ...requirements.metadata,
8060
+ DICTIONARY: mergedDictionary,
8061
+ };
8062
+ // Create the dictionary section for the system message
8063
+ // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
8064
+ const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
8065
+ return {
8066
+ ...this.appendToSystemMessage(requirements, dictionarySection),
8067
+ metadata: updatedMetadata,
8068
+ };
8069
+ }
8070
+ }
8071
+ /**
8072
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8073
+ */
8074
+
7967
8075
  /**
7968
8076
  * FORMAT commitment definition
7969
8077
  *
@@ -10784,6 +10892,7 @@ const COMMITMENT_REGISTRY = [
10784
10892
  new DeleteCommitmentDefinition('CANCEL'),
10785
10893
  new DeleteCommitmentDefinition('DISCARD'),
10786
10894
  new DeleteCommitmentDefinition('REMOVE'),
10895
+ new DictionaryCommitmentDefinition(),
10787
10896
  new OpenCommitmentDefinition(),
10788
10897
  new ClosedCommitmentDefinition(),
10789
10898
  new UseBrowserCommitmentDefinition(),
@@ -11468,13 +11577,14 @@ function prompt(strings, ...values) {
11468
11577
  *
11469
11578
  * @public exported from `@promptbook/utils`
11470
11579
  */
11471
- const $isRunningInBrowser = new Function(`
11580
+ function $isRunningInBrowser() {
11472
11581
  try {
11473
- return this === window;
11474
- } catch (e) {
11582
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
11583
+ }
11584
+ catch (e) {
11475
11585
  return false;
11476
11586
  }
11477
- `);
11587
+ }
11478
11588
  /**
11479
11589
  * TODO: [🎺]
11480
11590
  */
@@ -11486,13 +11596,15 @@ const $isRunningInBrowser = new Function(`
11486
11596
  *
11487
11597
  * @public exported from `@promptbook/utils`
11488
11598
  */
11489
- const $isRunningInJest = new Function(`
11599
+ function $isRunningInJest() {
11600
+ var _a;
11490
11601
  try {
11491
- return process.env.JEST_WORKER_ID !== undefined;
11492
- } catch (e) {
11602
+ return typeof process !== 'undefined' && ((_a = process.env) === null || _a === void 0 ? void 0 : _a.JEST_WORKER_ID) !== undefined;
11603
+ }
11604
+ catch (e) {
11493
11605
  return false;
11494
11606
  }
11495
- `);
11607
+ }
11496
11608
  /**
11497
11609
  * TODO: [🎺]
11498
11610
  */
@@ -11504,13 +11616,14 @@ const $isRunningInJest = new Function(`
11504
11616
  *
11505
11617
  * @public exported from `@promptbook/utils`
11506
11618
  */
11507
- const $isRunningInNode = new Function(`
11619
+ function $isRunningInNode() {
11508
11620
  try {
11509
- return this === global;
11510
- } catch (e) {
11621
+ return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
11622
+ }
11623
+ catch (e) {
11511
11624
  return false;
11512
11625
  }
11513
- `);
11626
+ }
11514
11627
  /**
11515
11628
  * TODO: [🎺]
11516
11629
  */
@@ -11522,17 +11635,17 @@ const $isRunningInNode = new Function(`
11522
11635
  *
11523
11636
  * @public exported from `@promptbook/utils`
11524
11637
  */
11525
- const $isRunningInWebWorker = new Function(`
11638
+ function $isRunningInWebWorker() {
11526
11639
  try {
11527
- if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
11528
- return true;
11529
- } else {
11530
- return false;
11531
- }
11532
- } catch (e) {
11640
+ // Note: Check for importScripts which is specific to workers
11641
+ // and not available in the main browser thread
11642
+ return (typeof self !== 'undefined' &&
11643
+ typeof self.importScripts === 'function');
11644
+ }
11645
+ catch (e) {
11533
11646
  return false;
11534
11647
  }
11535
- `);
11648
+ }
11536
11649
  /**
11537
11650
  * TODO: [🎺]
11538
11651
  */
@@ -11790,6 +11903,7 @@ function parseAgentSource(agentSource) {
11790
11903
  return {
11791
11904
  agentName: normalizeAgentName(parseResult.agentName || createDefaultAgentName(agentSource)),
11792
11905
  agentHash,
11906
+ permanentId: meta.id,
11793
11907
  personaDescription,
11794
11908
  initialMessage,
11795
11909
  meta,
@@ -11981,6 +12095,41 @@ const DEFAULT_BOOK = padBook(validateBook(spaceTrim$2(`
11981
12095
  // <- [🐱‍🚀] Buttons into genesis book
11982
12096
  // <- TODO: [🐱‍🚀] generateBookBoilerplate and deprecate `DEFAULT_BOOK`
11983
12097
 
12098
+ /**
12099
+ * Base58 characters
12100
+ */
12101
+ const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
12102
+ /**
12103
+ * Generates random base58 string
12104
+ *
12105
+ * Note: `$` is used to indicate that this function is not a pure function - it is not deterministic
12106
+ * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
12107
+ *
12108
+ * @param length - length of the string
12109
+ * @returns secure random base58 string
12110
+ *
12111
+ * @private internal helper function
12112
+ */
12113
+ function $randomBase58(length) {
12114
+ let result = '';
12115
+ while (result.length < length) {
12116
+ // Generate enough bytes to cover the remaining length, plus some extra buffer to reduce calls
12117
+ // But simply generating `length - result.length` is fine for small lengths
12118
+ const bytes = randomBytes(length - result.length);
12119
+ for (let i = 0; i < bytes.length; i++) {
12120
+ const byte = bytes[i];
12121
+ // 58 * 4 = 232
12122
+ // We discard values >= 232 to avoid modulo bias
12123
+ if (byte < 232) {
12124
+ result += BASE58_ALPHABET[byte % 58];
12125
+ if (result.length === length)
12126
+ break;
12127
+ }
12128
+ }
12129
+ }
12130
+ return result;
12131
+ }
12132
+
11984
12133
  // import { getTableName } from '../../../../../apps/agents-server/src/database/getTableName';
11985
12134
  // <- TODO: [🐱‍🚀] Prevent imports from `/apps` -> `/src`
11986
12135
  /**
@@ -12014,19 +12163,20 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12014
12163
  const { isVerbose = DEFAULT_IS_VERBOSE } = this.options || {};
12015
12164
  const selectResult = await this.supabaseClient
12016
12165
  .from(this.getTableName('Agent'))
12017
- .select('agentName,agentProfile');
12166
+ .select('agentName,agentProfile,permanentId')
12167
+ .is('deletedAt', null);
12018
12168
  if (selectResult.error) {
12019
12169
  throw new DatabaseError(spaceTrim((block) => `
12020
-
12170
+
12021
12171
  Error fetching agents from Supabase:
12022
-
12172
+
12023
12173
  ${block(selectResult.error.message)}
12024
12174
  `));
12025
12175
  }
12026
12176
  if (isVerbose) {
12027
12177
  console.info(`Found ${selectResult.data.length} agents in directory`);
12028
12178
  }
12029
- return selectResult.data.map(({ agentName, agentProfile }) => {
12179
+ return selectResult.data.map(({ agentName, agentProfile, permanentId }) => {
12030
12180
  if (isVerbose && agentProfile.agentName !== agentName) {
12031
12181
  console.warn(spaceTrim(`
12032
12182
  Agent name mismatch for agent "${agentName}". Using name from database.
@@ -12038,6 +12188,7 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12038
12188
  return {
12039
12189
  ...agentProfile,
12040
12190
  agentName,
12191
+ permanentId: permanentId || agentProfile.permanentId,
12041
12192
  };
12042
12193
  });
12043
12194
  }
@@ -12048,7 +12199,7 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12048
12199
  const selectResult = await this.supabaseClient
12049
12200
  .from(this.getTableName('Agent'))
12050
12201
  .select('agentSource')
12051
- .eq('agentName', agentName);
12202
+ .or(`agentName.eq.${agentName},permanentId.eq.${agentName}`);
12052
12203
  if (selectResult.data && selectResult.data.length === 0) {
12053
12204
  throw new NotFoundError(`Agent "${agentName}" not found`);
12054
12205
  }
@@ -12070,12 +12221,26 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12070
12221
  * Note: You can set 'PARENT' in the agent source to inherit from another agent in the collection.
12071
12222
  */
12072
12223
  async createAgent(agentSource) {
12073
- const agentProfile = parseAgentSource(agentSource);
12224
+ let agentProfile = parseAgentSource(agentSource);
12074
12225
  // <- TODO: [🕛]
12075
12226
  const { agentName, agentHash } = agentProfile;
12227
+ let { permanentId } = agentProfile;
12228
+ if (!permanentId) {
12229
+ permanentId = $randomBase58(14);
12230
+ const lines = agentSource.split('\n');
12231
+ if (lines.length > 0) {
12232
+ lines.splice(1, 0, `META ID ${permanentId}`);
12233
+ agentSource = lines.join('\n');
12234
+ }
12235
+ else {
12236
+ agentSource = `META ID ${permanentId}\n${agentSource}`;
12237
+ }
12238
+ agentProfile = parseAgentSource(agentSource);
12239
+ }
12076
12240
  const insertAgentResult = await this.supabaseClient.from(this.getTableName('Agent')).insert({
12077
12241
  agentName,
12078
12242
  agentHash,
12243
+ permanentId,
12079
12244
  agentProfile,
12080
12245
  createdAt: new Date().toISOString(),
12081
12246
  updatedAt: null,
@@ -12099,15 +12264,16 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12099
12264
  promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
12100
12265
  });
12101
12266
  // <- TODO: [🧠] What to do with `insertAgentHistoryResult.error`, ignore? wait?
12102
- return agentProfile;
12267
+ return { ...agentProfile, permanentId };
12103
12268
  }
12104
12269
  /**
12105
12270
  * Updates an existing agent in the collection
12106
12271
  */
12107
12272
  async updateAgentSource(agentName, agentSource) {
12273
+ console.log('!!! updateAgentSource', { agentName });
12108
12274
  const selectPreviousAgentResult = await this.supabaseClient
12109
12275
  .from(this.getTableName('Agent'))
12110
- .select('agentHash,agentName')
12276
+ .select('agentHash,agentName,permanentId')
12111
12277
  .eq('agentName', agentName)
12112
12278
  .single();
12113
12279
  if (selectPreviousAgentResult.error) {
@@ -12121,13 +12287,28 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12121
12287
  }
12122
12288
  selectPreviousAgentResult.data.agentName;
12123
12289
  const previousAgentHash = selectPreviousAgentResult.data.agentHash;
12124
- const agentProfile = parseAgentSource(agentSource);
12290
+ const previousPermanentId = selectPreviousAgentResult.data.permanentId;
12291
+ let agentProfile = parseAgentSource(agentSource);
12125
12292
  // <- TODO: [🕛]
12126
12293
  const { agentHash } = agentProfile;
12294
+ let { permanentId } = agentProfile;
12295
+ if (!permanentId && previousPermanentId) {
12296
+ permanentId = previousPermanentId;
12297
+ const lines = agentSource.split('\n');
12298
+ if (lines.length > 0) {
12299
+ lines.splice(1, 0, `META ID ${permanentId}`);
12300
+ agentSource = lines.join('\n');
12301
+ }
12302
+ else {
12303
+ agentSource = `META ID ${permanentId}\n${agentSource}`;
12304
+ }
12305
+ agentProfile = parseAgentSource(agentSource);
12306
+ }
12127
12307
  const updateAgentResult = await this.supabaseClient
12128
12308
  .from(this.getTableName('Agent'))
12129
12309
  .update({
12130
12310
  // TODO: [🐱‍🚀] Compare not update> agentName: agentProfile.agentName || '[🐱‍🚀]' /* <- TODO: [🐱‍🚀] Remove */,
12311
+ permanentId,
12131
12312
  agentProfile,
12132
12313
  updatedAt: new Date().toISOString(),
12133
12314
  agentHash: agentProfile.agentHash,
@@ -12158,20 +12339,39 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12158
12339
  // TODO: [🐱‍🚀] public async getAgentSourceSubject(agentName: string_agent_name): Promise<BehaviorSubject<string_book>>
12159
12340
  // Use Supabase realtime logic
12160
12341
  /**
12161
- * Deletes an agent from the collection
12342
+ * List agents that are soft deleted (deletedAt IS NOT NULL)
12162
12343
  */
12163
- async deleteAgent(agentName) {
12164
- const deleteResult = await this.supabaseClient
12344
+ async listDeletedAgents() {
12345
+ const { isVerbose = DEFAULT_IS_VERBOSE } = this.options || {};
12346
+ const selectResult = await this.supabaseClient
12165
12347
  .from(this.getTableName('Agent'))
12166
- .delete()
12167
- .eq('agentName', agentName);
12168
- if (deleteResult.error) {
12348
+ .select('agentName,agentProfile,permanentId')
12349
+ .not('deletedAt', 'is', null);
12350
+ if (selectResult.error) {
12169
12351
  throw new DatabaseError(spaceTrim((block) => `
12170
- Error deleting agent "${agentName}" from Supabase:
12171
-
12172
- ${block(deleteResult.error.message)}
12173
- `));
12352
+ Error fetching deleted agents from Supabase:
12353
+
12354
+ ${block(selectResult.error.message)}
12355
+ `));
12174
12356
  }
12357
+ if (isVerbose) {
12358
+ console.info(`Found ${selectResult.data.length} deleted agents in directory`);
12359
+ }
12360
+ return selectResult.data.map(({ agentName, agentProfile, permanentId }) => {
12361
+ if (isVerbose && agentProfile.agentName !== agentName) {
12362
+ console.warn(spaceTrim(`
12363
+ Agent name mismatch for agent "${agentName}". Using name from database.
12364
+
12365
+ agentName: "${agentName}"
12366
+ agentProfile.agentName: "${agentProfile.agentName}"
12367
+ `));
12368
+ }
12369
+ return {
12370
+ ...agentProfile,
12371
+ agentName,
12372
+ permanentId: permanentId || agentProfile.permanentId,
12373
+ };
12374
+ });
12175
12375
  }
12176
12376
  /**
12177
12377
  * List history of an agent
@@ -12185,71 +12385,70 @@ class AgentCollectionInSupabase /* TODO: [🐱‍🚀] implements Agent */ {
12185
12385
  if (result.error) {
12186
12386
  throw new DatabaseError(spaceTrim((block) => `
12187
12387
  Error listing history for agent "${agentName}" from Supabase:
12188
-
12388
+
12189
12389
  ${block(result.error.message)}
12190
12390
  `));
12191
12391
  }
12192
12392
  return result.data;
12193
12393
  }
12194
12394
  /**
12195
- * List agents that are in history but not in the active agents list
12395
+ * Restore a soft-deleted agent by setting deletedAt to NULL
12196
12396
  */
12197
- async listDeletedAgents() {
12198
- const historyNamesResult = await this.supabaseClient.from(this.getTableName('AgentHistory')).select('agentName');
12199
- const currentNamesResult = await this.supabaseClient.from(this.getTableName('Agent')).select('agentName');
12200
- if (historyNamesResult.error) {
12201
- throw new DatabaseError(spaceTrim((block) => `
12202
- Error fetching agent history names from Supabase:
12203
-
12204
- ${block(historyNamesResult.error.message)}
12205
- `));
12206
- }
12207
- if (currentNamesResult.error) {
12397
+ async restoreAgent(agentIdentifier) {
12398
+ const updateResult = await this.supabaseClient
12399
+ .from(this.getTableName('Agent'))
12400
+ .update({ deletedAt: null })
12401
+ .or(`agentName.eq.${agentIdentifier},permanentId.eq.${agentIdentifier}`)
12402
+ .not('deletedAt', 'is', null);
12403
+ if (updateResult.error) {
12208
12404
  throw new DatabaseError(spaceTrim((block) => `
12209
- Error fetching current agent names from Supabase:
12210
-
12211
- ${block(currentNamesResult.error.message)}
12405
+ Error restoring agent "${agentIdentifier}" from Supabase:
12406
+
12407
+ ${block(updateResult.error.message)}
12212
12408
  `));
12213
12409
  }
12214
- const currentNames = new Set(currentNamesResult.data.map((d) => d.agentName));
12215
- const deletedNames = new Set();
12216
- for (const { agentName } of historyNamesResult.data) {
12217
- if (!currentNames.has(agentName)) {
12218
- deletedNames.add(agentName);
12219
- }
12220
- }
12221
- return Array.from(deletedNames);
12222
12410
  }
12223
12411
  /**
12224
- * Restore an agent from history
12412
+ * Restore an agent from a specific history entry
12413
+ *
12414
+ * This will update the current agent with the source from the history entry
12225
12415
  */
12226
- async restoreAgent(historyId) {
12416
+ async restoreAgentFromHistory(historyId) {
12417
+ // First, get the history entry
12227
12418
  const historyResult = await this.supabaseClient
12228
12419
  .from(this.getTableName('AgentHistory'))
12229
- .select('*')
12420
+ .select('agentName, agentSource')
12230
12421
  .eq('id', historyId)
12231
12422
  .single();
12232
12423
  if (historyResult.error) {
12233
12424
  throw new DatabaseError(spaceTrim((block) => `
12234
- Error fetching agent history item "${historyId}" from Supabase:
12235
-
12425
+ Error fetching history entry with id "${historyId}" from Supabase:
12426
+
12236
12427
  ${block(historyResult.error.message)}
12237
12428
  `));
12238
12429
  }
12430
+ if (!historyResult.data) {
12431
+ throw new NotFoundError(`History entry with id "${historyId}" not found`);
12432
+ }
12239
12433
  const { agentName, agentSource } = historyResult.data;
12240
- // Check if agent exists
12241
- const agentResult = await this.supabaseClient
12434
+ // Update the agent with the source from the history entry
12435
+ await this.updateAgentSource(agentName, agentSource);
12436
+ }
12437
+ /**
12438
+ * Soft delete an agent by setting deletedAt to current timestamp
12439
+ */
12440
+ async deleteAgent(agentIdentifier) {
12441
+ const updateResult = await this.supabaseClient
12242
12442
  .from(this.getTableName('Agent'))
12243
- .select('id')
12244
- .eq('agentName', agentName)
12245
- .single();
12246
- if (agentResult.data) {
12247
- // Update
12248
- await this.updateAgentSource(agentName, agentSource);
12249
- }
12250
- else {
12251
- // Insert (Restore from deleted)
12252
- await this.createAgent(agentSource);
12443
+ .update({ deletedAt: new Date().toISOString() })
12444
+ .or(`agentName.eq.${agentIdentifier},permanentId.eq.${agentIdentifier}`)
12445
+ .is('deletedAt', null);
12446
+ if (updateResult.error) {
12447
+ throw new DatabaseError(spaceTrim((block) => `
12448
+ Error deleting agent "${agentIdentifier}" from Supabase:
12449
+
12450
+ ${block(updateResult.error.message)}
12451
+ `));
12253
12452
  }
12254
12453
  }
12255
12454
  /**
@@ -16467,7 +16666,7 @@ function $registeredLlmToolsMessage() {
16467
16666
  ${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
16468
16667
  ${morePieces.join('; ')}
16469
16668
  `);
16470
- if ($isRunningInNode) {
16669
+ if ($isRunningInNode()) {
16471
16670
  if (isInstalled && isFullyConfigured) {
16472
16671
  providerMessage = colors.green(providerMessage);
16473
16672
  }