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.
- package/LICENSE +21 -0
- package/README.md +170 -0
- package/package.json +63 -0
- package/src/README.md +96 -0
- package/src/cli/README.md +47 -0
- package/src/cli/commands/facts.ts +25 -0
- package/src/cli/commands/people.ts +25 -0
- package/src/cli/commands/quotes.ts +19 -0
- package/src/cli/commands/topics.ts +25 -0
- package/src/cli/commands/traits.ts +25 -0
- package/src/cli/retrieval.ts +269 -0
- package/src/cli.ts +176 -0
- package/src/core/AGENTS.md +104 -0
- package/src/core/embedding-service.ts +241 -0
- package/src/core/handlers/index.ts +1057 -0
- package/src/core/index.ts +4 -0
- package/src/core/llm-client.ts +265 -0
- package/src/core/model-context-windows.ts +49 -0
- package/src/core/orchestrators/ceremony.ts +500 -0
- package/src/core/orchestrators/extraction-chunker.ts +138 -0
- package/src/core/orchestrators/human-extraction.ts +457 -0
- package/src/core/orchestrators/index.ts +28 -0
- package/src/core/orchestrators/persona-generation.ts +76 -0
- package/src/core/orchestrators/persona-topics.ts +117 -0
- package/src/core/personas/index.ts +5 -0
- package/src/core/personas/opencode-agent.ts +81 -0
- package/src/core/processor.ts +1413 -0
- package/src/core/queue-processor.ts +197 -0
- package/src/core/state/checkpoints.ts +68 -0
- package/src/core/state/human.ts +176 -0
- package/src/core/state/index.ts +5 -0
- package/src/core/state/personas.ts +217 -0
- package/src/core/state/queue.ts +144 -0
- package/src/core/state-manager.ts +347 -0
- package/src/core/types.ts +421 -0
- package/src/core/utils/decay.ts +33 -0
- package/src/index.ts +1 -0
- package/src/integrations/opencode/importer.ts +896 -0
- package/src/integrations/opencode/index.ts +16 -0
- package/src/integrations/opencode/json-reader.ts +304 -0
- package/src/integrations/opencode/reader-factory.ts +35 -0
- package/src/integrations/opencode/sqlite-reader.ts +189 -0
- package/src/integrations/opencode/types.ts +244 -0
- package/src/prompts/AGENTS.md +62 -0
- package/src/prompts/ceremony/description-check.ts +47 -0
- package/src/prompts/ceremony/expire.ts +30 -0
- package/src/prompts/ceremony/explore.ts +60 -0
- package/src/prompts/ceremony/index.ts +11 -0
- package/src/prompts/ceremony/types.ts +42 -0
- package/src/prompts/generation/descriptions.ts +91 -0
- package/src/prompts/generation/index.ts +15 -0
- package/src/prompts/generation/persona.ts +155 -0
- package/src/prompts/generation/seeds.ts +31 -0
- package/src/prompts/generation/types.ts +47 -0
- package/src/prompts/heartbeat/check.ts +179 -0
- package/src/prompts/heartbeat/ei.ts +208 -0
- package/src/prompts/heartbeat/index.ts +15 -0
- package/src/prompts/heartbeat/types.ts +70 -0
- package/src/prompts/human/fact-scan.ts +152 -0
- package/src/prompts/human/index.ts +32 -0
- package/src/prompts/human/item-match.ts +74 -0
- package/src/prompts/human/item-update.ts +322 -0
- package/src/prompts/human/person-scan.ts +115 -0
- package/src/prompts/human/topic-scan.ts +135 -0
- package/src/prompts/human/trait-scan.ts +115 -0
- package/src/prompts/human/types.ts +127 -0
- package/src/prompts/index.ts +90 -0
- package/src/prompts/message-utils.ts +39 -0
- package/src/prompts/persona/index.ts +16 -0
- package/src/prompts/persona/topics-match.ts +69 -0
- package/src/prompts/persona/topics-scan.ts +98 -0
- package/src/prompts/persona/topics-update.ts +157 -0
- package/src/prompts/persona/traits.ts +117 -0
- package/src/prompts/persona/types.ts +74 -0
- package/src/prompts/response/index.ts +147 -0
- package/src/prompts/response/sections.ts +355 -0
- package/src/prompts/response/types.ts +38 -0
- package/src/prompts/validation/ei.ts +93 -0
- package/src/prompts/validation/index.ts +6 -0
- package/src/prompts/validation/types.ts +22 -0
- package/src/storage/crypto.ts +96 -0
- package/src/storage/index.ts +5 -0
- package/src/storage/interface.ts +9 -0
- package/src/storage/local.ts +79 -0
- package/src/storage/merge.ts +69 -0
- package/src/storage/remote.ts +145 -0
- package/src/templates/welcome.ts +91 -0
- package/tui/README.md +62 -0
- package/tui/bunfig.toml +4 -0
- package/tui/src/app.tsx +55 -0
- package/tui/src/commands/archive.tsx +93 -0
- package/tui/src/commands/context.tsx +124 -0
- package/tui/src/commands/delete.tsx +71 -0
- package/tui/src/commands/details.tsx +41 -0
- package/tui/src/commands/editor.tsx +46 -0
- package/tui/src/commands/help.tsx +12 -0
- package/tui/src/commands/me.tsx +145 -0
- package/tui/src/commands/model.ts +47 -0
- package/tui/src/commands/new.ts +31 -0
- package/tui/src/commands/pause.ts +46 -0
- package/tui/src/commands/persona.tsx +58 -0
- package/tui/src/commands/provider.tsx +124 -0
- package/tui/src/commands/quit.ts +22 -0
- package/tui/src/commands/quotes.tsx +172 -0
- package/tui/src/commands/registry.test.ts +137 -0
- package/tui/src/commands/registry.ts +130 -0
- package/tui/src/commands/resume.ts +39 -0
- package/tui/src/commands/setsync.tsx +43 -0
- package/tui/src/commands/settings.tsx +83 -0
- package/tui/src/components/ConfirmOverlay.tsx +51 -0
- package/tui/src/components/ConflictOverlay.tsx +78 -0
- package/tui/src/components/HelpOverlay.tsx +69 -0
- package/tui/src/components/Layout.tsx +24 -0
- package/tui/src/components/MessageList.tsx +174 -0
- package/tui/src/components/PersonaListOverlay.tsx +186 -0
- package/tui/src/components/PromptInput.tsx +145 -0
- package/tui/src/components/ProviderListOverlay.tsx +208 -0
- package/tui/src/components/QuotesOverlay.tsx +157 -0
- package/tui/src/components/Sidebar.tsx +95 -0
- package/tui/src/components/StatusBar.tsx +77 -0
- package/tui/src/components/WelcomeOverlay.tsx +73 -0
- package/tui/src/context/ei.tsx +623 -0
- package/tui/src/context/keyboard.tsx +164 -0
- package/tui/src/context/overlay.tsx +53 -0
- package/tui/src/index.tsx +8 -0
- package/tui/src/storage/file.ts +185 -0
- package/tui/src/util/duration.ts +32 -0
- package/tui/src/util/editor.ts +188 -0
- package/tui/src/util/logger.ts +109 -0
- package/tui/src/util/persona-editor.tsx +181 -0
- package/tui/src/util/provider-editor.tsx +168 -0
- package/tui/src/util/syntax.ts +35 -0
- 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";
|