@promptbook/components 0.101.0-7 β†’ 0.101.0-9

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/esm/index.es.js CHANGED
@@ -19,7 +19,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
19
19
  * @generated
20
20
  * @see https://github.com/webgptorg/promptbook
21
21
  */
22
- const PROMPTBOOK_ENGINE_VERSION = '0.101.0-7';
22
+ const PROMPTBOOK_ENGINE_VERSION = '0.101.0-9';
23
23
  /**
24
24
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
25
25
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
@@ -251,8 +251,8 @@ class BaseCommitmentDefinition {
251
251
  * @private [πŸͺ”] Maybe export the commitments through some package
252
252
  */
253
253
  class ActionCommitmentDefinition extends BaseCommitmentDefinition {
254
- constructor() {
255
- super('ACTION');
254
+ constructor(type = 'ACTION') {
255
+ super(type);
256
256
  }
257
257
  /**
258
258
  * Short one-line description of ACTION.
@@ -265,13 +265,14 @@ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
265
265
  */
266
266
  get documentation() {
267
267
  return spaceTrim(`
268
- # ACTION
268
+ # ${this.type}
269
269
 
270
270
  Defines specific actions or capabilities that the agent can perform.
271
271
 
272
272
  ## Key behaviors
273
273
 
274
- - Multiple \`ACTION\` commitments are applied sequentially.
274
+ - Multiple \`ACTION\` and \`ACTIONS\` commitments are applied sequentially.
275
+ - Both terms work identically and can be used interchangeably.
275
276
  - Each action adds to the agent's capability list.
276
277
  - Actions help users understand what the agent can do.
277
278
 
@@ -312,7 +313,13 @@ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
312
313
  *
313
314
  * @private [πŸͺ”] Maybe export the commitments through some package
314
315
  */
315
- new ActionCommitmentDefinition();
316
+ new ActionCommitmentDefinition('ACTION');
317
+ /**
318
+ * Singleton instance of the ACTIONS commitment definition
319
+ *
320
+ * @private [πŸͺ”] Maybe export the commitments through some package
321
+ */
322
+ new ActionCommitmentDefinition('ACTIONS');
316
323
  /**
317
324
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
318
325
  */
@@ -476,8 +483,8 @@ new DeleteCommitmentDefinition('REMOVE');
476
483
  * @private [πŸͺ”] Maybe export the commitments through some package
477
484
  */
478
485
  class FormatCommitmentDefinition extends BaseCommitmentDefinition {
479
- constructor() {
480
- super('FORMAT');
486
+ constructor(type = 'FORMAT') {
487
+ super(type);
481
488
  }
482
489
  /**
483
490
  * Short one-line description of FORMAT.
@@ -490,13 +497,14 @@ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
490
497
  */
491
498
  get documentation() {
492
499
  return spaceTrim(`
493
- # FORMAT
500
+ # ${this.type}
494
501
 
495
502
  Defines the specific output structure and formatting for responses (data formats, templates, structure).
496
503
 
497
504
  ## Key behaviors
498
505
 
499
- - Multiple \`FORMAT\` commitments are applied sequentially.
506
+ - Multiple \`FORMAT\` and \`FORMATS\` commitments are applied sequentially.
507
+ - Both terms work identically and can be used interchangeably.
500
508
  - If they are in conflict, the last one takes precedence.
501
509
  - You can specify both data formats and presentation styles.
502
510
 
@@ -535,7 +543,13 @@ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
535
543
  *
536
544
  * @private [πŸͺ”] Maybe export the commitments through some package
537
545
  */
538
- new FormatCommitmentDefinition();
546
+ new FormatCommitmentDefinition('FORMAT');
547
+ /**
548
+ * Singleton instance of the FORMATS commitment definition
549
+ *
550
+ * @private [πŸͺ”] Maybe export the commitments through some package
551
+ */
552
+ new FormatCommitmentDefinition('FORMATS');
539
553
  /**
540
554
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
541
555
  */
@@ -557,8 +571,8 @@ new FormatCommitmentDefinition();
557
571
  * @private [πŸͺ”] Maybe export the commitments through some package
558
572
  */
559
573
  class GoalCommitmentDefinition extends BaseCommitmentDefinition {
560
- constructor() {
561
- super('GOAL');
574
+ constructor(type = 'GOAL') {
575
+ super(type);
562
576
  }
563
577
  /**
564
578
  * Short one-line description of GOAL.
@@ -571,13 +585,14 @@ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
571
585
  */
572
586
  get documentation() {
573
587
  return spaceTrim(`
574
- # GOAL
588
+ # ${this.type}
575
589
 
576
590
  Defines the main goal which should be achieved by the AI assistant. There can be multiple goals, and later goals are more important than earlier goals.
577
591
 
578
592
  ## Key behaviors
579
593
 
580
- - Multiple \`GOAL\` commitments are applied sequentially.
594
+ - Multiple \`GOAL\` and \`GOALS\` commitments are applied sequentially.
595
+ - Both terms work identically and can be used interchangeably.
581
596
  - Later goals have higher priority and can override earlier goals.
582
597
  - Goals provide clear direction and purpose for the agent's responses.
583
598
  - Goals influence decision-making and response prioritization.
@@ -635,7 +650,13 @@ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
635
650
  *
636
651
  * @private [πŸͺ”] Maybe export the commitments through some package
637
652
  */
638
- new GoalCommitmentDefinition();
653
+ new GoalCommitmentDefinition('GOAL');
654
+ /**
655
+ * Singleton instance of the GOALS commitment definition
656
+ *
657
+ * @private [πŸͺ”] Maybe export the commitments through some package
658
+ */
659
+ new GoalCommitmentDefinition('GOALS');
639
660
  /**
640
661
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
641
662
  */
@@ -673,13 +694,13 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
673
694
  */
674
695
  get documentation() {
675
696
  return spaceTrim(`
676
- # KNOWLEDGE
697
+ # ${this.type}
677
698
 
678
699
  Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
679
700
 
680
701
  ## Key behaviors
681
702
 
682
- - Multiple \`KNOWLEDGE\` commitments are applied sequentially.
703
+ - Both terms work identically and can be used interchangeably.
683
704
  - Supports both direct text knowledge and external URLs.
684
705
  - External sources (PDFs, websites) are processed via RAG for context retrieval.
685
706
 
@@ -755,7 +776,7 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
755
776
  }
756
777
  }
757
778
  /**
758
- * Singleton instance of the KNOWLEDGE commitment definition
779
+ * Singleton instance of the KNOWLEDGE commitment definition !!!!
759
780
  *
760
781
  * @private [πŸͺ”] Maybe export the commitments through some package
761
782
  */
@@ -782,8 +803,8 @@ new KnowledgeCommitmentDefinition();
782
803
  * @private [πŸͺ”] Maybe export the commitments through some package
783
804
  */
784
805
  class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
785
- constructor() {
786
- super('MEMORY');
806
+ constructor(type = 'MEMORY') {
807
+ super(type);
787
808
  }
788
809
  /**
789
810
  * Short one-line description of MEMORY.
@@ -796,13 +817,14 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
796
817
  */
797
818
  get documentation() {
798
819
  return spaceTrim(`
799
- # MEMORY
820
+ # ${this.type}
800
821
 
801
822
  Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
802
823
 
803
824
  ## Key behaviors
804
825
 
805
- - Multiple \`MEMORY\` commitments are applied sequentially.
826
+ - Multiple \`MEMORY\` and \`MEMORIES\` commitments are applied sequentially. !!!!
827
+ - Both terms work identically and can be used interchangeably.
806
828
  - Focuses on user-specific information and interaction history.
807
829
  - Helps personalize responses based on past interactions.
808
830
  - Maintains continuity across conversations.
@@ -866,7 +888,13 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
866
888
  *
867
889
  * @private [πŸͺ”] Maybe export the commitments through some package
868
890
  */
869
- new MemoryCommitmentDefinition();
891
+ new MemoryCommitmentDefinition('MEMORY');
892
+ /**
893
+ * Singleton instance of the MEMORIES commitment definition
894
+ *
895
+ * @private [πŸͺ”] Maybe export the commitments through some package
896
+ */
897
+ new MemoryCommitmentDefinition('MEMORIES');
870
898
  /**
871
899
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
872
900
  */
@@ -890,8 +918,8 @@ new MemoryCommitmentDefinition();
890
918
  * @private [πŸͺ”] Maybe export the commitments through some package
891
919
  */
892
920
  class MessageCommitmentDefinition extends BaseCommitmentDefinition {
893
- constructor() {
894
- super('MESSAGE');
921
+ constructor(type = 'MESSAGE') {
922
+ super(type);
895
923
  }
896
924
  /**
897
925
  * Short one-line description of MESSAGE.
@@ -904,13 +932,14 @@ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
904
932
  */
905
933
  get documentation() {
906
934
  return spaceTrim(`
907
- # MESSAGE
935
+ # ${this.type}
908
936
 
909
937
  Contains 1:1 text of the message which AI assistant already sent during the conversation. Later messages are later in the conversation. It is similar to EXAMPLE but it is not example, it is the real message which AI assistant already sent.
910
938
 
911
939
  ## Key behaviors
912
940
 
913
- - Multiple \`MESSAGE\` commitments represent the conversation timeline.
941
+ - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
942
+ - Both terms work identically and can be used interchangeably.
914
943
  - Later messages are later in the conversation chronologically.
915
944
  - Contains actual historical messages, not examples or templates.
916
945
  - Helps maintain conversation continuity and context.
@@ -918,9 +947,9 @@ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
918
947
  ## Differences from EXAMPLE
919
948
 
920
949
  - \`EXAMPLE\` shows hypothetical or template responses
921
- - \`MESSAGE\` contains actual historical conversation content
922
- - \`MESSAGE\` preserves the exact conversation flow
923
- - \`MESSAGE\` helps with context awareness and consistency
950
+ - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
951
+ - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
952
+ - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
924
953
 
925
954
  ## Use cases
926
955
 
@@ -981,7 +1010,13 @@ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
981
1010
  *
982
1011
  * @private [πŸͺ”] Maybe export the commitments through some package
983
1012
  */
984
- new MessageCommitmentDefinition();
1013
+ new MessageCommitmentDefinition('MESSAGE');
1014
+ /**
1015
+ * Singleton instance of the MESSAGES commitment definition
1016
+ *
1017
+ * @private [πŸͺ”] Maybe export the commitments through some package
1018
+ */
1019
+ new MessageCommitmentDefinition('MESSAGES');
985
1020
  /**
986
1021
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
987
1022
  */
@@ -1146,8 +1181,8 @@ new MetaCommitmentDefinition();
1146
1181
  * @private [πŸͺ”] Maybe export the commitments through some package
1147
1182
  */
1148
1183
  class ModelCommitmentDefinition extends BaseCommitmentDefinition {
1149
- constructor() {
1150
- super('MODEL');
1184
+ constructor(type = 'MODEL') {
1185
+ super(type);
1151
1186
  }
1152
1187
  /**
1153
1188
  * Short one-line description of MODEL.
@@ -1160,13 +1195,14 @@ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
1160
1195
  */
1161
1196
  get documentation() {
1162
1197
  return spaceTrim(`
1163
- # MODEL
1198
+ # ${this.type}
1164
1199
 
1165
1200
  Specifies which AI model to use and optional decoding parameters.
1166
1201
 
1167
1202
  ## Key behaviors
1168
1203
 
1169
- - Only one \`MODEL\` commitment should be used per agent.
1204
+ - Only one \`MODEL\` or \`MODELS\` commitment should be used per agent.
1205
+ - Both terms work identically and can be used interchangeably.
1170
1206
  - If multiple are specified, the last one takes precedence.
1171
1207
  - Parameters control the randomness and creativity of responses.
1172
1208
 
@@ -1246,7 +1282,13 @@ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
1246
1282
  *
1247
1283
  * @private [πŸͺ”] Maybe export the commitments through some package
1248
1284
  */
1249
- new ModelCommitmentDefinition();
1285
+ new ModelCommitmentDefinition('MODEL');
1286
+ /**
1287
+ * Singleton instance of the MODELS commitment definition
1288
+ *
1289
+ * @private [πŸͺ”] Maybe export the commitments through some package
1290
+ */
1291
+ new ModelCommitmentDefinition('MODELS');
1250
1292
  /**
1251
1293
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
1252
1294
  */
@@ -1278,8 +1320,8 @@ new ModelCommitmentDefinition();
1278
1320
  * @private [πŸͺ”] Maybe export the commitments through some package
1279
1321
  */
1280
1322
  class NoteCommitmentDefinition extends BaseCommitmentDefinition {
1281
- constructor() {
1282
- super('NOTE');
1323
+ constructor(type = 'NOTE') {
1324
+ super(type);
1283
1325
  }
1284
1326
  /**
1285
1327
  * Short one-line description of NOTE.
@@ -1292,14 +1334,15 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
1292
1334
  */
1293
1335
  get documentation() {
1294
1336
  return spaceTrim(`
1295
- # NOTE
1337
+ # ${this.type}
1296
1338
 
1297
1339
  Adds comments for documentation without changing agent behavior.
1298
1340
 
1299
1341
  ## Key behaviors
1300
1342
 
1301
1343
  - Does not modify the agent's behavior or responses.
1302
- - Multiple \`NOTE\` commitments are aggregated for debugging.
1344
+ - Multiple \`NOTE\` and \`NOTES\` commitments are aggregated for debugging.
1345
+ - Both terms work identically and can be used interchangeably.
1303
1346
  - Useful for documenting design decisions and reminders.
1304
1347
  - Content is preserved in metadata for inspection.
1305
1348
 
@@ -1356,7 +1399,13 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
1356
1399
  *
1357
1400
  * @private [πŸͺ”] Maybe export the commitments through some package
1358
1401
  */
1359
- new NoteCommitmentDefinition();
1402
+ new NoteCommitmentDefinition('NOTE');
1403
+ /**
1404
+ * Singleton instance of the NOTES commitment definition
1405
+ *
1406
+ * @private [πŸͺ”] Maybe export the commitments through some package
1407
+ */
1408
+ new NoteCommitmentDefinition('NOTES');
1360
1409
  /**
1361
1410
  * [πŸ’ž] Ignore a discrepancy between file name and entity name
1362
1411
  */
@@ -1385,8 +1434,8 @@ new NoteCommitmentDefinition();
1385
1434
  * @private [πŸͺ”] Maybe export the commitments through some package
1386
1435
  */
1387
1436
  class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
1388
- constructor() {
1389
- super('PERSONA');
1437
+ constructor(type = 'PERSONA') {
1438
+ super(type);
1390
1439
  }
1391
1440
  /**
1392
1441
  * Short one-line description of PERSONA.
@@ -1399,13 +1448,14 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
1399
1448
  */
1400
1449
  get documentation() {
1401
1450
  return spaceTrim(`
1402
- # PERSONA
1451
+ # ${this.type}
1403
1452
 
1404
1453
  Defines who the agent is, their background, expertise, and personality traits.
1405
1454
 
1406
1455
  ## Key behaviors
1407
1456
 
1408
- - Multiple \`PERSONA\` commitments are merged together.
1457
+ - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
1458
+ - Both terms work identically and can be used interchangeably.
1409
1459
  - If they are in conflict, the last one takes precedence.
1410
1460
  - You can write persona content in multiple lines.
1411
1461
 
@@ -1495,7 +1545,13 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
1495
1545
  *
1496
1546
  * @private [πŸͺ”] Maybe export the commitments through some package
1497
1547
  */
1498
- new PersonaCommitmentDefinition();
1548
+ new PersonaCommitmentDefinition('PERSONA');
1549
+ /**
1550
+ * Singleton instance of the PERSONAE commitment definition
1551
+ *
1552
+ * @private [πŸͺ”] Maybe export the commitments through some package
1553
+ */
1554
+ new PersonaCommitmentDefinition('PERSONAE');
1499
1555
  /**
1500
1556
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
1501
1557
  */
@@ -1695,8 +1751,8 @@ new SampleCommitmentDefinition('EXAMPLE');
1695
1751
  * @private [πŸͺ”] Maybe export the commitments through some package
1696
1752
  */
1697
1753
  class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
1698
- constructor() {
1699
- super('SCENARIO');
1754
+ constructor(type = 'SCENARIO') {
1755
+ super(type);
1700
1756
  }
1701
1757
  /**
1702
1758
  * Short one-line description of SCENARIO.
@@ -1709,13 +1765,14 @@ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
1709
1765
  */
1710
1766
  get documentation() {
1711
1767
  return spaceTrim(`
1712
- # SCENARIO
1768
+ # ${this.type}
1713
1769
 
1714
1770
  Defines a specific situation or context in which the AI assistant should operate. It helps to set the scene for the AI's responses. Later scenarios are more important than earlier scenarios.
1715
1771
 
1716
1772
  ## Key behaviors
1717
1773
 
1718
- - Multiple \`SCENARIO\` commitments build upon each other.
1774
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
1775
+ - Both terms work identically and can be used interchangeably.
1719
1776
  - Later scenarios have higher priority and can override earlier scenarios.
1720
1777
  - Provides situational context that influences response tone and content.
1721
1778
  - Helps establish the environment and circumstances for interactions.
@@ -1795,7 +1852,13 @@ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
1795
1852
  *
1796
1853
  * @private [πŸͺ”] Maybe export the commitments through some package
1797
1854
  */
1798
- new ScenarioCommitmentDefinition();
1855
+ new ScenarioCommitmentDefinition('SCENARIO');
1856
+ /**
1857
+ * Singleton instance of the SCENARIOS commitment definition
1858
+ *
1859
+ * @private [πŸͺ”] Maybe export the commitments through some package
1860
+ */
1861
+ new ScenarioCommitmentDefinition('SCENARIOS');
1799
1862
  /**
1800
1863
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
1801
1864
  */
@@ -1816,8 +1879,8 @@ new ScenarioCommitmentDefinition();
1816
1879
  * @private [πŸͺ”] Maybe export the commitments through some package
1817
1880
  */
1818
1881
  class StyleCommitmentDefinition extends BaseCommitmentDefinition {
1819
- constructor() {
1820
- super('STYLE');
1882
+ constructor(type = 'STYLE') {
1883
+ super(type);
1821
1884
  }
1822
1885
  /**
1823
1886
  * Short one-line description of STYLE.
@@ -1830,13 +1893,14 @@ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
1830
1893
  */
1831
1894
  get documentation() {
1832
1895
  return spaceTrim(`
1833
- # STYLE
1896
+ # ${this.type}
1834
1897
 
1835
1898
  Defines how the agent should format and present its responses (tone, writing style, formatting).
1836
1899
 
1837
1900
  ## Key behaviors
1838
1901
 
1839
- - Multiple \`STYLE\` commitments are applied sequentially.
1902
+ - Multiple \`STYLE\` and \`STYLES\` commitments are applied sequentially.
1903
+ - Both terms work identically and can be used interchangeably.
1840
1904
  - Later style instructions can override earlier ones.
1841
1905
  - Style affects both tone and presentation format.
1842
1906
 
@@ -1877,7 +1941,13 @@ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
1877
1941
  *
1878
1942
  * @private [πŸͺ”] Maybe export the commitments through some package
1879
1943
  */
1880
- new StyleCommitmentDefinition();
1944
+ new StyleCommitmentDefinition('STYLE');
1945
+ /**
1946
+ * Singleton instance of the STYLES commitment definition
1947
+ *
1948
+ * @private [πŸͺ”] Maybe export the commitments through some package
1949
+ */
1950
+ new StyleCommitmentDefinition('STYLES');
1881
1951
  /**
1882
1952
  * [πŸ’ž] Ignore a discrepancy between file name and entity name
1883
1953
  */
@@ -1953,34 +2023,42 @@ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
1953
2023
  */
1954
2024
  const COMMITMENT_REGISTRY = [
1955
2025
  // Fully implemented commitments
1956
- new PersonaCommitmentDefinition(),
2026
+ new PersonaCommitmentDefinition('PERSONA'),
2027
+ new PersonaCommitmentDefinition('PERSONAE'),
1957
2028
  new KnowledgeCommitmentDefinition(),
1958
- new MemoryCommitmentDefinition(),
1959
- new StyleCommitmentDefinition(),
2029
+ new MemoryCommitmentDefinition('MEMORY'),
2030
+ new MemoryCommitmentDefinition('MEMORIES'),
2031
+ new StyleCommitmentDefinition('STYLE'),
2032
+ new StyleCommitmentDefinition('STYLES'),
1960
2033
  new RuleCommitmentDefinition('RULE'),
1961
2034
  new RuleCommitmentDefinition('RULES'),
1962
2035
  new SampleCommitmentDefinition('SAMPLE'),
1963
2036
  new SampleCommitmentDefinition('EXAMPLE'),
1964
- new FormatCommitmentDefinition(),
1965
- new ModelCommitmentDefinition(),
1966
- new ActionCommitmentDefinition(),
2037
+ new FormatCommitmentDefinition('FORMAT'),
2038
+ new FormatCommitmentDefinition('FORMATS'),
2039
+ new ModelCommitmentDefinition('MODEL'),
2040
+ new ModelCommitmentDefinition('MODELS'),
2041
+ new ActionCommitmentDefinition('ACTION'),
2042
+ new ActionCommitmentDefinition('ACTIONS'),
1967
2043
  new MetaCommitmentDefinition(),
1968
- new NoteCommitmentDefinition(),
1969
- new GoalCommitmentDefinition(),
1970
- new MessageCommitmentDefinition(),
1971
- new ScenarioCommitmentDefinition(),
2044
+ new NoteCommitmentDefinition('NOTE'),
2045
+ new NoteCommitmentDefinition('NOTES'),
2046
+ new GoalCommitmentDefinition('GOAL'),
2047
+ new GoalCommitmentDefinition('GOALS'),
2048
+ new MessageCommitmentDefinition('MESSAGE'),
2049
+ new MessageCommitmentDefinition('MESSAGES'),
2050
+ new ScenarioCommitmentDefinition('SCENARIO'),
2051
+ new ScenarioCommitmentDefinition('SCENARIOS'),
1972
2052
  new DeleteCommitmentDefinition('DELETE'),
1973
2053
  new DeleteCommitmentDefinition('CANCEL'),
1974
2054
  new DeleteCommitmentDefinition('DISCARD'),
1975
2055
  new DeleteCommitmentDefinition('REMOVE'),
1976
2056
  // Not yet implemented commitments (using placeholder)
1977
2057
  new NotYetImplementedCommitmentDefinition('EXPECT'),
1978
- new NotYetImplementedCommitmentDefinition('SCENARIOS'),
1979
2058
  new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
1980
2059
  new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
1981
2060
  new NotYetImplementedCommitmentDefinition('AVOID'),
1982
2061
  new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
1983
- new NotYetImplementedCommitmentDefinition('GOALS'),
1984
2062
  new NotYetImplementedCommitmentDefinition('CONTEXT'),
1985
2063
  ];
1986
2064
  /**
@@ -2087,6 +2165,64 @@ function parseAgentSourceWithCommitments(agentSource) {
2087
2165
  };
2088
2166
  }
2089
2167
 
2168
+ /**
2169
+ * Parses parameters from text using both supported notations:
2170
+ * 1. @Parameter - single word parameter starting with @
2171
+ * 2. {parameterName} or {parameter with multiple words} or {parameterName: description text}
2172
+ *
2173
+ * Both notations represent the same syntax feature - parameters
2174
+ *
2175
+ * @param text - Text to extract parameters from
2176
+ * @returns Array of parsed parameters with unified representation
2177
+ * @public exported from `@promptbook/core`
2178
+ */
2179
+ function parseParameters(text) {
2180
+ const parameters = [];
2181
+ // [🧠] Parameter syntax parsing - unified approach for two different notations of the same syntax feature
2182
+ // The Book language supports parameters in two different notations but they represent the same concept
2183
+ // Extract @Parameter notation (single word parameters starting with @)
2184
+ const atParameterRegex = /@[\w\u00C0-\u017F\u0100-\u024F\u1E00-\u1EFF]+/gim;
2185
+ text.replace(atParameterRegex, (match) => {
2186
+ const parameterName = match.slice(1); // Remove the @ symbol
2187
+ parameters.push({
2188
+ text: match,
2189
+ notation: 'at',
2190
+ name: parameterName,
2191
+ });
2192
+ return match;
2193
+ });
2194
+ // Extract {parameter} notation (parameters in braces)
2195
+ const braceParameterRegex = /\{([^}]+)\}/gim;
2196
+ text.replace(braceParameterRegex, (match, content) => {
2197
+ // Check if the parameter has a description (parameterName: description)
2198
+ const colonIndex = content.indexOf(':');
2199
+ if (colonIndex !== -1) {
2200
+ const name = content.substring(0, colonIndex).trim();
2201
+ const description = content.substring(colonIndex + 1).trim();
2202
+ parameters.push({
2203
+ text: match,
2204
+ notation: 'brace',
2205
+ name,
2206
+ description,
2207
+ });
2208
+ }
2209
+ else {
2210
+ // Simple parameter without description
2211
+ parameters.push({
2212
+ text: match,
2213
+ notation: 'brace',
2214
+ name: content.trim(),
2215
+ });
2216
+ }
2217
+ return match;
2218
+ });
2219
+ // Remove duplicates based on name (keep the first occurrence)
2220
+ const uniqueParameters = parameters.filter((param, index, array) => {
2221
+ return array.findIndex(p => p.name === param.name) === index;
2222
+ });
2223
+ return uniqueParameters;
2224
+ }
2225
+
2090
2226
  /**
2091
2227
  * Parses basic information from agent source
2092
2228
  *
@@ -2113,10 +2249,14 @@ function parseAgentSource(agentSource) {
2113
2249
  if (!profileImageUrl) {
2114
2250
  profileImageUrl = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
2115
2251
  }
2252
+ // Parse parameters using unified approach - both @Parameter and {parameter} notations
2253
+ // are treated as the same syntax feature with unified representation
2254
+ const parameters = parseParameters(agentSource);
2116
2255
  return {
2117
2256
  agentName: parseResult.agentName,
2118
2257
  personaDescription,
2119
2258
  profileImageUrl,
2259
+ parameters,
2120
2260
  };
2121
2261
  }
2122
2262
  /**
@@ -3667,7 +3807,7 @@ parseInt(process.env.API_REQUEST_TIMEOUT || '90000');
3667
3807
  * TODO: [🧠][πŸ§œβ€β™‚οΈ] Maybe join remoteServerUrl and path into single value
3668
3808
  */
3669
3809
 
3670
- var css_248z = ".BookEditor-module_BookEditor__s-0PU{height:450px;width:100%}.BookEditor-module_bookEditorContainer__wLMwM{height:100%;width:100%}.BookEditor-module_bookEditorContainer__wLMwM.BookEditor-module_isVerbose__VQ6iL{background-color:rgba(0,0,0,.05);outline:1px dotted rgba(0,0,0,.5)}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);height:100%;overflow:hidden;position:relative;transition:box-shadow .2s ease-in-out;width:100%}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorWrapper__twppD{overflow:visible}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_bookEditorWrapper__twppD:focus-within{box-shadow:0 0 0 3px rgba(99,102,241,.4);outline:2px solid transparent;outline-offset:2px}.BookEditor-module_bookEditorWrapper__twppD.BookEditor-module_isBorderRadiusDisabled__h1I3v{border-radius:0}.BookEditor-module_bookEditorBackground__5O4wu,.BookEditor-module_bookEditorHighlight__vs37t{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.BookEditor-module_bookEditorHighlight__vs37t{-ms-overflow-style:none;color:#111827;font-size:1.125rem;margin-bottom:50px;overflow:auto;overflow-wrap:break-word;padding-left:46px;padding-right:46px;padding-top:0;scrollbar-width:none;white-space:pre-wrap;z-index:10}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorHighlight__vs37t{opacity:.5;outline:1px dotted rgba(255,0,0,.5)}.BookEditor-module_bookEditorHighlight__vs37t::-webkit-scrollbar{display:none}.BookEditor-module_bookEditorTextarea__mUURn{background-color:transparent;border:none;bottom:0;caret-color:#111827;color:transparent;font-size:1.125rem;left:0;outline:none;overflow-wrap:break-word;padding-left:46px;padding-right:46px;padding-top:18px;position:absolute;resize:none;right:0;top:0;white-space:pre-wrap}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorTextarea__mUURn{color:rgba(255,255,0,.5);outline:1px dotted rgba(255,255,0,.5)}.BookEditor-module_bookEditorTextarea__mUURn::selection{background-color:rgba(99,102,241,.6)}.BookEditor-module_bookEditorSerif__QRS7g{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.BookEditor-module_bookEditorBar__haBDz{background-color:rgba(99,102,241,.1);border-top:1px solid rgba(209,213,219,.8);bottom:0;color:rgba(17,24,39,.6);font-size:.875rem;left:0;padding:.5rem 1rem;position:absolute;right:0}.BookEditor-module_bookEditorBar__haBDz a{color:unset;text-decoration:none}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-title{color:#30a8bd;text-decoration:underline}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-keyword{color:#30a8bd}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-at-parameter{color:#e67e22;font-weight:500}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-brace-parameter{color:#8e44ad;font-weight:500}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQ0FDSSxZQUFhLENBQ2IsVUFDSixDQUVBLDhDQUVJLFdBQVksQ0FEWixVQUVKLENBRUEsaUZBRUksZ0NBQXFDLENBQ3JDLGlDQUVKLENBRUEsb0NBQ0ksMEJBQ0osQ0FFQSw0Q0FRSSxxQkFBdUIsQ0FEdkIscUNBQTBDLENBRDFDLGtCQUFtQixDQUduQixzQ0FBMkMsQ0FQM0MsV0FBWSxDQUdaLGVBQWdCLENBRGhCLGlCQUFrQixDQU1sQixxQ0FBdUMsQ0FUdkMsVUFVSixDQUNBLGdGQUVJLGdCQUVKLENBRUEsa0RBQ0ksdUVBQ0osQ0FFQSx5REFHSSx3Q0FBNkMsQ0FGN0MsNkJBQThCLENBQzlCLGtCQUVKLENBRUEsNEZBQ0ksZUFDSixDQVdBLDZGQUpJLFFBQVMsQ0FDVCxNQUFPLENBTFAsbUJBQW9CLENBQ3BCLGlCQUFrQixDQUVsQixPQUFRLENBRFIsS0E4QkosQ0F4QkEsOENBb0JJLHVCQUF3QixDQVR4QixhQUFzQixDQUN0QixrQkFBbUIsQ0FJbkIsa0JBQW1CLENBUm5CLGFBQWMsQ0FjZCx3QkFBeUIsQ0FSekIsaUJBQWtCLENBQ2xCLGtCQUFtQixDQUZuQixhQUFjLENBTWQsb0JBQXFCLENBSXJCLG9CQUFxQixDQU5yQixVQU9KLENBRUEsa0ZBRUksVUFBWSxDQUNaLG1DQUVKLENBRUEsaUVBQ0ksWUFDSixDQUVBLDZDQVdJLDRCQUE2QixDQU03QixXQUFZLENBWlosUUFBUyxDQUlULG1CQUE0QixDQUQ1QixpQkFBa0IsQ0FFbEIsa0JBQW1CLENBSm5CLE1BQU8sQ0FNUCxZQUFhLENBUWIsd0JBQXlCLENBTHpCLGlCQUFrQixDQUNsQixrQkFBbUIsQ0FGbkIsZ0JBQWlCLENBWmpCLGlCQUFrQixDQVdsQixXQUFZLENBVFosT0FBUSxDQURSLEtBQU0sQ0FnQk4sb0JBRUosQ0FFQSxpRkFFSSx3QkFBNkIsQ0FDN0IscUNBRUosQ0FFQSx3REFDSSxvQ0FDSixDQUVBLDBDQUNJLGdFQUNKLENBRUEsd0NBVUksb0NBQXlDLENBRHpDLHlDQUE4QyxDQVA5QyxRQUFTLENBS1QsdUJBQTRCLENBRDVCLGlCQUFtQixDQUhuQixNQUFPLENBS1Asa0JBQW9CLENBUHBCLGlCQUFrQixDQUdsQixPQU9KLENBRUEsMENBQ0ksV0FBWSxDQUNaLG9CQUNKLENBSUEsb0VBQ0ksYUFBYyxDQUNkLHlCQUNKLENBRUEsc0VBQ0ksYUFDSixDQUdBLDJFQUNJLGFBQWMsQ0FDZCxlQUNKLENBRUEsOEVBQ0ksYUFBYyxDQUNkLGVBQ0oiLCJmaWxlIjoiQm9va0VkaXRvci5tb2R1bGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLkJvb2tFZGl0b3Ige1xuICAgIGhlaWdodDogNDUwcHg7XG4gICAgd2lkdGg6IDEwMCU7XG59XG5cbi5ib29rRWRpdG9yQ29udGFpbmVyIHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG59XG5cbi5ib29rRWRpdG9yQ29udGFpbmVyLmlzVmVyYm9zZSB7XG4gICAgLyoqL1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC4wNSk7XG4gICAgb3V0bGluZTogMXB4IGRvdHRlZCByZ2JhKDAsIDAsIDAsIDAuNSk7XG4gICAgLyoqL1xufVxuXG4uaXNWZXJib3NlIHtcbiAgICBvdXRsaW5lOiAycHggZG90dGVkIHJnYigyNTUgMTE3IDM4KTtcbn1cblxuLmJvb2tFZGl0b3JXcmFwcGVyIHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG5cbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICBib3JkZXItcmFkaXVzOiAxcmVtO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjA5LCAyMTMsIDIxOSwgMC44KTtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTtcbiAgICBib3gtc2hhZG93OiAwIDFweCAycHggMCByZ2JhKDAsIDAsIDAsIDAuMDUpO1xuICAgIHRyYW5zaXRpb246IGJveC1zaGFkb3cgMC4ycyBlYXNlLWluLW91dDtcbn1cbi5pc1ZlcmJvc2UgLmJvb2tFZGl0b3JXcmFwcGVyIHtcbiAgICAvKiovXG4gICAgb3ZlcmZsb3c6IHZpc2libGU7XG4gICAgLyoqL1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6aG92ZXIge1xuICAgIGJveC1zaGFkb3c6IDAgNHB4IDZweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4xKSwgMCAycHggNHB4IC0xcHggcmdiYSgwLCAwLCAwLCAwLjA2KTtcbn1cblxuLmJvb2tFZGl0b3JXcmFwcGVyOmZvY3VzLXdpdGhpbiB7XG4gICAgb3V0bGluZTogMnB4IHNvbGlkIHRyYW5zcGFyZW50O1xuICAgIG91dGxpbmUtb2Zmc2V0OiAycHg7XG4gICAgYm94LXNoYWRvdzogMCAwIDAgM3B4IHJnYmEoOTksIDEwMiwgMjQxLCAwLjQpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIuaXNCb3JkZXJSYWRpdXNEaXNhYmxlZCB7XG4gICAgYm9yZGVyLXJhZGl1czogMDtcbn1cblxuLmJvb2tFZGl0b3JCYWNrZ3JvdW5kIHtcbiAgICBwb2ludGVyLWV2ZW50czogbm9uZTtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICBsZWZ0OiAwO1xufVxuXG4uYm9va0VkaXRvckhpZ2hsaWdodCB7XG4gICAgLyogVE9ETzogRFJZICovXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgIHRvcDogMDtcbiAgICByaWdodDogMDtcbiAgICBib3R0b206IDA7XG4gICAgbGVmdDogMDtcblxuICAgIG92ZXJmbG93OiBhdXRvO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuXG4gICAgY29sb3I6IHJnYigxNywgMjQsIDM5KTtcbiAgICBmb250LXNpemU6IDEuMTI1cmVtOyAvKiBUT0RPOiBEUlkgKi9cbiAgICBwYWRkaW5nLXRvcDogMDtcbiAgICBwYWRkaW5nLWxlZnQ6IDQ2cHg7XG4gICAgcGFkZGluZy1yaWdodDogNDZweDtcbiAgICBtYXJnaW4tYm90dG9tOiA1MHB4O1xuICAgIHotaW5kZXg6IDEwO1xuXG4gICAgc2Nyb2xsYmFyLXdpZHRoOiBub25lO1xuICAgIC1tcy1vdmVyZmxvdy1zdHlsZTogbm9uZTtcblxuICAgIG92ZXJmbG93LXdyYXA6IGJyZWFrLXdvcmQ7XG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwO1xufVxuXG4uaXNWZXJib3NlIC5ib29rRWRpdG9ySGlnaGxpZ2h0IHtcbiAgICAvKiovXG4gICAgb3BhY2l0eTogMC41O1xuICAgIG91dGxpbmU6IDFweCBkb3R0ZWQgcmdiYSgyNTUsIDAsIDAsIDAuNSk7XG4gICAgLyoqL1xufVxuXG4uYm9va0VkaXRvckhpZ2hsaWdodDo6LXdlYmtpdC1zY3JvbGxiYXIge1xuICAgIGRpc3BsYXk6IG5vbmU7XG59XG5cbi5ib29rRWRpdG9yVGV4dGFyZWEge1xuICAgIC8qIFRPRE86IERSWSAqL1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGxlZnQ6IDA7XG5cbiAgICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgY2FyZXQtY29sb3I6IHJnYigxNywgMjQsIDM5KTtcbiAgICBmb250LXNpemU6IDEuMTI1cmVtOyAvKiBUT0RPOiBEUlkgKi9cbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICBvdXRsaW5lOiBub25lO1xuICAgIHJlc2l6ZTogbm9uZTtcbiAgICBwYWRkaW5nLXRvcDogMThweDtcbiAgICBwYWRkaW5nLWxlZnQ6IDQ2cHg7XG4gICAgcGFkZGluZy1yaWdodDogNDZweDtcbiAgICBib3JkZXI6IG5vbmU7XG5cbiAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG4gICAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcbn1cblxuLmlzVmVyYm9zZSAuYm9va0VkaXRvclRleHRhcmVhIHtcbiAgICAvKiovXG4gICAgY29sb3I6IHJnYmEoMjU1LCAyNTUsIDAsIDAuNSk7XG4gICAgb3V0bGluZTogMXB4IGRvdHRlZCByZ2JhKDI1NSwgMjU1LCAwLCAwLjUpO1xuICAgIC8qKi9cbn1cblxuLmJvb2tFZGl0b3JUZXh0YXJlYTo6c2VsZWN0aW9uIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDk5LCAxMDIsIDI0MSwgMC42KTtcbn1cblxuLmJvb2tFZGl0b3JTZXJpZiB7XG4gICAgZm9udC1mYW1pbHk6IHVpLXNlcmlmLCBHZW9yZ2lhLCBDYW1icmlhLCAnVGltZXMgTmV3IFJvbWFuJywgVGltZXMsIHNlcmlmO1xufVxuXG4uYm9va0VkaXRvckJhciB7XG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgIGJvdHRvbTogMDtcbiAgICBsZWZ0OiAwO1xuICAgIHJpZ2h0OiAwO1xuXG4gICAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgICBjb2xvcjogcmdiYSgxNywgMjQsIDM5LCAwLjYpO1xuICAgIHBhZGRpbmc6IDAuNXJlbSAxcmVtO1xuICAgIGJvcmRlci10b3A6IDFweCBzb2xpZCByZ2JhKDIwOSwgMjEzLCAyMTksIDAuOCk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg5OSwgMTAyLCAyNDEsIDAuMSk7XG59XG5cbi5ib29rRWRpdG9yQmFyIGEge1xuICAgIGNvbG9yOiB1bnNldDtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG59XG5cbi8qIC0tLSBCb29rIHN5bnRheCBoaWdobGlnaHRpbmcgKi9cblxuLmJvb2tFZGl0b3JIaWdobGlnaHQgOmdsb2JhbCguYm9vay1oaWdobGlnaHQtdGl0bGUpIHtcbiAgICBjb2xvcjogIzMwYThiZDtcbiAgICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbn1cblxuLmJvb2tFZGl0b3JIaWdobGlnaHQgOmdsb2JhbCguYm9vay1oaWdobGlnaHQta2V5d29yZCkge1xuICAgIGNvbG9yOiAjMzBhOGJkO1xufVxuXG4vKiBb8J+noF0gUGFyYW1ldGVyIHN5bnRheCBoaWdobGlnaHRpbmcgLSBkaWZmZXJlbnQgY29sb3JzIGZvciBkaWZmZXJlbnQgcGFyYW1ldGVyIHR5cGVzICovXG4uYm9va0VkaXRvckhpZ2hsaWdodCA6Z2xvYmFsKC5ib29rLWhpZ2hsaWdodC1hdC1wYXJhbWV0ZXIpIHtcbiAgICBjb2xvcjogI2U2N2UyMjsgLyogT3JhbmdlIGNvbG9yIGZvciBAUGFyYW1ldGVyIHN5bnRheCAqL1xuICAgIGZvbnQtd2VpZ2h0OiA1MDA7XG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0IDpnbG9iYWwoLmJvb2staGlnaGxpZ2h0LWJyYWNlLXBhcmFtZXRlcikge1xuICAgIGNvbG9yOiAjOGU0NGFkOyAvKiBQdXJwbGUgY29sb3IgZm9yIHtwYXJhbWV0ZXJ9IHN5bnRheCAqL1xuICAgIGZvbnQtd2VpZ2h0OiA1MDA7XG59XG4iXX0= */";
3810
+ var css_248z = ".BookEditor-module_BookEditor__s-0PU{height:450px;width:100%}.BookEditor-module_bookEditorContainer__wLMwM{height:100%;width:100%}.BookEditor-module_bookEditorContainer__wLMwM.BookEditor-module_isVerbose__VQ6iL{background-color:rgba(0,0,0,.05);outline:1px dotted rgba(0,0,0,.5)}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);height:100%;overflow:hidden;position:relative;transition:box-shadow .2s ease-in-out;width:100%}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorWrapper__twppD{overflow:visible}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_bookEditorWrapper__twppD:focus-within{box-shadow:0 0 0 3px rgba(99,102,241,.4);outline:2px solid transparent;outline-offset:2px}.BookEditor-module_bookEditorWrapper__twppD.BookEditor-module_isBorderRadiusDisabled__h1I3v{border-radius:0}.BookEditor-module_bookEditorBackground__5O4wu,.BookEditor-module_bookEditorHighlight__vs37t{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.BookEditor-module_bookEditorHighlight__vs37t{-ms-overflow-style:none;color:#111827;font-size:1.125rem;margin-bottom:50px;overflow:auto;overflow-wrap:break-word;padding-left:46px;padding-right:46px;padding-top:0;scrollbar-width:none;white-space:pre-wrap;z-index:10}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorHighlight__vs37t{opacity:.5;outline:1px dotted rgba(255,0,0,.5)}.BookEditor-module_bookEditorHighlight__vs37t::-webkit-scrollbar{display:none}.BookEditor-module_bookEditorTextarea__mUURn{background-color:transparent;border:none;bottom:0;caret-color:#111827;color:transparent;font-size:1.125rem;left:0;outline:none;overflow-wrap:break-word;padding-left:46px;padding-right:46px;padding-top:18px;position:absolute;resize:none;right:0;top:0;white-space:pre-wrap}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorTextarea__mUURn{color:rgba(255,255,0,.5);outline:1px dotted rgba(255,255,0,.5)}.BookEditor-module_bookEditorTextarea__mUURn::selection{background-color:rgba(99,102,241,.6)}.BookEditor-module_bookEditorSerif__QRS7g{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.BookEditor-module_bookEditorBar__haBDz{background-color:rgba(99,102,241,.1);border-top:1px solid rgba(209,213,219,.8);bottom:0;color:rgba(17,24,39,.6);font-size:.875rem;left:0;padding:.5rem 1rem;position:absolute;right:0}.BookEditor-module_bookEditorBar__haBDz a{color:unset;text-decoration:none}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-title{color:#30a8bd;text-decoration:underline}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-keyword{color:#30a8bd}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-at-parameter,.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-brace-parameter,.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-parameter{color:#8e44ad;font-weight:500}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQ0FDSSxZQUFhLENBQ2IsVUFDSixDQUVBLDhDQUVJLFdBQVksQ0FEWixVQUVKLENBRUEsaUZBRUksZ0NBQXFDLENBQ3JDLGlDQUVKLENBRUEsb0NBQ0ksMEJBQ0osQ0FFQSw0Q0FRSSxxQkFBdUIsQ0FEdkIscUNBQTBDLENBRDFDLGtCQUFtQixDQUduQixzQ0FBMkMsQ0FQM0MsV0FBWSxDQUdaLGVBQWdCLENBRGhCLGlCQUFrQixDQU1sQixxQ0FBdUMsQ0FUdkMsVUFVSixDQUNBLGdGQUVJLGdCQUVKLENBRUEsa0RBQ0ksdUVBQ0osQ0FFQSx5REFHSSx3Q0FBNkMsQ0FGN0MsNkJBQThCLENBQzlCLGtCQUVKLENBRUEsNEZBQ0ksZUFDSixDQVdBLDZGQUpJLFFBQVMsQ0FDVCxNQUFPLENBTFAsbUJBQW9CLENBQ3BCLGlCQUFrQixDQUVsQixPQUFRLENBRFIsS0E4QkosQ0F4QkEsOENBb0JJLHVCQUF3QixDQVR4QixhQUFzQixDQUN0QixrQkFBbUIsQ0FJbkIsa0JBQW1CLENBUm5CLGFBQWMsQ0FjZCx3QkFBeUIsQ0FSekIsaUJBQWtCLENBQ2xCLGtCQUFtQixDQUZuQixhQUFjLENBTWQsb0JBQXFCLENBSXJCLG9CQUFxQixDQU5yQixVQU9KLENBRUEsa0ZBRUksVUFBWSxDQUNaLG1DQUVKLENBRUEsaUVBQ0ksWUFDSixDQUVBLDZDQVdJLDRCQUE2QixDQU03QixXQUFZLENBWlosUUFBUyxDQUlULG1CQUE0QixDQUQ1QixpQkFBa0IsQ0FFbEIsa0JBQW1CLENBSm5CLE1BQU8sQ0FNUCxZQUFhLENBUWIsd0JBQXlCLENBTHpCLGlCQUFrQixDQUNsQixrQkFBbUIsQ0FGbkIsZ0JBQWlCLENBWmpCLGlCQUFrQixDQVdsQixXQUFZLENBVFosT0FBUSxDQURSLEtBQU0sQ0FnQk4sb0JBRUosQ0FFQSxpRkFFSSx3QkFBNkIsQ0FDN0IscUNBRUosQ0FFQSx3REFDSSxvQ0FDSixDQUVBLDBDQUNJLGdFQUNKLENBRUEsd0NBVUksb0NBQXlDLENBRHpDLHlDQUE4QyxDQVA5QyxRQUFTLENBS1QsdUJBQTRCLENBRDVCLGlCQUFtQixDQUhuQixNQUFPLENBS1Asa0JBQW9CLENBUHBCLGlCQUFrQixDQUdsQixPQU9KLENBRUEsMENBQ0ksV0FBWSxDQUNaLG9CQUNKLENBSUEsb0VBQ0ksYUFBYyxDQUNkLHlCQUNKLENBRUEsc0VBQ0ksYUFDSixDQW1CQSxpT0FDSSxhQUFjLENBQ2QsZUFDSiIsImZpbGUiOiJCb29rRWRpdG9yLm1vZHVsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuQm9va0VkaXRvciB7XG4gICAgaGVpZ2h0OiA0NTBweDtcbiAgICB3aWR0aDogMTAwJTtcbn1cblxuLmJvb2tFZGl0b3JDb250YWluZXIge1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTtcbn1cblxuLmJvb2tFZGl0b3JDb250YWluZXIuaXNWZXJib3NlIHtcbiAgICAvKiovXG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICBvdXRsaW5lOiAxcHggZG90dGVkIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICAvKiovXG59XG5cbi5pc1ZlcmJvc2Uge1xuICAgIG91dGxpbmU6IDJweCBkb3R0ZWQgcmdiKDI1NSAxMTcgMzgpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIge1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTtcblxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIGJvcmRlci1yYWRpdXM6IDFyZW07XG4gICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyMDksIDIxMywgMjE5LCAwLjgpO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHdoaXRlO1xuICAgIGJveC1zaGFkb3c6IDAgMXB4IDJweCAwIHJnYmEoMCwgMCwgMCwgMC4wNSk7XG4gICAgdHJhbnNpdGlvbjogYm94LXNoYWRvdyAwLjJzIGVhc2UtaW4tb3V0O1xufVxuLmlzVmVyYm9zZSAuYm9va0VkaXRvcldyYXBwZXIge1xuICAgIC8qKi9cbiAgICBvdmVyZmxvdzogdmlzaWJsZTtcbiAgICAvKiovXG59XG5cbi5ib29rRWRpdG9yV3JhcHBlcjpob3ZlciB7XG4gICAgYm94LXNoYWRvdzogMCA0cHggNnB4IC0xcHggcmdiYSgwLCAwLCAwLCAwLjEpLCAwIDJweCA0cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMDYpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6Zm9jdXMtd2l0aGluIHtcbiAgICBvdXRsaW5lOiAycHggc29saWQgdHJhbnNwYXJlbnQ7XG4gICAgb3V0bGluZS1vZmZzZXQ6IDJweDtcbiAgICBib3gtc2hhZG93OiAwIDAgMCAzcHggcmdiYSg5OSwgMTAyLCAyNDEsIDAuNCk7XG59XG5cbi5ib29rRWRpdG9yV3JhcHBlci5pc0JvcmRlclJhZGl1c0Rpc2FibGVkIHtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xufVxuXG4uYm9va0VkaXRvckJhY2tncm91bmQge1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGxlZnQ6IDA7XG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0IHtcbiAgICAvKiBUT0RPOiBEUlkgKi9cbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICBsZWZ0OiAwO1xuXG4gICAgb3ZlcmZsb3c6IGF1dG87XG4gICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG5cbiAgICBjb2xvcjogcmdiKDE3LCAyNCwgMzkpO1xuICAgIGZvbnQtc2l6ZTogMS4xMjVyZW07IC8qIFRPRE86IERSWSAqL1xuICAgIHBhZGRpbmctdG9wOiAwO1xuICAgIHBhZGRpbmctbGVmdDogNDZweDtcbiAgICBwYWRkaW5nLXJpZ2h0OiA0NnB4O1xuICAgIG1hcmdpbi1ib3R0b206IDUwcHg7XG4gICAgei1pbmRleDogMTA7XG5cbiAgICBzY3JvbGxiYXItd2lkdGg6IG5vbmU7XG4gICAgLW1zLW92ZXJmbG93LXN0eWxlOiBub25lO1xuXG4gICAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcbiAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG59XG5cbi5pc1ZlcmJvc2UgLmJvb2tFZGl0b3JIaWdobGlnaHQge1xuICAgIC8qKi9cbiAgICBvcGFjaXR5OiAwLjU7XG4gICAgb3V0bGluZTogMXB4IGRvdHRlZCByZ2JhKDI1NSwgMCwgMCwgMC41KTtcbiAgICAvKiovXG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0Ojotd2Via2l0LXNjcm9sbGJhciB7XG4gICAgZGlzcGxheTogbm9uZTtcbn1cblxuLmJvb2tFZGl0b3JUZXh0YXJlYSB7XG4gICAgLyogVE9ETzogRFJZICovXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgIHRvcDogMDtcbiAgICByaWdodDogMDtcbiAgICBib3R0b206IDA7XG4gICAgbGVmdDogMDtcblxuICAgIGNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICBjYXJldC1jb2xvcjogcmdiKDE3LCAyNCwgMzkpO1xuICAgIGZvbnQtc2l6ZTogMS4xMjVyZW07IC8qIFRPRE86IERSWSAqL1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgIG91dGxpbmU6IG5vbmU7XG4gICAgcmVzaXplOiBub25lO1xuICAgIHBhZGRpbmctdG9wOiAxOHB4O1xuICAgIHBhZGRpbmctbGVmdDogNDZweDtcbiAgICBwYWRkaW5nLXJpZ2h0OiA0NnB4O1xuICAgIGJvcmRlcjogbm9uZTtcblxuICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcbiAgICBvdmVyZmxvdy13cmFwOiBicmVhay13b3JkO1xufVxuXG4uaXNWZXJib3NlIC5ib29rRWRpdG9yVGV4dGFyZWEge1xuICAgIC8qKi9cbiAgICBjb2xvcjogcmdiYSgyNTUsIDI1NSwgMCwgMC41KTtcbiAgICBvdXRsaW5lOiAxcHggZG90dGVkIHJnYmEoMjU1LCAyNTUsIDAsIDAuNSk7XG4gICAgLyoqL1xufVxuXG4uYm9va0VkaXRvclRleHRhcmVhOjpzZWxlY3Rpb24ge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoOTksIDEwMiwgMjQxLCAwLjYpO1xufVxuXG4uYm9va0VkaXRvclNlcmlmIHtcbiAgICBmb250LWZhbWlseTogdWktc2VyaWYsIEdlb3JnaWEsIENhbWJyaWEsICdUaW1lcyBOZXcgUm9tYW4nLCBUaW1lcywgc2VyaWY7XG59XG5cbi5ib29rRWRpdG9yQmFyIHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgYm90dG9tOiAwO1xuICAgIGxlZnQ6IDA7XG4gICAgcmlnaHQ6IDA7XG5cbiAgICBmb250LXNpemU6IDAuODc1cmVtO1xuICAgIGNvbG9yOiByZ2JhKDE3LCAyNCwgMzksIDAuNik7XG4gICAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHJnYmEoMjA5LCAyMTMsIDIxOSwgMC44KTtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDk5LCAxMDIsIDI0MSwgMC4xKTtcbn1cblxuLmJvb2tFZGl0b3JCYXIgYSB7XG4gICAgY29sb3I6IHVuc2V0O1xuICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbn1cblxuLyogLS0tIEJvb2sgc3ludGF4IGhpZ2hsaWdodGluZyAqL1xuXG4uYm9va0VkaXRvckhpZ2hsaWdodCA6Z2xvYmFsKC5ib29rLWhpZ2hsaWdodC10aXRsZSkge1xuICAgIGNvbG9yOiAjMzBhOGJkO1xuICAgIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lO1xufVxuXG4uYm9va0VkaXRvckhpZ2hsaWdodCA6Z2xvYmFsKC5ib29rLWhpZ2hsaWdodC1rZXl3b3JkKSB7XG4gICAgY29sb3I6ICMzMGE4YmQ7XG59XG5cbi8qIFvwn6egXSBQYXJhbWV0ZXIgc3ludGF4IGhpZ2hsaWdodGluZyAtIHVuaWZpZWQgY29sb3IgZm9yIGJvdGggcGFyYW1ldGVyIG5vdGF0aW9uc1xuICogVGhlIEJvb2sgbGFuZ3VhZ2Ugc3VwcG9ydHMgdHdvIGRpZmZlcmVudCBub3RhdGlvbnMgZm9yIHRoZSBzYW1lIHN5bnRheCBmZWF0dXJlIC0gcGFyYW1ldGVyczpcbiAqIDEuIEBQYXJhbWV0ZXIgLSBzaW5nbGUgd29yZCBwYXJhbWV0ZXIgc3RhcnRpbmcgd2l0aCBAXG4gKiAyLiB7cGFyYW1ldGVyTmFtZX0gb3Ige3BhcmFtZXRlciB3aXRoIG11bHRpcGxlIHdvcmRzfSBvciB7cGFyYW1ldGVyTmFtZTogZGVzY3JpcHRpb24gdGV4dH1cbiAqIEJvdGggbm90YXRpb25zIHJlcHJlc2VudCB0aGUgc2FtZSBzZW1hbnRpYyBjb25jZXB0IGFuZCBhcmUgaGlnaGxpZ2h0ZWQgd2l0aCB0aGUgc2FtZSBwdXJwbGUgY29sb3IuXG4gKi9cbi5ib29rRWRpdG9ySGlnaGxpZ2h0IDpnbG9iYWwoLmJvb2staGlnaGxpZ2h0LXBhcmFtZXRlcikge1xuICAgIGNvbG9yOiAjOGU0NGFkOyAvKiBQdXJwbGUgY29sb3IgZm9yIGFsbCBwYXJhbWV0ZXIgc3ludGF4ZXMgKi9cbiAgICBmb250LXdlaWdodDogNTAwO1xufVxuXG4vKiBMZWdhY3kgY2xhc3NlcyBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSAtIGJvdGggdXNlIHRoZSBzYW1lIHB1cnBsZSBjb2xvciBub3cgKi9cbi5ib29rRWRpdG9ySGlnaGxpZ2h0IDpnbG9iYWwoLmJvb2staGlnaGxpZ2h0LWF0LXBhcmFtZXRlcikge1xuICAgIGNvbG9yOiAjOGU0NGFkOyAvKiBQdXJwbGUgY29sb3IgKHVuaWZpZWQgd2l0aCBicmFjZSBwYXJhbWV0ZXJzKSAqL1xuICAgIGZvbnQtd2VpZ2h0OiA1MDA7XG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0IDpnbG9iYWwoLmJvb2staGlnaGxpZ2h0LWJyYWNlLXBhcmFtZXRlcikge1xuICAgIGNvbG9yOiAjOGU0NGFkOyAvKiBQdXJwbGUgY29sb3IgKHNhbWUgYXMgYXQgcGFyYW1ldGVycykgKi9cbiAgICBmb250LXdlaWdodDogNTAwO1xufVxuIl19 */";
3671
3811
  var styles = {"BookEditor":"BookEditor-module_BookEditor__s-0PU","bookEditorContainer":"BookEditor-module_bookEditorContainer__wLMwM","isVerbose":"BookEditor-module_isVerbose__VQ6iL","bookEditorWrapper":"BookEditor-module_bookEditorWrapper__twppD","isBorderRadiusDisabled":"BookEditor-module_isBorderRadiusDisabled__h1I3v","bookEditorBackground":"BookEditor-module_bookEditorBackground__5O4wu","bookEditorHighlight":"BookEditor-module_bookEditorHighlight__vs37t","bookEditorTextarea":"BookEditor-module_bookEditorTextarea__mUURn","bookEditorSerif":"BookEditor-module_bookEditorSerif__QRS7g","bookEditorBar":"BookEditor-module_bookEditorBar__haBDz"};
3672
3812
  styleInject(css_248z);
3673
3813
 
@@ -3978,17 +4118,31 @@ function BookEditorInner(props) {
3978
4118
  const allTypes = getAllCommitmentDefinitions().map(({ type }) => String(type));
3979
4119
  // Filter out 'META' from regular commitments since we'll handle it specially
3980
4120
  const nonMetaTypes = allTypes.filter((t) => t !== 'META');
3981
- const pattern = `\\b(?:${nonMetaTypes.map((t) => escapeRegex(t)).join('|')})\\b`;
4121
+ // Only match commitments at the beginning of lines (after newline or at start of text)
4122
+ // This follows the same logic as parsing in createCommitmentRegex.ts
4123
+ const pattern = `(^|\\n)\\s*(?:${nonMetaTypes.map((t) => escapeRegex(t)).join('|')})\\b`;
3982
4124
  return new RegExp(pattern, 'gmi');
3983
4125
  }, []);
3984
4126
  const metaRegex = useMemo(() => {
3985
- // Pattern to match META followed by one or more uppercase words
3986
- // This will match: META IMAGE, META LINK, META TITLE, META DESCRIPTION, META CUSTOM FOO, etc.
3987
- return /\bMETA\s+(?:[A-Z]+(?:\s+[A-Z]+)*)/gim;
4127
+ // Pattern to match META followed by exactly one uppercase word (DRY principle - single pattern for all META commitments)
4128
+ // Only match at the beginning of lines, consistent with other commitments and parsing logic
4129
+ // This will match: META IMAGE, META LINK, META TITLE, META DESCRIPTION, META FOO, etc.
4130
+ // But NOT multiple words like "META IMAGE SOMETHING" - only "META IMAGE" part will be highlighted
4131
+ return /(^|\n)\s*META\s+[A-Z]+\b/gim;
3988
4132
  }, []);
3989
- // [🧠] Parameter syntax highlighting - two types:
3990
- // 1. @Parameter (single word parameters starting with @)
3991
- // 2. {parameterName} or {parameter with multiple words} or {parameterName: description text}
4133
+ // [🧠] Parameter syntax highlighting - unified approach for two different notations of the same syntax feature
4134
+ //
4135
+ // IMPORTANT PRINCIPLE: The Book language supports parameters as a single syntax feature
4136
+ // expressed through two different notations:
4137
+ // 1. @Parameter (single word parameters starting with @) - e.g., @name, @ěőčřžý
4138
+ // 2. {parameterName} (parameters in braces) - e.g., {name}, {user name}, {name: description}
4139
+ //
4140
+ // Both notations represent the same semantic concept - parameters - and should be:
4141
+ // - Highlighted with the same color (purple)
4142
+ // - Parsed using the same logic
4143
+ // - Treated identically in the syntax processing
4144
+ //
4145
+ // This follows the DRY principle: don't repeat yourself for the same syntax feature.
3992
4146
  const atParameterRegex = useMemo(() => {
3993
4147
  // Match @followed by word characters (letters, numbers, underscore) and unicode letters (for @ěőčřžý)
3994
4148
  return /@[\w\u00C0-\u017F\u0100-\u024F\u1E00-\u1EFF]+/gim;
@@ -3997,6 +4151,43 @@ function BookEditorInner(props) {
3997
4151
  // Match {parameter} or {parameter: description} - content inside braces
3998
4152
  return /\{[^}]+\}/gim;
3999
4153
  }, []);
4154
+ /**
4155
+ * Unified parameter extraction function that handles both parameter notations
4156
+ *
4157
+ * This function embodies the principle that @Parameter and {parameter} are
4158
+ * two different notations for the same syntax feature - parameters.
4159
+ *
4160
+ * @param text - Text to extract parameters from
4161
+ * @returns Array of parameter ranges with unified type
4162
+ */
4163
+ const extractUnifiedParameters = useCallback((text) => {
4164
+ const parameters = [];
4165
+ // Extract @Parameter notation (first notation)
4166
+ text.replace(atParameterRegex, (match, ...args) => {
4167
+ const index = args[args.length - 2];
4168
+ parameters.push({
4169
+ start: index,
4170
+ end: index + match.length,
4171
+ type: 'parameter',
4172
+ notation: 'at',
4173
+ text: match,
4174
+ });
4175
+ return match;
4176
+ });
4177
+ // Extract {parameter} notation (second notation)
4178
+ text.replace(braceParameterRegex, (match, ...args) => {
4179
+ const index = args[args.length - 2];
4180
+ parameters.push({
4181
+ start: index,
4182
+ end: index + match.length,
4183
+ type: 'parameter',
4184
+ notation: 'brace',
4185
+ text: match,
4186
+ });
4187
+ return match;
4188
+ });
4189
+ return parameters.sort((a, b) => a.start - b.start);
4190
+ }, [atParameterRegex, braceParameterRegex]);
4000
4191
  const highlightedHtml = useMemo(() => {
4001
4192
  const text = value !== null && value !== void 0 ? value : '';
4002
4193
  let lastIndex = 0;
@@ -4005,47 +4196,43 @@ function BookEditorInner(props) {
4005
4196
  // First, handle META commitments (they take priority)
4006
4197
  text.replace(metaRegex, (match, ...args) => {
4007
4198
  const index = args[args.length - 2];
4008
- processedRanges.push({ start: index, end: index + match.length, type: 'keyword' });
4199
+ // Adjust index to skip the newline character if present at the beginning of match
4200
+ const adjustedStart = match.startsWith('\n') ? index + 1 : index;
4201
+ const adjustedMatch = match.startsWith('\n') ? match.slice(1) : match;
4202
+ processedRanges.push({ start: adjustedStart, end: adjustedStart + adjustedMatch.length, type: 'keyword' });
4009
4203
  return match;
4010
4204
  });
4011
4205
  // Then handle regular commitment types, avoiding overlaps with META ranges
4012
4206
  text.replace(typeRegex, (match, ...args) => {
4013
4207
  const index = args[args.length - 2];
4014
- const matchEnd = index + match.length;
4208
+ // Adjust index to skip the newline character if present at the beginning of match
4209
+ const adjustedStart = match.startsWith('\n') ? index + 1 : index;
4210
+ const adjustedMatch = match.startsWith('\n') ? match.slice(1) : match;
4211
+ const matchEnd = adjustedStart + adjustedMatch.length;
4015
4212
  // Check if this match overlaps with any existing range
4016
- const overlaps = processedRanges.some((range) => (index >= range.start && index < range.end) ||
4213
+ const overlaps = processedRanges.some((range) => (adjustedStart >= range.start && adjustedStart < range.end) ||
4017
4214
  (matchEnd > range.start && matchEnd <= range.end) ||
4018
- (index < range.start && matchEnd > range.end));
4215
+ (adjustedStart < range.start && matchEnd > range.end));
4019
4216
  if (!overlaps) {
4020
- processedRanges.push({ start: index, end: matchEnd, type: 'keyword' });
4217
+ processedRanges.push({ start: adjustedStart, end: matchEnd, type: 'keyword' });
4021
4218
  }
4022
4219
  return match;
4023
4220
  });
4024
- // Handle @Parameter syntax (single word parameters starting with @)
4025
- text.replace(atParameterRegex, (match, ...args) => {
4026
- const index = args[args.length - 2];
4027
- const matchEnd = index + match.length;
4028
- // Check if this match overlaps with any existing range
4029
- const overlaps = processedRanges.some((range) => (index >= range.start && index < range.end) ||
4030
- (matchEnd > range.start && matchEnd <= range.end) ||
4031
- (index < range.start && matchEnd > range.end));
4221
+ // Handle parameters using the unified extraction function - both @Parameter and {parameter} notations
4222
+ // are treated as the same syntax feature with unified highlighting
4223
+ const unifiedParameters = extractUnifiedParameters(text);
4224
+ unifiedParameters.forEach((param) => {
4225
+ // Check if this parameter overlaps with any existing range
4226
+ const overlaps = processedRanges.some((range) => (param.start >= range.start && param.start < range.end) ||
4227
+ (param.end > range.start && param.end <= range.end) ||
4228
+ (param.start < range.start && param.end > range.end));
4032
4229
  if (!overlaps) {
4033
- processedRanges.push({ start: index, end: matchEnd, type: 'at-parameter' });
4034
- }
4035
- return match;
4036
- });
4037
- // Handle {parameter} syntax (parameters in braces)
4038
- text.replace(braceParameterRegex, (match, ...args) => {
4039
- const index = args[args.length - 2];
4040
- const matchEnd = index + match.length;
4041
- // Check if this match overlaps with any existing range
4042
- const overlaps = processedRanges.some((range) => (index >= range.start && index < range.end) ||
4043
- (matchEnd > range.start && matchEnd <= range.end) ||
4044
- (index < range.start && matchEnd > range.end));
4045
- if (!overlaps) {
4046
- processedRanges.push({ start: index, end: matchEnd, type: 'brace-parameter' });
4230
+ processedRanges.push({
4231
+ start: param.start,
4232
+ end: param.end,
4233
+ type: 'parameter'
4234
+ });
4047
4235
  }
4048
- return match;
4049
4236
  });
4050
4237
  // Sort ranges by start position
4051
4238
  processedRanges.sort((a, b) => a.start - b.start);
@@ -4060,11 +4247,9 @@ function BookEditorInner(props) {
4060
4247
  case 'keyword':
4061
4248
  cssClass = 'book-highlight-keyword';
4062
4249
  break;
4063
- case 'at-parameter':
4064
- cssClass = 'book-highlight-at-parameter';
4065
- break;
4066
- case 'brace-parameter':
4067
- cssClass = 'book-highlight-brace-parameter';
4250
+ case 'parameter':
4251
+ // Use the unified parameter class, but maintain backward compatibility
4252
+ cssClass = 'book-highlight-parameter';
4068
4253
  break;
4069
4254
  default:
4070
4255
  cssClass = 'book-highlight-keyword';
@@ -4080,7 +4265,7 @@ function BookEditorInner(props) {
4080
4265
  lines[0] = `<span class="book-highlight-title">${lines[0]}</span>`;
4081
4266
  }
4082
4267
  return lines.join('\n');
4083
- }, [value, typeRegex, metaRegex, atParameterRegex, braceParameterRegex]);
4268
+ }, [value, typeRegex, metaRegex, extractUnifiedParameters]);
4084
4269
  return (jsx("div", { className: classNames(styles.bookEditorContainer, isVerbose && styles.isVerbose, className), children: jsxs("div", { className: classNames(styles.bookEditorWrapper, effectiveFontClassName, isBorderRadiusDisabled && styles.isBorderRadiusDisabled), children: [jsx("div", { "aria-hidden": true, className: styles.bookEditorBackground, style: { backgroundImage: 'none' } }), jsx("pre", { ref: highlightRef, "aria-hidden": true, className: `${styles.bookEditorHighlight} ${effectiveFontClassName}`, style: {
4085
4270
  lineHeight: `${lineHeight}px`,
4086
4271
  backgroundImage: `linear-gradient(90deg, transparent 30px, rgba(59,130,246,0.3) 30px, rgba(59,130,246,0.3) 31px, transparent 31px), repeating-linear-gradient(0deg, transparent, transparent calc(${lineHeight}px - 1px), rgba(0,0,0,0.06) ${lineHeight}px)`,