friday-framework-core 0.1.0a0__py3-none-any.whl

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.
@@ -0,0 +1,129 @@
1
+ """
2
+ Friday Core Package
3
+ Foundation interfaces and shared utilities.
4
+
5
+ This package provides the foundational "glue" for the Friday Framework:
6
+ - Configuration management (FridayBaseSettings)
7
+ - Exception hierarchy (FridayError and subclasses)
8
+ - Logging utilities (get_logger, LoggerProtocol)
9
+ - Telemetry interfaces (TelemetryInterface, DebugTelemetryRecorder)
10
+ - Storage adapter protocols (EpisodicStoreAdapter, VectorStoreAdapter, GraphStoreAdapter)
11
+ - Context engineering protocol (ContextEngineeringInterface)
12
+
13
+ Ref: Batch 0 Specification
14
+ """ # noqa: E501
15
+
16
+ # Configuration
17
+ # Security
18
+ from friday_core import security
19
+ from friday_core.config import FridayBaseSettings
20
+
21
+ # Exceptions
22
+ from friday_core.exceptions import (
23
+ ContextOverflowError,
24
+ FridayError,
25
+ MemoryError,
26
+ ProviderAPIError,
27
+ )
28
+
29
+ # Interfaces
30
+ from friday_core.interfaces import (
31
+ AgentInterface,
32
+ ArbitrationDecision,
33
+ ArbitrationInterface,
34
+ ChatCompletionResponse,
35
+ ContextEngineeringInterface,
36
+ EmbeddingModel,
37
+ EpisodicStoreAdapter,
38
+ GraphStoreAdapter,
39
+ LabHarnessInterface,
40
+ LLMClient,
41
+ MemoryPromotionProposal,
42
+ MultiAgentMemoryInterface,
43
+ NamespacePolicyInterface,
44
+ RegistryInterface,
45
+ SchemaFormat,
46
+ SharedWriteCapability,
47
+ SystemRuntime,
48
+ ToolAdapter,
49
+ ToolCall,
50
+ ToolDefinition,
51
+ ToolRegistry,
52
+ TranscriptBackedEpisodicStore,
53
+ TranscriptStoreProtocol,
54
+ VectorStoreAdapter,
55
+ )
56
+
57
+ # Logging
58
+ from friday_core.logging import LoggerProtocol, get_logger
59
+
60
+ # Memory Profiles
61
+ from friday_core.profiles import (
62
+ MemoryProfile,
63
+ create_graph_store,
64
+ create_vector_store,
65
+ )
66
+
67
+ # Telemetry
68
+ from friday_core.telemetry import (
69
+ DebugTelemetryRecorder,
70
+ EventRecord,
71
+ SpanRecord,
72
+ TelemetryInterface,
73
+ )
74
+
75
+ __all__ = [
76
+ # Configuration
77
+ "FridayBaseSettings",
78
+ # Exceptions
79
+ "FridayError",
80
+ "MemoryError",
81
+ "ContextOverflowError",
82
+ "ProviderAPIError",
83
+ # Logging
84
+ "LoggerProtocol",
85
+ "get_logger",
86
+ # Telemetry
87
+ "TelemetryInterface",
88
+ "DebugTelemetryRecorder",
89
+ "SpanRecord",
90
+ "EventRecord",
91
+ # Storage Adapters
92
+ "EpisodicStoreAdapter",
93
+ "VectorStoreAdapter",
94
+ "GraphStoreAdapter",
95
+ "NamespacePolicyInterface",
96
+ "MultiAgentMemoryInterface",
97
+ "ArbitrationInterface",
98
+ "ArbitrationDecision",
99
+ "SharedWriteCapability",
100
+ "MemoryPromotionProposal",
101
+ # Context Engineering
102
+ "ContextEngineeringInterface",
103
+ # LLM Interfaces
104
+ "LLMClient",
105
+ "EmbeddingModel",
106
+ "ChatCompletionResponse",
107
+ "ToolCall",
108
+ # Tool Management
109
+ "SchemaFormat",
110
+ "ToolDefinition",
111
+ "ToolAdapter",
112
+ "ToolRegistry",
113
+ # Runtime Interfaces
114
+ "SystemRuntime",
115
+ "AgentInterface",
116
+ "RegistryInterface",
117
+ "LabHarnessInterface",
118
+ # Memory Profiles
119
+ "MemoryProfile",
120
+ "create_vector_store",
121
+ "create_graph_store",
122
+ # Transcript Integration
123
+ "TranscriptBackedEpisodicStore",
124
+ "TranscriptStoreProtocol",
125
+ # Security
126
+ "security",
127
+ ]
128
+
129
+ __version__ = "0.1.0"
friday_core/config.py ADDED
@@ -0,0 +1,39 @@
1
+ """
2
+ Global configuration management using Pydantic Settings.
3
+ Handles environment variable loading and validation.
4
+
5
+ Ref: Batch 0 Specification, Section 3.1
6
+ """
7
+
8
+ from pydantic_settings import BaseSettings, SettingsConfigDict
9
+
10
+
11
+ class FridayBaseSettings(BaseSettings):
12
+ """
13
+ Global settings inherited by all packages.
14
+
15
+ Configuration is loaded from environment variables and .env files.
16
+ Inner components MUST NOT instantiate this directly - configuration
17
+ should be injected via constructor parameters.
18
+
19
+ Example:
20
+ # In application layer (friday-cli):
21
+ settings = FridayBaseSettings()
22
+ engine = ContextEngine(
23
+ model_name=settings.DEFAULT_MODEL,
24
+ api_key=settings.OPENAI_API_KEY
25
+ )
26
+ """
27
+
28
+ APP_ENV: str = "development" # development | production | testing
29
+ LOG_LEVEL: str = "INFO"
30
+
31
+ # LLM Settings (needed by Memory components)
32
+ DEFAULT_MODEL: str = "gpt-4-turbo"
33
+ OPENAI_API_KEY: str | None = None
34
+
35
+ model_config = SettingsConfigDict(
36
+ env_file=".env",
37
+ env_file_encoding="utf-8",
38
+ extra="ignore",
39
+ )
@@ -0,0 +1,50 @@
1
+ """
2
+ Base exception hierarchy for the Friday Framework.
3
+ Defines FridayError, MemoryError, ContextOverflowError, etc.
4
+
5
+ Ref: Batch 0 Specification, Section 4.2
6
+ """
7
+
8
+
9
+ class FridayError(Exception):
10
+ """
11
+ Root exception for the Friday Framework.
12
+
13
+ All framework-specific exceptions inherit from this class,
14
+ allowing consumers to catch all Friday errors with a single handler.
15
+ """
16
+
17
+ pass
18
+
19
+
20
+ class MemoryError(FridayError):
21
+ """
22
+ Base exception for database/storage failures.
23
+
24
+ Raised when operations on Vector, Graph, or Episodic stores fail.
25
+ """
26
+
27
+ pass
28
+
29
+
30
+ class ContextOverflowError(FridayError):
31
+ """
32
+ Raised when the Context Budget is impossible to satisfy.
33
+
34
+ This occurs when the minimum required context (system prompt,
35
+ immediate history, critical user data) exceeds the available
36
+ token budget.
37
+ """
38
+
39
+ pass
40
+
41
+
42
+ class ProviderAPIError(FridayError):
43
+ """
44
+ Raised when LLM provider API calls fail.
45
+
46
+ Wraps errors from LiteLLM, OpenAI, or other provider SDKs
47
+ to provide a consistent error interface.
48
+ """
49
+
50
+ pass
@@ -0,0 +1,98 @@
1
+ """
2
+ Shared Protocol Definitions.
3
+
4
+ This module exports all abstract base classes (protocols) that define
5
+ the contracts for swappable components in the Friday Framework.
6
+
7
+ Storage Adapters (Batch 1):
8
+ - EpisodicStoreAdapter: Short-term conversation history
9
+ - VectorStoreAdapter: Semantic search storage
10
+ - GraphStoreAdapter: Relationship graph storage
11
+
12
+ Context Engineering (Batch 2a):
13
+ - ContextEngineeringInterface: Context strategy lifecycle
14
+
15
+ LLM Interfaces (Batch 3):
16
+ - LLMClient: Chat completion protocol
17
+ - EmbeddingModel: Text embedding protocol
18
+ - ChatCompletionResponse: Structured LLM response
19
+ - ToolCall: Tool call representation
20
+
21
+ Tool Management (Batch 3):
22
+ - ToolRegistry: Tool registration and resolution
23
+
24
+ Runtime Interfaces (Phase 1):
25
+ - SystemRuntime: Headless runtime kernel contract
26
+ - AgentInterface: Agent execution contract
27
+ - RegistryInterface: Agent registry contract
28
+ - LabHarnessInterface: Integration test harness contract
29
+
30
+ Transcript Integration:
31
+ - TranscriptBackedEpisodicStore: Bridge adapter for persistent transcripts
32
+ """
33
+
34
+ from friday_core.interfaces.agent import AgentInterface
35
+ from friday_core.interfaces.context import ContextEngineeringInterface
36
+ from friday_core.interfaces.lab import LabHarnessInterface
37
+ from friday_core.interfaces.llm import (
38
+ ChatCompletionResponse,
39
+ EmbeddingModel,
40
+ LLMClient,
41
+ ToolCall,
42
+ )
43
+ from friday_core.interfaces.memory import (
44
+ ArbitrationDecision,
45
+ ArbitrationInterface,
46
+ EpisodicStoreAdapter,
47
+ GraphStoreAdapter,
48
+ MemoryPromotionProposal,
49
+ MultiAgentMemoryInterface,
50
+ NamespacePolicyInterface,
51
+ SharedWriteCapability,
52
+ VectorStoreAdapter,
53
+ )
54
+ from friday_core.interfaces.registry import RegistryInterface
55
+ from friday_core.interfaces.runtime import SystemRuntime
56
+ from friday_core.interfaces.tools import (
57
+ SchemaFormat,
58
+ ToolAdapter,
59
+ ToolDefinition,
60
+ ToolRegistry,
61
+ )
62
+ from friday_core.interfaces.transcript import (
63
+ TranscriptBackedEpisodicStore,
64
+ TranscriptStoreProtocol,
65
+ )
66
+
67
+ __all__ = [
68
+ # Storage Adapters
69
+ "EpisodicStoreAdapter",
70
+ "VectorStoreAdapter",
71
+ "GraphStoreAdapter",
72
+ "NamespacePolicyInterface",
73
+ "MultiAgentMemoryInterface",
74
+ "ArbitrationInterface",
75
+ "ArbitrationDecision",
76
+ "SharedWriteCapability",
77
+ "MemoryPromotionProposal",
78
+ # Context Engineering
79
+ "ContextEngineeringInterface",
80
+ # LLM Interfaces
81
+ "LLMClient",
82
+ "EmbeddingModel",
83
+ "ChatCompletionResponse",
84
+ "ToolCall",
85
+ # Tool Management
86
+ "SchemaFormat",
87
+ "ToolDefinition",
88
+ "ToolAdapter",
89
+ "ToolRegistry",
90
+ # Runtime Interfaces
91
+ "SystemRuntime",
92
+ "AgentInterface",
93
+ "RegistryInterface",
94
+ "LabHarnessInterface",
95
+ # Transcript Integration
96
+ "TranscriptBackedEpisodicStore",
97
+ "TranscriptStoreProtocol",
98
+ ]
@@ -0,0 +1,71 @@
1
+ """
2
+ Agent Interface.
3
+
4
+ Defines the AgentInterface contract that all agent implementations
5
+ must satisfy. The interface matches the existing AgentBase signatures
6
+ to ensure backward compatibility.
7
+
8
+ Ref: Phase 1 Build Plan, Section 2 - Interface Compliance Matrix
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from abc import ABC, abstractmethod
14
+ from typing import Any
15
+
16
+
17
+ class AgentInterface(ABC):
18
+ """
19
+ Abstract interface for all Friday agents.
20
+
21
+ Defines the minimal contract for agent lifecycle management
22
+ and execution. The signatures intentionally match AgentBase
23
+ to ensure existing implementations comply without modification.
24
+ """
25
+
26
+ @abstractmethod
27
+ async def run(self, input_signal: str) -> str:
28
+ """
29
+ Execute the agent's core logic on the given input.
30
+
31
+ Args:
32
+ input_signal: User or orchestrator input to process.
33
+
34
+ Returns:
35
+ Agent response string.
36
+ """
37
+ ...
38
+
39
+ @abstractmethod
40
+ async def initialize_session(
41
+ self,
42
+ session_id: str | None = None,
43
+ user_id: str = "default",
44
+ ) -> Any:
45
+ """
46
+ Initialize or resume a session for this agent.
47
+
48
+ Args:
49
+ session_id: Existing session ID to resume, or None
50
+ to create a new session.
51
+ user_id: User identifier for the session.
52
+
53
+ Returns:
54
+ SessionState instance for the initialized session.
55
+
56
+ Note:
57
+ This signature matches AgentBase.initialize_session(),
58
+ not the original spec's (session_id: str, user_id: str) -> None.
59
+ """
60
+ ...
61
+
62
+ @abstractmethod
63
+ def emit_telemetry(self, event_type: str, data: dict[str, Any]) -> None:
64
+ """
65
+ Emit a telemetry event.
66
+
67
+ Args:
68
+ event_type: Type of event to emit.
69
+ data: Event payload data.
70
+ """
71
+ ...
@@ -0,0 +1,187 @@
1
+ """
2
+ Context Engineering Interface Protocol.
3
+ Defines the standard lifecycle for context engineering strategies.
4
+
5
+ Ref: Batch 2a Specification, Section 1.1
6
+
7
+ Note: Type references like 'SessionState', 'ConsolidationReport', 'ContextPayload',
8
+ and 'Interaction' are forward references to models that will be defined in
9
+ friday-memory/models/. This allows the protocol to be defined without circular imports.
10
+ """
11
+
12
+ from abc import ABC, abstractmethod
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ if TYPE_CHECKING:
16
+ # Forward references to types defined in friday-memory/models/
17
+ # These are only used for type checking, not at runtime
18
+ from typing import TypeAlias
19
+
20
+ SessionState: TypeAlias = Any # Will be friday_memory.models.SessionState
21
+ ConsolidationReport: TypeAlias = (
22
+ Any # Will be friday_memory.models.ConsolidationReport
23
+ )
24
+ ContextPayload: TypeAlias = Any # Will be friday_memory.models.ContextPayload
25
+ Interaction: TypeAlias = Any # Will be friday_memory.models.Interaction
26
+
27
+
28
+ class ContextEngineeringInterface(ABC):
29
+ """
30
+ The Master Protocol for Context Engineering.
31
+
32
+ Defines the standard lifecycle methods that any context strategy must
33
+ implement. This abstraction ensures the underlying Memory Architecture
34
+ is decoupled from the strategy used to process it.
35
+
36
+ Lifecycle:
37
+ 1. initialize_session() - Start or resume a session
38
+ 2. extract_context() - Harvest facts from new interactions
39
+ 3. consolidate_memory() - Merge short-term into long-term memory
40
+ 4. assemble_context() - Build the context payload for inference
41
+ 5. format_prompt() - Structure the final prompt for the LLM
42
+
43
+ Implementations:
44
+ - ContextAssembler (default for Friday Copilot)
45
+ - Custom strategies can be "snapped in" via this interface
46
+ """
47
+
48
+ # --- Session Management ---
49
+
50
+ @abstractmethod
51
+ async def initialize_session(self, session_id: str, user_id: str) -> "SessionState":
52
+ """
53
+ Loads or creates the session context, establishing the 'Thread'.
54
+
55
+ Args:
56
+ session_id: Unique identifier for the session
57
+ user_id: Unique identifier for the user
58
+
59
+ Returns:
60
+ SessionState containing session metadata and scoped variables
61
+ """
62
+ pass
63
+
64
+ @abstractmethod
65
+ async def restore_checkpoint(self, session_id: str, turn_id: str) -> "SessionState":
66
+ """
67
+ Reverts the session state to a previous turn.
68
+
69
+ Used for error recovery - allows "time travel" to undo mistakes.
70
+
71
+ Algorithm:
72
+ 1. Triggers MemoryController.rollback_session()
73
+ 2. Reloads the SessionState effective at that time
74
+
75
+ Args:
76
+ session_id: Unique identifier for the session
77
+ turn_id: The turn ID to restore to
78
+
79
+ Returns:
80
+ SessionState as it was at the target turn
81
+ """
82
+ pass
83
+
84
+ # --- The Ingestion Cycle (Extraction) ---
85
+
86
+ @abstractmethod
87
+ async def extract_context(
88
+ self, interaction_turn: "Interaction", async_execution: bool = True
89
+ ) -> None:
90
+ """
91
+ Analyzes the last turn to identify 'Hot' facts or memories.
92
+
93
+ Triggers 'Memory Generation' (Extraction) tasks to harvest
94
+ entities, preferences, and other structured data from the
95
+ raw conversation.
96
+
97
+ Args:
98
+ interaction_turn: The completed interaction to analyze
99
+ async_execution: If True, run extraction in background (default)
100
+ If False, block until extraction completes
101
+ """
102
+ pass
103
+
104
+ # --- The Maintenance Cycle (Consolidation) ---
105
+
106
+ @abstractmethod
107
+ async def consolidate_memory(self, session_id: str) -> "ConsolidationReport":
108
+ """
109
+ Merges fragmented short-term memories into solidified long-term blocks.
110
+
111
+ Performs:
112
+ - Deduplication of similar facts
113
+ - Summarization of verbose interaction sequences
114
+ - Conflict resolution when facts contradict
115
+ - Entity resolution (merging 'Bob' and 'Robert')
116
+
117
+ Args:
118
+ session_id: The session to consolidate
119
+
120
+ Returns:
121
+ ConsolidationReport with statistics on the consolidation
122
+ """
123
+ pass
124
+
125
+ # --- The Retrieval Cycle (Construction) ---
126
+
127
+ @abstractmethod
128
+ async def assemble_context(
129
+ self,
130
+ query: str,
131
+ state: "SessionState",
132
+ budget_limit: int,
133
+ context_strategy: str = "standard",
134
+ ) -> "ContextPayload":
135
+ """
136
+ The core 'Recall' step - selects, ranks, and compresses data.
137
+
138
+ Supports both Passive and Active retrieval:
139
+ - Passive: query is the user's message (broad search)
140
+ - Active: query is agent-generated for specific lookup
141
+
142
+ Uses the Knapsack algorithm to fit content within token budget,
143
+ prioritizing by the defined hierarchy (immediate context > recent
144
+ history > weak matches > deep history).
145
+
146
+ Args:
147
+ query: The search string (user message or agent query)
148
+ state: Current SessionState with scoped variables
149
+ budget_limit: Maximum tokens for dynamic content
150
+ context_strategy: Retrieval strategy name. `minimal` may bypass
151
+ semantic recall, while `standard` and `extended` use the full
152
+ semantic memory pipeline.
153
+
154
+ Returns:
155
+ ContextPayload with history, passages, entities, facts
156
+ """
157
+ pass
158
+
159
+ # --- The Formatting Cycle (Architecture) ---
160
+
161
+ @abstractmethod
162
+ async def format_prompt(
163
+ self, system_prompt: str, payload: "ContextPayload"
164
+ ) -> list[dict[str, Any]]:
165
+ """
166
+ Physically arranges the messages for optimal model attention.
167
+
168
+ Structures the prompt to combat "Lost in the Middle" by placing
169
+ critical information at start and end of context.
170
+
171
+ Layout order:
172
+ 1. System Block (identity & guardrails)
173
+ 2. Transparency Block (recent auto-archived memories)
174
+ 3. Procedural Memory (few-shot examples)
175
+ 4. Semantic Memory (vector passages)
176
+ 5. Episodic Memory (conversation history)
177
+ 6. State Memory (scoped variables)
178
+ 7. User Trigger (the query)
179
+
180
+ Args:
181
+ system_prompt: The system instructions
182
+ payload: The assembled ContextPayload
183
+
184
+ Returns:
185
+ List of message dicts ready for LLM API (role, content format)
186
+ """
187
+ pass
@@ -0,0 +1,65 @@
1
+ """
2
+ Lab Harness Interface.
3
+
4
+ Defines the LabHarnessInterface for integration testing the
5
+ agent framework in a controlled, deterministic environment.
6
+
7
+ Ref: Phase 1 Build Plan, Section 7
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from abc import ABC, abstractmethod
13
+ from typing import Any
14
+
15
+
16
+ class LabHarnessInterface(ABC):
17
+ """
18
+ Integration environment for stress-testing the agent hive.
19
+
20
+ Provides deterministic test execution by replacing LLM agents
21
+ with mock implementations and enabling controlled conflict
22
+ injection and session replay.
23
+ """
24
+
25
+ @abstractmethod
26
+ def mock_agent(self, name: str, fixed_responses: list[str]) -> None:
27
+ """
28
+ Replace a real LLM agent with a deterministic mock.
29
+
30
+ The mock agent returns responses from `fixed_responses` in
31
+ order, cycling back to the start if exhausted.
32
+
33
+ Args:
34
+ name: Agent name to mock.
35
+ fixed_responses: Ordered list of responses the mock
36
+ will return.
37
+ """
38
+ ...
39
+
40
+ @abstractmethod
41
+ async def inject_conflict(self, fact_a: Any, fact_b: Any) -> None:
42
+ """
43
+ Simulate a race condition or semantic conflict.
44
+
45
+ Args:
46
+ fact_a: First conflicting memory proposal.
47
+ fact_b: Second conflicting memory proposal.
48
+
49
+ Raises:
50
+ NotImplementedError: In Phase 1 (requires Arbitrator).
51
+ """
52
+ ...
53
+
54
+ @abstractmethod
55
+ async def replay_session(self, session_log_path: str) -> None:
56
+ """
57
+ Deterministically replay a recorded session.
58
+
59
+ Args:
60
+ session_log_path: Path to session transcript log.
61
+
62
+ Raises:
63
+ NotImplementedError: In Phase 1 (requires transcript tooling).
64
+ """
65
+ ...