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,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EI V1 Core Types
|
|
3
|
+
* Source of truth: CONTRACTS.md
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// ENUMS
|
|
8
|
+
// =============================================================================
|
|
9
|
+
|
|
10
|
+
export enum ContextStatus {
|
|
11
|
+
Default = "default",
|
|
12
|
+
Always = "always",
|
|
13
|
+
Never = "never",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export enum ValidationLevel {
|
|
17
|
+
None = "none", // Fresh data, never acknowledged
|
|
18
|
+
Ei = "ei", // Ei mentioned it to user (don't mention again)
|
|
19
|
+
Human = "human", // User explicitly confirmed (locked)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export enum LLMRequestType {
|
|
23
|
+
Response = "response",
|
|
24
|
+
JSON = "json",
|
|
25
|
+
Raw = "raw",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export enum LLMPriority {
|
|
29
|
+
High = "high",
|
|
30
|
+
Normal = "normal",
|
|
31
|
+
Low = "low",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export enum LLMNextStep {
|
|
35
|
+
HandlePersonaResponse = "handlePersonaResponse",
|
|
36
|
+
HandlePersonaGeneration = "handlePersonaGeneration",
|
|
37
|
+
HandlePersonaDescriptions = "handlePersonaDescriptions",
|
|
38
|
+
HandleHumanFactScan = "handleHumanFactScan",
|
|
39
|
+
HandleHumanTraitScan = "handleHumanTraitScan",
|
|
40
|
+
HandleHumanTopicScan = "handleHumanTopicScan",
|
|
41
|
+
HandleHumanPersonScan = "handleHumanPersonScan",
|
|
42
|
+
HandleHumanItemMatch = "handleHumanItemMatch",
|
|
43
|
+
HandleHumanItemUpdate = "handleHumanItemUpdate",
|
|
44
|
+
HandlePersonaTraitExtraction = "handlePersonaTraitExtraction",
|
|
45
|
+
HandlePersonaTopicScan = "handlePersonaTopicScan",
|
|
46
|
+
HandlePersonaTopicMatch = "handlePersonaTopicMatch",
|
|
47
|
+
HandlePersonaTopicUpdate = "handlePersonaTopicUpdate",
|
|
48
|
+
HandleHeartbeatCheck = "handleHeartbeatCheck",
|
|
49
|
+
HandleEiHeartbeat = "handleEiHeartbeat",
|
|
50
|
+
HandleEiValidation = "handleEiValidation",
|
|
51
|
+
HandleOneShot = "handleOneShot",
|
|
52
|
+
// Ceremony handlers
|
|
53
|
+
HandlePersonaExpire = "handlePersonaExpire",
|
|
54
|
+
HandlePersonaExplore = "handlePersonaExplore",
|
|
55
|
+
HandleDescriptionCheck = "handleDescriptionCheck",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// =============================================================================
|
|
59
|
+
// DATA ITEMS
|
|
60
|
+
// =============================================================================
|
|
61
|
+
|
|
62
|
+
export interface DataItemBase {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
description: string;
|
|
66
|
+
sentiment: number;
|
|
67
|
+
last_updated: string;
|
|
68
|
+
learned_by?: string; // Persona ID that learned this item
|
|
69
|
+
persona_groups?: string[];
|
|
70
|
+
embedding?: number[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface Fact extends DataItemBase {
|
|
74
|
+
validated: ValidationLevel;
|
|
75
|
+
validated_date: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface Trait extends DataItemBase {
|
|
79
|
+
strength?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface Topic extends DataItemBase {
|
|
83
|
+
category?: string; // Interest, Goal, Dream, Conflict, Concern, Fear, Hope, Plan, Project
|
|
84
|
+
exposure_current: number;
|
|
85
|
+
exposure_desired: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* PersonaTopic - How a persona engages with a topic
|
|
90
|
+
*
|
|
91
|
+
* Different from Human Topic because:
|
|
92
|
+
* - Persona-local (not shared across personas via groups)
|
|
93
|
+
* - Richer fields: perspective, approach, personal_stake
|
|
94
|
+
* - Not "learned" - generated during Ceremony
|
|
95
|
+
*/
|
|
96
|
+
export interface PersonaTopic {
|
|
97
|
+
id: string;
|
|
98
|
+
name: string;
|
|
99
|
+
perspective: string; // Their view/opinion on this topic
|
|
100
|
+
approach: string; // How they prefer to engage with this topic
|
|
101
|
+
personal_stake: string; // Why this topic matters to them personally
|
|
102
|
+
sentiment: number; // -1.0 to 1.0
|
|
103
|
+
exposure_current: number; // 0.0 to 1.0 (how recently discussed)
|
|
104
|
+
exposure_desired: number; // 0.0 to 1.0 (how much they want to discuss)
|
|
105
|
+
last_updated: string; // ISO timestamp
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface Person extends DataItemBase {
|
|
109
|
+
relationship: string;
|
|
110
|
+
exposure_current: number;
|
|
111
|
+
exposure_desired: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface Quote {
|
|
115
|
+
id: string; // UUID (use crypto.randomUUID())
|
|
116
|
+
message_id: string | null; // FK to Message.id (nullable for manual quotes)
|
|
117
|
+
data_item_ids: string[]; // FK[] to DataItemBase.id
|
|
118
|
+
persona_groups: string[]; // Visibility groups
|
|
119
|
+
text: string; // The quote content
|
|
120
|
+
speaker: "human" | string; // Who said it (persona ID or "human")
|
|
121
|
+
timestamp: string; // ISO timestamp (from original message)
|
|
122
|
+
start: number | null; // Character offset in message (null = can't highlight)
|
|
123
|
+
end: number | null; // Character offset in message (null = can't highlight)
|
|
124
|
+
created_at: string; // ISO timestamp when captured
|
|
125
|
+
created_by: "extraction" | "human"; // How it was created
|
|
126
|
+
embedding?: number[]; // Semantic embedding for similarity search
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// =============================================================================
|
|
130
|
+
// PROVIDER ACCOUNTS
|
|
131
|
+
// =============================================================================
|
|
132
|
+
|
|
133
|
+
export enum ProviderType {
|
|
134
|
+
LLM = "llm",
|
|
135
|
+
Storage = "storage",
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* ProviderAccount - Configuration for external service connections
|
|
140
|
+
*
|
|
141
|
+
* Used for both LLM providers (OpenRouter, Bedrock, etc.) and storage providers
|
|
142
|
+
* (flare576.com, Dropbox, Google Drive, etc.).
|
|
143
|
+
*
|
|
144
|
+
* Model specification format: `account-name:model` (e.g., `MyOpenRouter:mistralai/mistral-7b`)
|
|
145
|
+
* Falls back to environment variables if no matching account is found.
|
|
146
|
+
*/
|
|
147
|
+
export interface ProviderAccount {
|
|
148
|
+
id: string; // UUID
|
|
149
|
+
name: string; // User-defined display name (e.g., "OpenRouter-Free", "Work Bedrock")
|
|
150
|
+
type: ProviderType; // "llm" | "storage"
|
|
151
|
+
url: string; // Base URL for API (e.g., "https://openrouter.ai/api/v1")
|
|
152
|
+
|
|
153
|
+
// Auth - use api_key for Bearer token, or username+password for basic/custom auth
|
|
154
|
+
api_key?: string; // Bearer token auth (most common)
|
|
155
|
+
username?: string; // Basic auth or custom (for storage providers)
|
|
156
|
+
password?: string; // Basic auth or custom (for storage providers)
|
|
157
|
+
|
|
158
|
+
// LLM-specific
|
|
159
|
+
default_model?: string; // Default model for this account
|
|
160
|
+
token_limit?: number; // Context window override (tokens). Used for extraction chunking.
|
|
161
|
+
|
|
162
|
+
// Provider-specific extras (e.g., OpenRouter needs HTTP-Referer, X-Title)
|
|
163
|
+
extra_headers?: Record<string, string>;
|
|
164
|
+
|
|
165
|
+
// Metadata
|
|
166
|
+
enabled?: boolean; // Default: true
|
|
167
|
+
created_at: string; // ISO timestamp
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// ENTITIES
|
|
172
|
+
// =============================================================================
|
|
173
|
+
|
|
174
|
+
export interface SyncCredentials {
|
|
175
|
+
username: string;
|
|
176
|
+
passphrase: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface OpenCodeSettings {
|
|
180
|
+
integration?: boolean;
|
|
181
|
+
polling_interval_ms?: number; // Default: 1800000 (30 min)
|
|
182
|
+
last_sync?: string; // ISO timestamp
|
|
183
|
+
extraction_point?: string; // ISO timestamp - earliest unprocessed message, gradual extraction advances this
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface CeremonyConfig {
|
|
187
|
+
time: string; // "HH:MM" format (e.g., "09:00")
|
|
188
|
+
last_ceremony?: string; // ISO timestamp
|
|
189
|
+
decay_rate?: number; // Default: 0.1
|
|
190
|
+
explore_threshold?: number; // Default: 3
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface HumanSettings {
|
|
194
|
+
default_model?: string;
|
|
195
|
+
queue_paused?: boolean;
|
|
196
|
+
skip_quote_delete_confirm?: boolean;
|
|
197
|
+
name_display?: string;
|
|
198
|
+
time_mode?: "24h" | "12h" | "local" | "utc";
|
|
199
|
+
accounts?: ProviderAccount[];
|
|
200
|
+
sync?: SyncCredentials;
|
|
201
|
+
opencode?: OpenCodeSettings;
|
|
202
|
+
ceremony?: CeremonyConfig;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface HumanEntity {
|
|
206
|
+
entity: "human";
|
|
207
|
+
facts: Fact[];
|
|
208
|
+
traits: Trait[];
|
|
209
|
+
topics: Topic[];
|
|
210
|
+
people: Person[];
|
|
211
|
+
quotes: Quote[];
|
|
212
|
+
last_updated: string;
|
|
213
|
+
last_activity: string;
|
|
214
|
+
settings?: HumanSettings;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface PersonaEntity {
|
|
218
|
+
id: string; // UUID (or "ei" for built-in Ei persona)
|
|
219
|
+
display_name: string; // What shows in UI (user's chosen name)
|
|
220
|
+
entity: "system";
|
|
221
|
+
aliases?: string[]; // For fuzzy matching (user types "/persona Bob")
|
|
222
|
+
short_description?: string;
|
|
223
|
+
long_description?: string;
|
|
224
|
+
model?: string;
|
|
225
|
+
group_primary?: string | null;
|
|
226
|
+
groups_visible?: string[];
|
|
227
|
+
traits: Trait[];
|
|
228
|
+
topics: PersonaTopic[];
|
|
229
|
+
is_paused: boolean;
|
|
230
|
+
pause_until?: string;
|
|
231
|
+
is_archived: boolean;
|
|
232
|
+
archived_at?: string;
|
|
233
|
+
is_static: boolean;
|
|
234
|
+
heartbeat_delay_ms?: number;
|
|
235
|
+
context_window_hours?: number;
|
|
236
|
+
context_boundary?: string; // ISO timestamp - messages before this excluded from LLM context
|
|
237
|
+
last_updated: string;
|
|
238
|
+
last_activity: string;
|
|
239
|
+
last_heartbeat?: string;
|
|
240
|
+
last_extraction?: string;
|
|
241
|
+
last_inactivity_ping?: string;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface PersonaCreationInput {
|
|
245
|
+
name: string;
|
|
246
|
+
aliases?: string[];
|
|
247
|
+
long_description?: string;
|
|
248
|
+
short_description?: string;
|
|
249
|
+
traits?: Partial<Trait>[];
|
|
250
|
+
topics?: Partial<Topic>[];
|
|
251
|
+
model?: string;
|
|
252
|
+
group_primary?: string;
|
|
253
|
+
groups_visible?: string[];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Message pruning thresholds (shared by ceremony and import)
|
|
257
|
+
export const MESSAGE_MIN_COUNT = 200;
|
|
258
|
+
export const MESSAGE_MAX_AGE_DAYS = 14;
|
|
259
|
+
|
|
260
|
+
// Reserved persona names (command keywords that conflict with /persona subcommands)
|
|
261
|
+
export const RESERVED_PERSONA_NAMES = ["new", "clone"] as const;
|
|
262
|
+
export type ReservedPersonaName = typeof RESERVED_PERSONA_NAMES[number];
|
|
263
|
+
|
|
264
|
+
export function isReservedPersonaName(name: string): boolean {
|
|
265
|
+
return RESERVED_PERSONA_NAMES.includes(name.toLowerCase() as ReservedPersonaName);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// =============================================================================
|
|
269
|
+
// MESSAGES
|
|
270
|
+
// =============================================================================
|
|
271
|
+
|
|
272
|
+
export interface Message {
|
|
273
|
+
id: string;
|
|
274
|
+
role: "human" | "system";
|
|
275
|
+
content: string;
|
|
276
|
+
timestamp: string;
|
|
277
|
+
read: boolean;
|
|
278
|
+
context_status: ContextStatus;
|
|
279
|
+
f?: boolean; // fact extraction done
|
|
280
|
+
r?: boolean; // trait extraction done
|
|
281
|
+
p?: boolean; // person extraction done
|
|
282
|
+
o?: boolean; // topic extraction done
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface ChatMessage {
|
|
286
|
+
role: "system" | "user" | "assistant";
|
|
287
|
+
content: string;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// =============================================================================
|
|
291
|
+
// LLM TYPES
|
|
292
|
+
// =============================================================================
|
|
293
|
+
|
|
294
|
+
export interface LLMRequest {
|
|
295
|
+
id: string;
|
|
296
|
+
created_at: string;
|
|
297
|
+
attempts: number;
|
|
298
|
+
last_attempt?: string;
|
|
299
|
+
retry_after?: string;
|
|
300
|
+
type: LLMRequestType;
|
|
301
|
+
priority: LLMPriority;
|
|
302
|
+
system: string;
|
|
303
|
+
user: string;
|
|
304
|
+
next_step: LLMNextStep;
|
|
305
|
+
model?: string;
|
|
306
|
+
data: Record<string, unknown>;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
export interface QueueFailResult {
|
|
311
|
+
dropped: boolean;
|
|
312
|
+
retryDelay?: number;
|
|
313
|
+
}
|
|
314
|
+
export interface LLMResponse {
|
|
315
|
+
request: LLMRequest;
|
|
316
|
+
success: boolean;
|
|
317
|
+
content: string | null;
|
|
318
|
+
parsed?: unknown;
|
|
319
|
+
error?: string;
|
|
320
|
+
finish_reason?: string;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// =============================================================================
|
|
324
|
+
// API TYPES
|
|
325
|
+
// =============================================================================
|
|
326
|
+
|
|
327
|
+
export interface PersonaSummary {
|
|
328
|
+
id: string;
|
|
329
|
+
display_name: string;
|
|
330
|
+
aliases: string[];
|
|
331
|
+
short_description?: string;
|
|
332
|
+
is_paused: boolean;
|
|
333
|
+
is_archived: boolean;
|
|
334
|
+
unread_count: number;
|
|
335
|
+
last_activity?: string;
|
|
336
|
+
context_boundary?: string;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface MessageQueryOptions {
|
|
340
|
+
after?: string;
|
|
341
|
+
before?: string;
|
|
342
|
+
limit?: number;
|
|
343
|
+
includeOutOfContext?: boolean;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export interface QueueStatus {
|
|
347
|
+
state: "idle" | "busy" | "paused";
|
|
348
|
+
pending_count: number;
|
|
349
|
+
current_operation?: string;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export interface EiError {
|
|
353
|
+
code: string;
|
|
354
|
+
message: string;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// =============================================================================
|
|
358
|
+
// EI_INTERFACE (Processor -> Frontend events)
|
|
359
|
+
// =============================================================================
|
|
360
|
+
|
|
361
|
+
export interface Ei_Interface {
|
|
362
|
+
onPersonaAdded?: () => void;
|
|
363
|
+
onPersonaRemoved?: () => void;
|
|
364
|
+
onPersonaUpdated?: (personaId: string) => void;
|
|
365
|
+
onMessageAdded?: (personaId: string) => void;
|
|
366
|
+
onMessageRecalled?: (personaId: string, content: string) => void;
|
|
367
|
+
onMessageProcessing?: (personaId: string) => void;
|
|
368
|
+
onMessageQueued?: (personaId: string) => void;
|
|
369
|
+
onHumanUpdated?: () => void;
|
|
370
|
+
onQuoteAdded?: () => void;
|
|
371
|
+
onQuoteUpdated?: () => void;
|
|
372
|
+
onQuoteRemoved?: () => void;
|
|
373
|
+
onQueueStateChanged?: (state: "idle" | "busy" | "paused") => void;
|
|
374
|
+
onError?: (error: EiError) => void;
|
|
375
|
+
onStateImported?: () => void;
|
|
376
|
+
onOneShotReturned?: (guid: string, content: string) => void;
|
|
377
|
+
onContextBoundaryChanged?: (personaId: string) => void;
|
|
378
|
+
onSaveAndExitStart?: () => void;
|
|
379
|
+
onSaveAndExitFinish?: () => void;
|
|
380
|
+
onStateConflict?: (data: StateConflictData) => void;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// =============================================================================
|
|
384
|
+
// SYNC TYPES
|
|
385
|
+
// =============================================================================
|
|
386
|
+
|
|
387
|
+
export type StateConflictResolution = "local" | "server" | "yolo";
|
|
388
|
+
|
|
389
|
+
export interface StateConflictData {
|
|
390
|
+
localTimestamp: Date;
|
|
391
|
+
remoteTimestamp: Date;
|
|
392
|
+
hasLocalState: boolean;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// =============================================================================
|
|
396
|
+
// STORAGE TYPES
|
|
397
|
+
// =============================================================================
|
|
398
|
+
|
|
399
|
+
export interface StorageState {
|
|
400
|
+
version: number;
|
|
401
|
+
timestamp: string;
|
|
402
|
+
human: HumanEntity;
|
|
403
|
+
personas: Record<
|
|
404
|
+
string,
|
|
405
|
+
{
|
|
406
|
+
entity: PersonaEntity;
|
|
407
|
+
messages: Message[];
|
|
408
|
+
}
|
|
409
|
+
>;
|
|
410
|
+
queue: LLMRequest[];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
// =============================================================================
|
|
416
|
+
// DATA ITEM TYPE HELPERS
|
|
417
|
+
// =============================================================================
|
|
418
|
+
|
|
419
|
+
export type DataItemType = "fact" | "trait" | "topic" | "person";
|
|
420
|
+
|
|
421
|
+
export type DataItem = Fact | Trait | Topic | Person;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logarithmic decay utility for exposure values.
|
|
3
|
+
* Ported from V0: v0/src/topic-decay.ts
|
|
4
|
+
*
|
|
5
|
+
* The formula decays faster at extremes (0 and 1), slower in the middle.
|
|
6
|
+
* K=0.1 means ~10% decay per day at midpoint (0.5).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function calculateLogarithmicDecay(
|
|
10
|
+
currentValue: number,
|
|
11
|
+
hoursSinceUpdate: number,
|
|
12
|
+
K: number = 0.1
|
|
13
|
+
): number {
|
|
14
|
+
const decay = K * currentValue * (1 - currentValue) * hoursSinceUpdate;
|
|
15
|
+
return Math.max(0, Math.min(1, currentValue - decay));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function applyDecayToValue(
|
|
19
|
+
currentValue: number,
|
|
20
|
+
lastUpdated: string,
|
|
21
|
+
now: Date = new Date(),
|
|
22
|
+
K: number = 0.1
|
|
23
|
+
): { newValue: number; hoursSinceUpdate: number } {
|
|
24
|
+
const lastUpdatedTime = new Date(lastUpdated).getTime();
|
|
25
|
+
const hoursSinceUpdate = (now.getTime() - lastUpdatedTime) / (1000 * 60 * 60);
|
|
26
|
+
|
|
27
|
+
if (hoursSinceUpdate < 0.1) {
|
|
28
|
+
return { newValue: currentValue, hoursSinceUpdate };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const newValue = calculateLogarithmicDecay(currentValue, hoursSinceUpdate, K);
|
|
32
|
+
return { newValue, hoursSinceUpdate };
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./core/index.js";
|