ei-tui 0.1.3

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 (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -0
  3. package/package.json +63 -0
  4. package/src/README.md +96 -0
  5. package/src/cli/README.md +47 -0
  6. package/src/cli/commands/facts.ts +25 -0
  7. package/src/cli/commands/people.ts +25 -0
  8. package/src/cli/commands/quotes.ts +19 -0
  9. package/src/cli/commands/topics.ts +25 -0
  10. package/src/cli/commands/traits.ts +25 -0
  11. package/src/cli/retrieval.ts +269 -0
  12. package/src/cli.ts +176 -0
  13. package/src/core/AGENTS.md +104 -0
  14. package/src/core/embedding-service.ts +241 -0
  15. package/src/core/handlers/index.ts +1057 -0
  16. package/src/core/index.ts +4 -0
  17. package/src/core/llm-client.ts +265 -0
  18. package/src/core/model-context-windows.ts +49 -0
  19. package/src/core/orchestrators/ceremony.ts +500 -0
  20. package/src/core/orchestrators/extraction-chunker.ts +138 -0
  21. package/src/core/orchestrators/human-extraction.ts +457 -0
  22. package/src/core/orchestrators/index.ts +28 -0
  23. package/src/core/orchestrators/persona-generation.ts +76 -0
  24. package/src/core/orchestrators/persona-topics.ts +117 -0
  25. package/src/core/personas/index.ts +5 -0
  26. package/src/core/personas/opencode-agent.ts +81 -0
  27. package/src/core/processor.ts +1413 -0
  28. package/src/core/queue-processor.ts +197 -0
  29. package/src/core/state/checkpoints.ts +68 -0
  30. package/src/core/state/human.ts +176 -0
  31. package/src/core/state/index.ts +5 -0
  32. package/src/core/state/personas.ts +217 -0
  33. package/src/core/state/queue.ts +144 -0
  34. package/src/core/state-manager.ts +347 -0
  35. package/src/core/types.ts +421 -0
  36. package/src/core/utils/decay.ts +33 -0
  37. package/src/index.ts +1 -0
  38. package/src/integrations/opencode/importer.ts +896 -0
  39. package/src/integrations/opencode/index.ts +16 -0
  40. package/src/integrations/opencode/json-reader.ts +304 -0
  41. package/src/integrations/opencode/reader-factory.ts +35 -0
  42. package/src/integrations/opencode/sqlite-reader.ts +189 -0
  43. package/src/integrations/opencode/types.ts +244 -0
  44. package/src/prompts/AGENTS.md +62 -0
  45. package/src/prompts/ceremony/description-check.ts +47 -0
  46. package/src/prompts/ceremony/expire.ts +30 -0
  47. package/src/prompts/ceremony/explore.ts +60 -0
  48. package/src/prompts/ceremony/index.ts +11 -0
  49. package/src/prompts/ceremony/types.ts +42 -0
  50. package/src/prompts/generation/descriptions.ts +91 -0
  51. package/src/prompts/generation/index.ts +15 -0
  52. package/src/prompts/generation/persona.ts +155 -0
  53. package/src/prompts/generation/seeds.ts +31 -0
  54. package/src/prompts/generation/types.ts +47 -0
  55. package/src/prompts/heartbeat/check.ts +179 -0
  56. package/src/prompts/heartbeat/ei.ts +208 -0
  57. package/src/prompts/heartbeat/index.ts +15 -0
  58. package/src/prompts/heartbeat/types.ts +70 -0
  59. package/src/prompts/human/fact-scan.ts +152 -0
  60. package/src/prompts/human/index.ts +32 -0
  61. package/src/prompts/human/item-match.ts +74 -0
  62. package/src/prompts/human/item-update.ts +322 -0
  63. package/src/prompts/human/person-scan.ts +115 -0
  64. package/src/prompts/human/topic-scan.ts +135 -0
  65. package/src/prompts/human/trait-scan.ts +115 -0
  66. package/src/prompts/human/types.ts +127 -0
  67. package/src/prompts/index.ts +90 -0
  68. package/src/prompts/message-utils.ts +39 -0
  69. package/src/prompts/persona/index.ts +16 -0
  70. package/src/prompts/persona/topics-match.ts +69 -0
  71. package/src/prompts/persona/topics-scan.ts +98 -0
  72. package/src/prompts/persona/topics-update.ts +157 -0
  73. package/src/prompts/persona/traits.ts +117 -0
  74. package/src/prompts/persona/types.ts +74 -0
  75. package/src/prompts/response/index.ts +147 -0
  76. package/src/prompts/response/sections.ts +355 -0
  77. package/src/prompts/response/types.ts +38 -0
  78. package/src/prompts/validation/ei.ts +93 -0
  79. package/src/prompts/validation/index.ts +6 -0
  80. package/src/prompts/validation/types.ts +22 -0
  81. package/src/storage/crypto.ts +96 -0
  82. package/src/storage/index.ts +5 -0
  83. package/src/storage/interface.ts +9 -0
  84. package/src/storage/local.ts +79 -0
  85. package/src/storage/merge.ts +69 -0
  86. package/src/storage/remote.ts +145 -0
  87. package/src/templates/welcome.ts +91 -0
  88. package/tui/README.md +62 -0
  89. package/tui/bunfig.toml +4 -0
  90. package/tui/src/app.tsx +55 -0
  91. package/tui/src/commands/archive.tsx +93 -0
  92. package/tui/src/commands/context.tsx +124 -0
  93. package/tui/src/commands/delete.tsx +71 -0
  94. package/tui/src/commands/details.tsx +41 -0
  95. package/tui/src/commands/editor.tsx +46 -0
  96. package/tui/src/commands/help.tsx +12 -0
  97. package/tui/src/commands/me.tsx +145 -0
  98. package/tui/src/commands/model.ts +47 -0
  99. package/tui/src/commands/new.ts +31 -0
  100. package/tui/src/commands/pause.ts +46 -0
  101. package/tui/src/commands/persona.tsx +58 -0
  102. package/tui/src/commands/provider.tsx +124 -0
  103. package/tui/src/commands/quit.ts +22 -0
  104. package/tui/src/commands/quotes.tsx +172 -0
  105. package/tui/src/commands/registry.test.ts +137 -0
  106. package/tui/src/commands/registry.ts +130 -0
  107. package/tui/src/commands/resume.ts +39 -0
  108. package/tui/src/commands/setsync.tsx +43 -0
  109. package/tui/src/commands/settings.tsx +83 -0
  110. package/tui/src/components/ConfirmOverlay.tsx +51 -0
  111. package/tui/src/components/ConflictOverlay.tsx +78 -0
  112. package/tui/src/components/HelpOverlay.tsx +69 -0
  113. package/tui/src/components/Layout.tsx +24 -0
  114. package/tui/src/components/MessageList.tsx +174 -0
  115. package/tui/src/components/PersonaListOverlay.tsx +186 -0
  116. package/tui/src/components/PromptInput.tsx +145 -0
  117. package/tui/src/components/ProviderListOverlay.tsx +208 -0
  118. package/tui/src/components/QuotesOverlay.tsx +157 -0
  119. package/tui/src/components/Sidebar.tsx +95 -0
  120. package/tui/src/components/StatusBar.tsx +77 -0
  121. package/tui/src/components/WelcomeOverlay.tsx +73 -0
  122. package/tui/src/context/ei.tsx +623 -0
  123. package/tui/src/context/keyboard.tsx +164 -0
  124. package/tui/src/context/overlay.tsx +53 -0
  125. package/tui/src/index.tsx +8 -0
  126. package/tui/src/storage/file.ts +185 -0
  127. package/tui/src/util/duration.ts +32 -0
  128. package/tui/src/util/editor.ts +188 -0
  129. package/tui/src/util/logger.ts +109 -0
  130. package/tui/src/util/persona-editor.tsx +181 -0
  131. package/tui/src/util/provider-editor.tsx +168 -0
  132. package/tui/src/util/syntax.ts +35 -0
  133. package/tui/src/util/yaml-serializers.ts +755 -0
@@ -0,0 +1,115 @@
1
+ import type { PersonScanPromptData, PromptOutput } from "./types.js";
2
+ import { formatMessagesAsPlaceholders } from "../message-utils.js";
3
+
4
+ export function buildHumanPersonScanPrompt(data: PersonScanPromptData): PromptOutput {
5
+ if (!data.persona_name) {
6
+ throw new Error("buildHumanPersonScanPrompt: persona_name is required");
7
+ }
8
+
9
+ const personaName = data.persona_name;
10
+ const knownPersonasList = data.known_persona_names.length > 0
11
+ ? data.known_persona_names.map(name => ` + ${name}`).join('\n')
12
+ : ' + (none)';
13
+
14
+ const taskFragment = `# Task
15
+
16
+ You are scanning a conversation to quickly identify PEOPLE of interest TO the HUMAN USER. Your ONLY job is to spot mentions of PEOPLE. Do NOT analyze them deeply. Just detect and flag.`;
17
+
18
+ const specificNeedsFragment = `## Specific Needs
19
+
20
+ Your job is to quickly identify:
21
+ 1. Which PEOPLE were mentioned or relevant
22
+ a. Only flag PEOPLE that were actually discussed, not just tangentially related
23
+ b. Be CONSERVATIVE - only suggest genuinely important, long-term relevant PEOPLE
24
+ i. Ignore: greetings, small talk, one-off mentions, jokes
25
+ c. Be CLEAR - state your \`reason\` for including this PERSON with any evidence you used`;
26
+
27
+ const guidelinesFragment = `## Guidelines
28
+
29
+ 1. **Unknown Types and Names of PEOPLE**
30
+ a. In some conversations, it may be impossible to identify which "Brother" or which "Bob" the user is referring to.
31
+ - Use "Unknown" for the missing field and explain in the \`reason\`
32
+ - This will trigger a later validation step to get more information!
33
+ b. If you're adding a NEW PERSON, be as specific as you can, for example:
34
+ - { "type_of_person": "Unknown", "name_of_person": "Alice from work", "reason": "Mentioned but relationship unclear" }
35
+ - { "type_of_person": "Sibling", "name_of_person": "Name Unknown", "reason": "Mentioned a sibling, name not given" }
36
+
37
+ **A PERSON Is**
38
+ * Immediate Family: Father, Husband, Son, Brother, Mother, Wife, Daughter, Sister (and step/in-law variants)
39
+ * Extended Family: Grandfather, Grandmother, Aunt, Uncle, Cousin, Niece, Nephew
40
+ * Close Acquaintance
41
+ * Friend
42
+ * Lover / Love Interest
43
+ * Fiance / Spouse
44
+ * Coworker
45
+
46
+ **A PERSON Is NOT**
47
+ - Biographical data: Birthday, Location, Job, Marital Status, Gender, Eye Color, Hair Color
48
+ - Other unchangeable Data: Wedding Day, Allergies
49
+ - Trait: Personality patterns, communication style, behavioral tendencies
50
+ - General Topic: Interests, Hobbies, General subjects
51
+ - Personas: AI personas they discuss
52
+ * Known Personas:
53
+ ${knownPersonasList}
54
+ - Characters: Fictitious entities from books, movies, stories, media, etc.`;
55
+
56
+ const criticalFragment = `# CRITICAL INSTRUCTIONS
57
+
58
+ ONLY ANALYZE the "Most Recent Messages" in the following conversation. The "Earlier Conversation" is provided for your context and has already been processed!
59
+
60
+ The JSON format is:
61
+
62
+ \`\`\`json
63
+ {
64
+ "people": [
65
+ {
66
+ "type_of_person": "Father|Friend|Love Interest|Unknown|etc.",
67
+ "name_of_person": "Bob|Alice|Charles|Name Unknown|etc.",
68
+ "reason": "User stated...|Assumed from..."
69
+ }
70
+ ]
71
+ }
72
+ \`\`\`
73
+
74
+ **Return JSON only.**`;
75
+
76
+ const system = `${taskFragment}
77
+
78
+ ${specificNeedsFragment}
79
+
80
+ ${guidelinesFragment}
81
+
82
+ ${criticalFragment}`;
83
+
84
+ const earlierSection = data.messages_context.length > 0
85
+ ? `## Earlier Conversation
86
+ ${formatMessagesAsPlaceholders(data.messages_context, personaName)}
87
+
88
+ `
89
+ : '';
90
+
91
+ const recentSection = `## Most Recent Messages
92
+ ${formatMessagesAsPlaceholders(data.messages_analyze, personaName)}`;
93
+
94
+ const user = `# Conversation
95
+ ${earlierSection}${recentSection}
96
+
97
+ ---
98
+
99
+ Scan the "Most Recent Messages" for PEOPLE mentioned by the human user.
100
+
101
+ **Return JSON:**
102
+ \`\`\`json
103
+ {
104
+ "people": [
105
+ {
106
+ "type_of_person": "Father|Friend|Love Interest|Unknown|etc.",
107
+ "name_of_person": "Bob|Alice|Charles|Name Unknown|etc.",
108
+ "reason": "User stated..."
109
+ }
110
+ ]
111
+ }
112
+ \`\`\``;
113
+
114
+ return { system, user };
115
+ }
@@ -0,0 +1,135 @@
1
+ import type { TopicScanPromptData, PromptOutput } from "./types.js";
2
+ import { formatMessagesAsPlaceholders } from "../message-utils.js";
3
+
4
+ export function buildHumanTopicScanPrompt(data: TopicScanPromptData): PromptOutput {
5
+ if (!data.persona_name) {
6
+ throw new Error("buildHumanTopicScanPrompt: persona_name is required");
7
+ }
8
+
9
+ const personaName = data.persona_name;
10
+
11
+ const taskFragment = `# Task
12
+
13
+ You are scanning a conversation to quickly identify TOPICS of interest TO the HUMAN USER. Your ONLY job is to spot mentions of TOPICS. Do NOT analyze them deeply. Just detect and flag.`;
14
+
15
+ const specificNeedsFragment = `## Specific Needs
16
+
17
+ Your job is to quickly identify:
18
+ 1. Which TOPICS were mentioned or relevant
19
+ a. Only flag TOPICS that were actually discussed, not just tangentially related
20
+ b. Be CONSERVATIVE - only suggest genuinely important, long-term relevant TOPICS
21
+ c. Be CLEAR - state your \`reason\` for including this TOPIC with any evidence you used
22
+
23
+ The goal of the system is to remember important TOPICS to the HUMAN USER in order to ask about them in the future.`;
24
+
25
+ const guidelinesFragment = `## Guidelines
26
+
27
+ # A TOPIC Is:
28
+
29
+ A meaningful subject or concept relevant to the HUMAN USER. It is:
30
+
31
+ - **Specific and Contextual:** Not a broad category or just a list of isolated facts. It must have narrative or direct relevance in the conversation.
32
+
33
+ 1. **Primary Focus** - Capture the main idea of the conversation, not minute details
34
+ 2. **Participation** - Things the HUMAN USER does or wants to do
35
+ 3. **Interests** - Hobbies or concepts they spend time on BY CHOICE
36
+ 4. **Responsibilities** - Tasks or requirements that occupy their time BY NECESSITY
37
+ 5. **Knowledge** - Ideas they are exploring or learning about, or are expert in
38
+ 6. **Dreams** - Wild ideas, hopes for the future, or vision of an ideal state
39
+ 7. **Conflicts** - Things they have difficulty with or are frustrated with
40
+ 8. **Concerns** - Ideas they express worry over
41
+ 9. **Stories and Characters** - Extended narratives they share (more than a sentence or two)
42
+ 10. **Location** - Favorite places, travel destinations
43
+ 11. **Preferences** - "I like {thing}" or "I hate {thing}" statements`;
44
+
45
+ const doNotCaptureFragment = `# **IMPORTANT** The Following Are NOT TOPICS
46
+
47
+ # The system tracks FACTS, TRAITS, and PEOPLE as separate types. Do NOT capture:
48
+
49
+ ## FACTS - Tracked Separately
50
+ - **Biographical Data (Do NOT Capture):** Name, Nickname, Birthday, Location, Job, Marital Status, Gender, Eye Color, Hair Color.
51
+ > **CRITICAL:** The HUMAN USER's name itself, or a collection of their basic biographical facts, is NEVER a TOPIC. Even if multiple biographical facts are mentioned together (e.g., "My name is John, I live in NYC, and I'm a software engineer"), do not summarize them as a 'topic' about the user's identity.
52
+ - Other Important Dates: Wedding Anniversary, Job Anniversary
53
+ - Health & Well-being: Allergies, Medical Conditions, Dietary Restrictions
54
+
55
+ > NOTE: Many FACTS have stories/topics around them.
56
+ > "My birthday is May 26th" is a FACT. "A goat jumped out of my birthday cake" is a TOPIC.
57
+
58
+ ## TRAITS - Tracked Separately
59
+ * Personality Patterns, Communication style, Behavioral tendencies
60
+ * Cognitive Style, Emotional Traits, Work Ethic, Social Orientation
61
+
62
+ > NOTE: Many TRAITS have stories/topics around them.
63
+ > "I'm a visual learner" is a TRAIT. "I saw a picture of an atom and I FINALLY GET IT" is a TOPIC.
64
+
65
+ ## PEOPLE / Relationships - Tracked Separately
66
+ - Immediate family, Extended family, Friends, Coworkers, etc.
67
+
68
+ > NOTE: Many PEOPLE have stories/topics around them.
69
+ > "Sarah is my dream girl" is a PERSON. "I hope Sarah and I get married on the moon" is a TOPIC.
70
+
71
+ ## AI PERSONAS - Tracked Separately
72
+ - Do NOT record any stories or details about PERSONAS as TOPICS`;
73
+
74
+ const criticalFragment = `# CRITICAL INSTRUCTIONS
75
+
76
+ ONLY ANALYZE the "Most Recent Messages" in the following conversation. The "Earlier Conversation" is provided for your context and has already been processed!
77
+
78
+ The JSON format is:
79
+
80
+ \`\`\`json
81
+ {
82
+ "topics": [
83
+ {
84
+ "type_of_topic": "Interest|Goal|Dream|Conflict|Concern|etc.",
85
+ "value_of_topic": "woodworking|Become Millionaire|Visit Spain|etc.",
86
+ "reason": "User stated...|Assumed from..."
87
+ }
88
+ ]
89
+ }
90
+ \`\`\`
91
+
92
+ **Return JSON only.**`;
93
+
94
+ const system = `${taskFragment}
95
+
96
+ ${specificNeedsFragment}
97
+
98
+ ${guidelinesFragment}
99
+
100
+ ${doNotCaptureFragment}
101
+
102
+ ${criticalFragment}`;
103
+
104
+ const earlierSection = data.messages_context.length > 0
105
+ ? `## Earlier Conversation
106
+ ${formatMessagesAsPlaceholders(data.messages_context, personaName)}
107
+
108
+ `
109
+ : '';
110
+
111
+ const recentSection = `## Most Recent Messages
112
+ ${formatMessagesAsPlaceholders(data.messages_analyze, personaName)}`;
113
+
114
+ const user = `# Conversation
115
+ ${earlierSection}${recentSection}
116
+
117
+ ---
118
+
119
+ Scan the "Most Recent Messages" for TOPICS of interest to the human user.
120
+
121
+ **Return JSON:**
122
+ \`\`\`json
123
+ {
124
+ "topics": [
125
+ {
126
+ "type_of_topic": "Interest|Goal|Dream|etc.",
127
+ "value_of_topic": "woodworking|Become Millionaire|etc.",
128
+ "reason": "User stated..."
129
+ }
130
+ ]
131
+ }
132
+ \`\`\``;
133
+
134
+ return { system, user };
135
+ }
@@ -0,0 +1,115 @@
1
+ import type { TraitScanPromptData, PromptOutput } from "./types.js";
2
+ import { formatMessagesAsPlaceholders } from "../message-utils.js";
3
+
4
+ export function buildHumanTraitScanPrompt(data: TraitScanPromptData): PromptOutput {
5
+ if (!data.persona_name) {
6
+ throw new Error("buildHumanTraitScanPrompt: persona_name is required");
7
+ }
8
+
9
+ const personaName = data.persona_name;
10
+
11
+ const taskFragment = `# Task
12
+
13
+ You are scanning a conversation to quickly identify important TRAITS of the HUMAN USER. Your ONLY job is to spot admissions, observations, or other indicators of TRAITS. Do NOT analyze them deeply. Just detect and flag.`;
14
+
15
+ const specificNeedsFragment = `## Specific Needs
16
+
17
+ Your job is to quickly identify:
18
+ 1. Which TRAITS were mentioned or observed
19
+ a. Only flag TRAITS that were actually discussed, not just tangentially related
20
+ b. Be CONSERVATIVE - only suggest genuinely important, long-term relevant TRAITS
21
+ i. Ignore: greetings, small talk, one-off mentions, jokes
22
+ c. Be CLEAR - state your \`reason\` for including this TRAIT with any evidence you used`;
23
+
24
+ const guidelinesFragment = `## Guidelines
25
+
26
+ **A TRAIT Is:**
27
+ * type_of_trait: Personality Patterns
28
+ * Values: Introverted, Reserved, Extroverted, Detail Oriented, Analytical
29
+ * type_of_trait: Communication Style
30
+ * Assertive, Passive, Empathetic, Curious, Narrative
31
+ * type_of_trait: Behavioral Tendencies
32
+ * Risk-Taker, Cautious, Spontaneous, Decisive
33
+ * type_of_trait: Cognitive Style / Learning Approach
34
+ * Logical, Creative, Intuitive, Visual Learner
35
+ * type_of_trait: Emotional Traits / Regulation
36
+ * Emotionally Resilient, Optimistic, Pessimistic, Calm, Anxious
37
+ * type_of_trait: Work Ethic / Task Orientation
38
+ * Diligent, Proactive, Organized, Ambitious, Persistent
39
+ * type_of_trait: Social Orientation
40
+ * Collaborative, Independent, Competitive, Supportive, Gregarious
41
+ * type_of_trait: Approach to Change & Adversity
42
+ * Adaptable, Resilient, Flexible, Open-minded
43
+ * type_of_trait: Motivational Drivers
44
+ * Achievement-Oriented, Altruistic, Curiosity-Driven
45
+ * type_of_trait: Ethical & Moral Stance
46
+ * Principled, Honest, Integrity-Driven, Fair-minded
47
+
48
+ **A TRAIT Is NOT:**
49
+ - Biographical data: Name, Nickname, Birthday, Location, Job, Marital Status, Gender, Eye Color, Hair Color
50
+ - Other unchangeable Data: Wedding Day, Allergies
51
+ - General Topic: Interests, hobbies
52
+ - People: Real people in their life: Wife, Husband, Daughter, Son, etc.
53
+ - Personas: AI personas they discuss
54
+ - Characters: Fictitious entities from books, movies, stories, media, etc.`;
55
+
56
+ const criticalFragment = `# CRITICAL INSTRUCTIONS
57
+
58
+ ONLY ANALYZE the "Most Recent Messages" in the following conversation. The "Earlier Conversation" is provided for your context and has already been processed!
59
+
60
+ The JSON format is:
61
+
62
+ \`\`\`json
63
+ {
64
+ "traits": [
65
+ {
66
+ "type_of_trait": "Personality Pattern|Communication Style|etc.",
67
+ "value_of_trait": "Introverted|Assertive|etc.",
68
+ "reason": "User stated...|Assumed from..."
69
+ }
70
+ ]
71
+ }
72
+ \`\`\`
73
+
74
+ **Return JSON only.**`;
75
+
76
+ const system = `${taskFragment}
77
+
78
+ ${specificNeedsFragment}
79
+
80
+ ${guidelinesFragment}
81
+
82
+ ${criticalFragment}`;
83
+
84
+ const earlierSection = data.messages_context.length > 0
85
+ ? `## Earlier Conversation
86
+ ${formatMessagesAsPlaceholders(data.messages_context, personaName)}
87
+
88
+ `
89
+ : '';
90
+
91
+ const recentSection = `## Most Recent Messages
92
+ ${formatMessagesAsPlaceholders(data.messages_analyze, personaName)}`;
93
+
94
+ const user = `# Conversation
95
+ ${earlierSection}${recentSection}
96
+
97
+ ---
98
+
99
+ Scan the "Most Recent Messages" for TRAITS of the human user.
100
+
101
+ **Return JSON:**
102
+ \`\`\`json
103
+ {
104
+ "traits": [
105
+ {
106
+ "type_of_trait": "Personality Pattern|Communication Style|etc.",
107
+ "value_of_trait": "Introverted|Assertive|etc.",
108
+ "reason": "User stated..."
109
+ }
110
+ ]
111
+ }
112
+ \`\`\``;
113
+
114
+ return { system, user };
115
+ }
@@ -0,0 +1,127 @@
1
+ import type { Message, DataItemBase, DataItemType } from "../../core/types.js";
2
+
3
+ export interface PromptOutput {
4
+ system: string;
5
+ user: string;
6
+ }
7
+
8
+ interface BaseScanPromptData {
9
+ messages_context: Message[];
10
+ messages_analyze: Message[];
11
+ persona_name: string;
12
+ }
13
+
14
+ export interface FactScanPromptData extends BaseScanPromptData {}
15
+
16
+ export interface TraitScanPromptData extends BaseScanPromptData {}
17
+
18
+ export interface TopicScanPromptData extends BaseScanPromptData {}
19
+
20
+ export interface PersonScanPromptData extends BaseScanPromptData {
21
+ known_persona_names: string[];
22
+ }
23
+
24
+ export interface FactScanCandidate {
25
+ type_of_fact: string;
26
+ value_of_fact: string;
27
+ reason: string;
28
+ }
29
+
30
+ export interface TraitScanCandidate {
31
+ type_of_trait: string;
32
+ value_of_trait: string;
33
+ reason: string;
34
+ }
35
+
36
+ export interface TopicScanCandidate {
37
+ type_of_topic: string;
38
+ value_of_topic: string;
39
+ reason: string;
40
+ }
41
+
42
+ export interface PersonScanCandidate {
43
+ type_of_person: string;
44
+ name_of_person: string;
45
+ reason: string;
46
+ }
47
+
48
+ export interface FactScanResult {
49
+ facts: FactScanCandidate[];
50
+ }
51
+
52
+ export interface TraitScanResult {
53
+ traits: TraitScanCandidate[];
54
+ }
55
+
56
+ export interface TopicScanResult {
57
+ topics: TopicScanCandidate[];
58
+ }
59
+
60
+ export interface PersonScanResult {
61
+ people: PersonScanCandidate[];
62
+ }
63
+
64
+ export interface ItemMatchPromptData {
65
+ candidate_type: DataItemType;
66
+ candidate_name: string;
67
+ candidate_value: string;
68
+ all_items: Array<{
69
+ data_type: DataItemType;
70
+ data_id: string;
71
+ data_name: string;
72
+ data_description: string;
73
+ }>;
74
+ }
75
+
76
+ export interface ItemMatchResult {
77
+ matched_guid: string | null;
78
+ }
79
+
80
+ export interface ItemUpdatePromptData {
81
+ data_type: DataItemType;
82
+ existing_item: DataItemBase | null;
83
+ messages_context: Message[];
84
+ messages_analyze: Message[];
85
+ persona_name: string;
86
+ new_item_name?: string;
87
+ new_item_value?: string;
88
+ }
89
+
90
+ export type ExposureImpact = "high" | "medium" | "low" | "none";
91
+
92
+ export interface QuoteCandidate {
93
+ text: string;
94
+ reason: string;
95
+ }
96
+
97
+ export interface ItemUpdateResultBase {
98
+ name: string;
99
+ description: string;
100
+ sentiment: number;
101
+ quotes?: QuoteCandidate[];
102
+ }
103
+
104
+ export interface FactUpdateResult extends ItemUpdateResultBase {}
105
+
106
+ export interface TraitUpdateResult extends ItemUpdateResultBase {
107
+ strength?: number;
108
+ }
109
+
110
+ export interface TopicUpdateResult extends ItemUpdateResultBase {
111
+ category?: string;
112
+ exposure_desired?: number;
113
+ exposure_impact?: ExposureImpact;
114
+ }
115
+
116
+ export interface PersonUpdateResult extends ItemUpdateResultBase {
117
+ relationship?: string;
118
+ exposure_desired?: number;
119
+ exposure_impact?: ExposureImpact;
120
+ }
121
+
122
+ export type ItemUpdateResult =
123
+ | FactUpdateResult
124
+ | TraitUpdateResult
125
+ | TopicUpdateResult
126
+ | PersonUpdateResult
127
+ | Record<string, never>;
@@ -0,0 +1,90 @@
1
+ export { buildResponsePrompt } from "./response/index.js";
2
+ export type { ResponsePromptData, PromptOutput } from "./response/types.js";
3
+
4
+ export {
5
+ buildHeartbeatCheckPrompt,
6
+ buildEiHeartbeatPrompt,
7
+ } from "./heartbeat/index.js";
8
+ export type {
9
+ HeartbeatCheckPromptData,
10
+ HeartbeatCheckResult,
11
+ EiHeartbeatPromptData,
12
+ EiHeartbeatResult,
13
+ } from "./heartbeat/types.js";
14
+
15
+ export {
16
+ buildPersonaGenerationPrompt,
17
+ buildPersonaDescriptionsPrompt,
18
+ } from "./generation/index.js";
19
+ export type {
20
+ PersonaGenerationPromptData,
21
+ PersonaGenerationResult,
22
+ PersonaDescriptionsPromptData,
23
+ PersonaDescriptionsResult,
24
+ } from "./generation/types.js";
25
+
26
+ export {
27
+ buildPersonaTraitExtractionPrompt,
28
+ buildPersonaTopicScanPrompt,
29
+ buildPersonaTopicMatchPrompt,
30
+ buildPersonaTopicUpdatePrompt,
31
+ } from "./persona/index.js";
32
+ export type {
33
+ PersonaTraitExtractionPromptData,
34
+ PersonaTopicScanPromptData,
35
+ PersonaTopicScanCandidate,
36
+ PersonaTopicScanResult,
37
+ PersonaTopicMatchPromptData,
38
+ PersonaTopicMatchResult,
39
+ PersonaTopicUpdatePromptData,
40
+ PersonaTopicUpdateResult,
41
+ TraitResult,
42
+ } from "./persona/types.js";
43
+
44
+ export { buildEiValidationPrompt } from "./validation/index.js";
45
+ export type {
46
+ EiValidationPromptData,
47
+ EiValidationResult,
48
+ } from "./validation/types.js";
49
+
50
+ export {
51
+ buildHumanFactScanPrompt,
52
+ buildHumanTraitScanPrompt,
53
+ buildHumanTopicScanPrompt,
54
+ buildHumanPersonScanPrompt,
55
+ buildHumanItemMatchPrompt,
56
+ buildHumanItemUpdatePrompt,
57
+ } from "./human/index.js";
58
+ export type {
59
+ FactScanPromptData,
60
+ TraitScanPromptData,
61
+ TopicScanPromptData,
62
+ PersonScanPromptData,
63
+ FactScanCandidate,
64
+ TraitScanCandidate,
65
+ TopicScanCandidate,
66
+ PersonScanCandidate,
67
+ FactScanResult,
68
+ TraitScanResult,
69
+ TopicScanResult,
70
+ PersonScanResult,
71
+ ItemMatchPromptData,
72
+ ItemMatchResult,
73
+ ItemUpdatePromptData,
74
+ ExposureImpact,
75
+ ItemUpdateResult,
76
+ } from "./human/types.js";
77
+
78
+ export {
79
+ buildPersonaExpirePrompt,
80
+ buildPersonaExplorePrompt,
81
+ buildDescriptionCheckPrompt,
82
+ } from "./ceremony/index.js";
83
+ export type {
84
+ PersonaExpirePromptData,
85
+ PersonaExpireResult,
86
+ PersonaExplorePromptData,
87
+ PersonaExploreResult,
88
+ DescriptionCheckPromptData,
89
+ DescriptionCheckResult,
90
+ } from "./ceremony/types.js";
@@ -0,0 +1,39 @@
1
+ import type { Message } from "../core/types.js";
2
+
3
+ const MESSAGE_PLACEHOLDER_REGEX = /\[mid:([a-zA-Z0-9_-]+):([^\]]+)\]/g;
4
+
5
+ export function formatMessageAsPlaceholder(message: Message, personaName: string): string {
6
+ const role = message.role === "human" ? "human" : personaName;
7
+ return `[mid:${message.id}:${role}]`;
8
+ }
9
+
10
+ export function formatMessagesAsPlaceholders(messages: Message[], personaName: string): string {
11
+ if (messages.length === 0) return "(No messages)";
12
+ return messages.map(m => formatMessageAsPlaceholder(m, personaName)).join('\n\n');
13
+ }
14
+
15
+ export function hydratePromptPlaceholders(
16
+ prompt: string,
17
+ messageMap: Map<string, Message>
18
+ ): string {
19
+ return prompt.replace(MESSAGE_PLACEHOLDER_REGEX, (_match, id, role) => {
20
+ const message = messageMap.get(id);
21
+ if (!message) {
22
+ return `[${role}]: [message not found]`;
23
+ }
24
+ const displayRole = message.role === "human" ? "[human]" : `[${role}]`;
25
+ return `${displayRole}: ${message.content}`;
26
+ });
27
+ }
28
+
29
+ export function buildMessageMapFromPersonas(
30
+ personaMessages: Map<string, Message[]>
31
+ ): Map<string, Message> {
32
+ const map = new Map<string, Message>();
33
+ for (const messages of personaMessages.values()) {
34
+ for (const msg of messages) {
35
+ map.set(msg.id, msg);
36
+ }
37
+ }
38
+ return map;
39
+ }
@@ -0,0 +1,16 @@
1
+ export { buildPersonaTraitExtractionPrompt } from "./traits.js";
2
+ export { buildPersonaTopicScanPrompt } from "./topics-scan.js";
3
+ export { buildPersonaTopicMatchPrompt } from "./topics-match.js";
4
+ export { buildPersonaTopicUpdatePrompt } from "./topics-update.js";
5
+ export type {
6
+ PersonaTraitExtractionPromptData,
7
+ PersonaTopicScanPromptData,
8
+ PersonaTopicScanCandidate,
9
+ PersonaTopicScanResult,
10
+ PersonaTopicMatchPromptData,
11
+ PersonaTopicMatchResult,
12
+ PersonaTopicUpdatePromptData,
13
+ PersonaTopicUpdateResult,
14
+ TraitResult,
15
+ PromptOutput,
16
+ } from "./types.js";