remdb 0.3.242__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.
Potentially problematic release.
This version of remdb might be problematic. Click here for more details.
- rem/__init__.py +129 -0
- rem/agentic/README.md +760 -0
- rem/agentic/__init__.py +54 -0
- rem/agentic/agents/README.md +155 -0
- rem/agentic/agents/__init__.py +38 -0
- rem/agentic/agents/agent_manager.py +311 -0
- rem/agentic/agents/sse_simulator.py +502 -0
- rem/agentic/context.py +425 -0
- rem/agentic/context_builder.py +360 -0
- rem/agentic/llm_provider_models.py +301 -0
- rem/agentic/mcp/__init__.py +0 -0
- rem/agentic/mcp/tool_wrapper.py +273 -0
- rem/agentic/otel/__init__.py +5 -0
- rem/agentic/otel/setup.py +240 -0
- rem/agentic/providers/phoenix.py +926 -0
- rem/agentic/providers/pydantic_ai.py +854 -0
- rem/agentic/query.py +117 -0
- rem/agentic/query_helper.py +89 -0
- rem/agentic/schema.py +737 -0
- rem/agentic/serialization.py +245 -0
- rem/agentic/tools/__init__.py +5 -0
- rem/agentic/tools/rem_tools.py +242 -0
- rem/api/README.md +657 -0
- rem/api/deps.py +253 -0
- rem/api/main.py +460 -0
- rem/api/mcp_router/prompts.py +182 -0
- rem/api/mcp_router/resources.py +820 -0
- rem/api/mcp_router/server.py +243 -0
- rem/api/mcp_router/tools.py +1605 -0
- rem/api/middleware/tracking.py +172 -0
- rem/api/routers/admin.py +520 -0
- rem/api/routers/auth.py +898 -0
- rem/api/routers/chat/__init__.py +5 -0
- rem/api/routers/chat/child_streaming.py +394 -0
- rem/api/routers/chat/completions.py +702 -0
- rem/api/routers/chat/json_utils.py +76 -0
- rem/api/routers/chat/models.py +202 -0
- rem/api/routers/chat/otel_utils.py +33 -0
- rem/api/routers/chat/sse_events.py +546 -0
- rem/api/routers/chat/streaming.py +950 -0
- rem/api/routers/chat/streaming_utils.py +327 -0
- rem/api/routers/common.py +18 -0
- rem/api/routers/dev.py +87 -0
- rem/api/routers/feedback.py +276 -0
- rem/api/routers/messages.py +620 -0
- rem/api/routers/models.py +86 -0
- rem/api/routers/query.py +362 -0
- rem/api/routers/shared_sessions.py +422 -0
- rem/auth/README.md +258 -0
- rem/auth/__init__.py +36 -0
- rem/auth/jwt.py +367 -0
- rem/auth/middleware.py +318 -0
- rem/auth/providers/__init__.py +16 -0
- rem/auth/providers/base.py +376 -0
- rem/auth/providers/email.py +215 -0
- rem/auth/providers/google.py +163 -0
- rem/auth/providers/microsoft.py +237 -0
- rem/cli/README.md +517 -0
- rem/cli/__init__.py +8 -0
- rem/cli/commands/README.md +299 -0
- rem/cli/commands/__init__.py +3 -0
- rem/cli/commands/ask.py +549 -0
- rem/cli/commands/cluster.py +1808 -0
- rem/cli/commands/configure.py +495 -0
- rem/cli/commands/db.py +828 -0
- rem/cli/commands/dreaming.py +324 -0
- rem/cli/commands/experiments.py +1698 -0
- rem/cli/commands/mcp.py +66 -0
- rem/cli/commands/process.py +388 -0
- rem/cli/commands/query.py +109 -0
- rem/cli/commands/scaffold.py +47 -0
- rem/cli/commands/schema.py +230 -0
- rem/cli/commands/serve.py +106 -0
- rem/cli/commands/session.py +453 -0
- rem/cli/dreaming.py +363 -0
- rem/cli/main.py +123 -0
- rem/config.py +244 -0
- rem/mcp_server.py +41 -0
- rem/models/core/__init__.py +49 -0
- rem/models/core/core_model.py +70 -0
- rem/models/core/engram.py +333 -0
- rem/models/core/experiment.py +672 -0
- rem/models/core/inline_edge.py +132 -0
- rem/models/core/rem_query.py +246 -0
- rem/models/entities/__init__.py +68 -0
- rem/models/entities/domain_resource.py +38 -0
- rem/models/entities/feedback.py +123 -0
- rem/models/entities/file.py +57 -0
- rem/models/entities/image_resource.py +88 -0
- rem/models/entities/message.py +64 -0
- rem/models/entities/moment.py +123 -0
- rem/models/entities/ontology.py +181 -0
- rem/models/entities/ontology_config.py +131 -0
- rem/models/entities/resource.py +95 -0
- rem/models/entities/schema.py +87 -0
- rem/models/entities/session.py +84 -0
- rem/models/entities/shared_session.py +180 -0
- rem/models/entities/subscriber.py +175 -0
- rem/models/entities/user.py +93 -0
- rem/py.typed +0 -0
- rem/registry.py +373 -0
- rem/schemas/README.md +507 -0
- rem/schemas/__init__.py +6 -0
- rem/schemas/agents/README.md +92 -0
- rem/schemas/agents/core/agent-builder.yaml +235 -0
- rem/schemas/agents/core/moment-builder.yaml +178 -0
- rem/schemas/agents/core/rem-query-agent.yaml +226 -0
- rem/schemas/agents/core/resource-affinity-assessor.yaml +99 -0
- rem/schemas/agents/core/simple-assistant.yaml +19 -0
- rem/schemas/agents/core/user-profile-builder.yaml +163 -0
- rem/schemas/agents/examples/contract-analyzer.yaml +317 -0
- rem/schemas/agents/examples/contract-extractor.yaml +134 -0
- rem/schemas/agents/examples/cv-parser.yaml +263 -0
- rem/schemas/agents/examples/hello-world.yaml +37 -0
- rem/schemas/agents/examples/query.yaml +54 -0
- rem/schemas/agents/examples/simple.yaml +21 -0
- rem/schemas/agents/examples/test.yaml +29 -0
- rem/schemas/agents/rem.yaml +132 -0
- rem/schemas/evaluators/hello-world/default.yaml +77 -0
- rem/schemas/evaluators/rem/faithfulness.yaml +219 -0
- rem/schemas/evaluators/rem/lookup-correctness.yaml +182 -0
- rem/schemas/evaluators/rem/retrieval-precision.yaml +199 -0
- rem/schemas/evaluators/rem/retrieval-recall.yaml +211 -0
- rem/schemas/evaluators/rem/search-correctness.yaml +192 -0
- rem/services/__init__.py +18 -0
- rem/services/audio/INTEGRATION.md +308 -0
- rem/services/audio/README.md +376 -0
- rem/services/audio/__init__.py +15 -0
- rem/services/audio/chunker.py +354 -0
- rem/services/audio/transcriber.py +259 -0
- rem/services/content/README.md +1269 -0
- rem/services/content/__init__.py +5 -0
- rem/services/content/providers.py +760 -0
- rem/services/content/service.py +762 -0
- rem/services/dreaming/README.md +230 -0
- rem/services/dreaming/__init__.py +53 -0
- rem/services/dreaming/affinity_service.py +322 -0
- rem/services/dreaming/moment_service.py +251 -0
- rem/services/dreaming/ontology_service.py +54 -0
- rem/services/dreaming/user_model_service.py +297 -0
- rem/services/dreaming/utils.py +39 -0
- rem/services/email/__init__.py +10 -0
- rem/services/email/service.py +522 -0
- rem/services/email/templates.py +360 -0
- rem/services/embeddings/__init__.py +11 -0
- rem/services/embeddings/api.py +127 -0
- rem/services/embeddings/worker.py +435 -0
- rem/services/fs/README.md +662 -0
- rem/services/fs/__init__.py +62 -0
- rem/services/fs/examples.py +206 -0
- rem/services/fs/examples_paths.py +204 -0
- rem/services/fs/git_provider.py +935 -0
- rem/services/fs/local_provider.py +760 -0
- rem/services/fs/parsing-hooks-examples.md +172 -0
- rem/services/fs/paths.py +276 -0
- rem/services/fs/provider.py +460 -0
- rem/services/fs/s3_provider.py +1042 -0
- rem/services/fs/service.py +186 -0
- rem/services/git/README.md +1075 -0
- rem/services/git/__init__.py +17 -0
- rem/services/git/service.py +469 -0
- rem/services/phoenix/EXPERIMENT_DESIGN.md +1146 -0
- rem/services/phoenix/README.md +453 -0
- rem/services/phoenix/__init__.py +46 -0
- rem/services/phoenix/client.py +960 -0
- rem/services/phoenix/config.py +88 -0
- rem/services/phoenix/prompt_labels.py +477 -0
- rem/services/postgres/README.md +757 -0
- rem/services/postgres/__init__.py +49 -0
- rem/services/postgres/diff_service.py +599 -0
- rem/services/postgres/migration_service.py +427 -0
- rem/services/postgres/programmable_diff_service.py +635 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +562 -0
- rem/services/postgres/register_type.py +353 -0
- rem/services/postgres/repository.py +481 -0
- rem/services/postgres/schema_generator.py +661 -0
- rem/services/postgres/service.py +802 -0
- rem/services/postgres/sql_builder.py +355 -0
- rem/services/rate_limit.py +113 -0
- rem/services/rem/README.md +318 -0
- rem/services/rem/__init__.py +23 -0
- rem/services/rem/exceptions.py +71 -0
- rem/services/rem/executor.py +293 -0
- rem/services/rem/parser.py +180 -0
- rem/services/rem/queries.py +196 -0
- rem/services/rem/query.py +371 -0
- rem/services/rem/service.py +608 -0
- rem/services/session/README.md +374 -0
- rem/services/session/__init__.py +13 -0
- rem/services/session/compression.py +488 -0
- rem/services/session/pydantic_messages.py +310 -0
- rem/services/session/reload.py +85 -0
- rem/services/user_service.py +130 -0
- rem/settings.py +1877 -0
- rem/sql/background_indexes.sql +52 -0
- rem/sql/migrations/001_install.sql +983 -0
- rem/sql/migrations/002_install_models.sql +3157 -0
- rem/sql/migrations/003_optional_extensions.sql +326 -0
- rem/sql/migrations/004_cache_system.sql +282 -0
- rem/sql/migrations/005_schema_update.sql +145 -0
- rem/sql/migrations/migrate_session_id_to_uuid.sql +45 -0
- rem/utils/AGENTIC_CHUNKING.md +597 -0
- rem/utils/README.md +628 -0
- rem/utils/__init__.py +61 -0
- rem/utils/agentic_chunking.py +622 -0
- rem/utils/batch_ops.py +343 -0
- rem/utils/chunking.py +108 -0
- rem/utils/clip_embeddings.py +276 -0
- rem/utils/constants.py +97 -0
- rem/utils/date_utils.py +228 -0
- rem/utils/dict_utils.py +98 -0
- rem/utils/embeddings.py +436 -0
- rem/utils/examples/embeddings_example.py +305 -0
- rem/utils/examples/sql_types_example.py +202 -0
- rem/utils/files.py +323 -0
- rem/utils/markdown.py +16 -0
- rem/utils/mime_types.py +158 -0
- rem/utils/model_helpers.py +492 -0
- rem/utils/schema_loader.py +649 -0
- rem/utils/sql_paths.py +146 -0
- rem/utils/sql_types.py +350 -0
- rem/utils/user_id.py +81 -0
- rem/utils/vision.py +325 -0
- rem/workers/README.md +506 -0
- rem/workers/__init__.py +7 -0
- rem/workers/db_listener.py +579 -0
- rem/workers/db_maintainer.py +74 -0
- rem/workers/dreaming.py +502 -0
- rem/workers/engram_processor.py +312 -0
- rem/workers/sqs_file_processor.py +193 -0
- rem/workers/unlogged_maintainer.py +463 -0
- remdb-0.3.242.dist-info/METADATA +1632 -0
- remdb-0.3.242.dist-info/RECORD +235 -0
- remdb-0.3.242.dist-info/WHEEL +4 -0
- remdb-0.3.242.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SSE Event Types for Rich Streaming Responses.
|
|
3
|
+
|
|
4
|
+
This module defines custom Server-Sent Events (SSE) event types that extend
|
|
5
|
+
beyond simple text streaming.
|
|
6
|
+
|
|
7
|
+
## SSE Protocol
|
|
8
|
+
|
|
9
|
+
Text content uses **OpenAI-compatible format** (plain `data:` prefix):
|
|
10
|
+
```
|
|
11
|
+
data: {"id":"chatcmpl-...","choices":[{"delta":{"content":"Hello"}}]}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Custom events use **named event format** (`event:` prefix):
|
|
15
|
+
```
|
|
16
|
+
event: reasoning
|
|
17
|
+
data: {"type": "reasoning", "content": "Analyzing...", "step": 1}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Event Types
|
|
21
|
+
|
|
22
|
+
| Event | Format | Purpose |
|
|
23
|
+
|-------|--------|---------|
|
|
24
|
+
| (text) | `data:` (OpenAI) | Content chunks - main response |
|
|
25
|
+
| reasoning | `event:` | Model thinking/chain-of-thought |
|
|
26
|
+
| progress | `event:` | Step indicators |
|
|
27
|
+
| tool_call | `event:` | Tool invocation start/complete |
|
|
28
|
+
| metadata | `event:` | System metadata (confidence, sources) |
|
|
29
|
+
| action_request | `event:` | UI solicitation (buttons, forms) |
|
|
30
|
+
| error | `event:` | Error notifications |
|
|
31
|
+
| done | `event:` | Stream completion marker |
|
|
32
|
+
|
|
33
|
+
## Action Schema Design
|
|
34
|
+
|
|
35
|
+
- Inspired by Microsoft Adaptive Cards (https://adaptivecards.io/)
|
|
36
|
+
- JSON Schema-based UI element definitions
|
|
37
|
+
- Cross-platform compatibility for React, mobile, etc.
|
|
38
|
+
|
|
39
|
+
## References
|
|
40
|
+
|
|
41
|
+
- MDN SSE: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
|
|
42
|
+
- Adaptive Cards: https://adaptivecards.io/explorer/
|
|
43
|
+
- Model Context Protocol: https://modelcontextprotocol.io/specification/2025-06-18
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
from enum import Enum
|
|
47
|
+
from typing import Any, Literal
|
|
48
|
+
from pydantic import BaseModel, Field
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class SSEEventType(str, Enum):
|
|
52
|
+
"""SSE event types for streaming responses."""
|
|
53
|
+
|
|
54
|
+
TEXT_DELTA = "text_delta" # Standard text chunk
|
|
55
|
+
REASONING = "reasoning" # Model thinking/reasoning
|
|
56
|
+
ACTION_REQUEST = "action_request" # UI action solicitation
|
|
57
|
+
METADATA = "metadata" # System metadata
|
|
58
|
+
PROGRESS = "progress" # Progress indicator
|
|
59
|
+
TOOL_CALL = "tool_call" # Tool invocation
|
|
60
|
+
ERROR = "error" # Error notification
|
|
61
|
+
DONE = "done" # Stream complete
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# Action Solicitation Schema (Adaptive Cards-inspired)
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
class ActionStyle(str, Enum):
|
|
69
|
+
"""Visual style for action buttons."""
|
|
70
|
+
|
|
71
|
+
DEFAULT = "default"
|
|
72
|
+
PRIMARY = "primary"
|
|
73
|
+
SECONDARY = "secondary"
|
|
74
|
+
DESTRUCTIVE = "destructive"
|
|
75
|
+
POSITIVE = "positive"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class ActionSubmit(BaseModel):
|
|
79
|
+
"""
|
|
80
|
+
Submit action - triggers callback to server with payload.
|
|
81
|
+
|
|
82
|
+
Inspired by Adaptive Cards Action.Submit:
|
|
83
|
+
https://adaptivecards.io/explorer/Action.Submit.html
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
type: Literal["Action.Submit"] = "Action.Submit"
|
|
87
|
+
id: str = Field(description="Unique action identifier")
|
|
88
|
+
title: str = Field(description="Button label text")
|
|
89
|
+
style: ActionStyle = Field(
|
|
90
|
+
default=ActionStyle.DEFAULT,
|
|
91
|
+
description="Visual style"
|
|
92
|
+
)
|
|
93
|
+
data: dict[str, Any] = Field(
|
|
94
|
+
default_factory=dict,
|
|
95
|
+
description="Payload sent to server when action is triggered"
|
|
96
|
+
)
|
|
97
|
+
tooltip: str | None = Field(
|
|
98
|
+
default=None,
|
|
99
|
+
description="Tooltip text on hover"
|
|
100
|
+
)
|
|
101
|
+
icon_url: str | None = Field(
|
|
102
|
+
default=None,
|
|
103
|
+
description="Optional icon URL"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ActionOpenUrl(BaseModel):
|
|
108
|
+
"""
|
|
109
|
+
Open URL action - navigates to external URL.
|
|
110
|
+
|
|
111
|
+
Inspired by Adaptive Cards Action.OpenUrl:
|
|
112
|
+
https://adaptivecards.io/explorer/Action.OpenUrl.html
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
type: Literal["Action.OpenUrl"] = "Action.OpenUrl"
|
|
116
|
+
id: str = Field(description="Unique action identifier")
|
|
117
|
+
title: str = Field(description="Button label text")
|
|
118
|
+
url: str = Field(description="URL to open")
|
|
119
|
+
style: ActionStyle = Field(default=ActionStyle.DEFAULT)
|
|
120
|
+
tooltip: str | None = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ActionShowCard(BaseModel):
|
|
124
|
+
"""
|
|
125
|
+
Show card action - reveals nested content inline.
|
|
126
|
+
|
|
127
|
+
Inspired by Adaptive Cards Action.ShowCard:
|
|
128
|
+
https://adaptivecards.io/explorer/Action.ShowCard.html
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
type: Literal["Action.ShowCard"] = "Action.ShowCard"
|
|
132
|
+
id: str = Field(description="Unique action identifier")
|
|
133
|
+
title: str = Field(description="Button label text")
|
|
134
|
+
card: dict[str, Any] = Field(
|
|
135
|
+
description="Nested card content to reveal (Adaptive Card JSON)"
|
|
136
|
+
)
|
|
137
|
+
style: ActionStyle = Field(default=ActionStyle.DEFAULT)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Union type for all action types
|
|
141
|
+
ActionType = ActionSubmit | ActionOpenUrl | ActionShowCard
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class InputText(BaseModel):
|
|
145
|
+
"""Text input field for action cards."""
|
|
146
|
+
|
|
147
|
+
type: Literal["Input.Text"] = "Input.Text"
|
|
148
|
+
id: str = Field(description="Input field identifier (used in submit payload)")
|
|
149
|
+
label: str | None = Field(default=None, description="Input label")
|
|
150
|
+
placeholder: str | None = Field(default=None, description="Placeholder text")
|
|
151
|
+
is_required: bool = Field(default=False, description="Whether input is required")
|
|
152
|
+
is_multiline: bool = Field(default=False, description="Multi-line text area")
|
|
153
|
+
max_length: int | None = Field(default=None, description="Maximum character length")
|
|
154
|
+
value: str | None = Field(default=None, description="Default value")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class InputChoiceSet(BaseModel):
|
|
158
|
+
"""Choice/select input for action cards."""
|
|
159
|
+
|
|
160
|
+
type: Literal["Input.ChoiceSet"] = "Input.ChoiceSet"
|
|
161
|
+
id: str = Field(description="Input field identifier")
|
|
162
|
+
label: str | None = None
|
|
163
|
+
choices: list[dict[str, str]] = Field(
|
|
164
|
+
description="List of {title, value} choice objects"
|
|
165
|
+
)
|
|
166
|
+
is_required: bool = False
|
|
167
|
+
is_multi_select: bool = Field(default=False, description="Allow multiple selections")
|
|
168
|
+
value: str | None = Field(default=None, description="Default selected value")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class InputToggle(BaseModel):
|
|
172
|
+
"""Toggle/checkbox input for action cards."""
|
|
173
|
+
|
|
174
|
+
type: Literal["Input.Toggle"] = "Input.Toggle"
|
|
175
|
+
id: str = Field(description="Input field identifier")
|
|
176
|
+
title: str = Field(description="Toggle label text")
|
|
177
|
+
value: str = Field(default="false", description="Current value ('true'/'false')")
|
|
178
|
+
value_on: str = Field(default="true", description="Value when toggled on")
|
|
179
|
+
value_off: str = Field(default="false", description="Value when toggled off")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# Union type for all input types
|
|
183
|
+
InputType = InputText | InputChoiceSet | InputToggle
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ActionDisplayStyle(str, Enum):
|
|
187
|
+
"""How to display the action request in the UI."""
|
|
188
|
+
|
|
189
|
+
INLINE = "inline" # Rendered inline after message content
|
|
190
|
+
FLOATING = "floating" # Floating panel/overlay
|
|
191
|
+
MODAL = "modal" # Modal dialog
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ActionRequestCard(BaseModel):
|
|
195
|
+
"""
|
|
196
|
+
Action solicitation card - requests user input or action.
|
|
197
|
+
|
|
198
|
+
This is the main payload for action_request SSE events.
|
|
199
|
+
Uses Adaptive Cards-inspired schema for cross-platform UI compatibility.
|
|
200
|
+
|
|
201
|
+
Example use cases:
|
|
202
|
+
- Confirm/cancel dialogs
|
|
203
|
+
- Form inputs (name, email, etc.)
|
|
204
|
+
- Multi-choice selections
|
|
205
|
+
- Quick reply buttons
|
|
206
|
+
- Feedback collection (thumbs up/down)
|
|
207
|
+
|
|
208
|
+
Example:
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"id": "confirm-delete-123",
|
|
212
|
+
"prompt": "Are you sure you want to delete this item?",
|
|
213
|
+
"display_style": "modal",
|
|
214
|
+
"actions": [
|
|
215
|
+
{
|
|
216
|
+
"type": "Action.Submit",
|
|
217
|
+
"id": "confirm",
|
|
218
|
+
"title": "Delete",
|
|
219
|
+
"style": "destructive",
|
|
220
|
+
"data": {"action": "delete", "item_id": "123"}
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"type": "Action.Submit",
|
|
224
|
+
"id": "cancel",
|
|
225
|
+
"title": "Cancel",
|
|
226
|
+
"style": "secondary",
|
|
227
|
+
"data": {"action": "cancel"}
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
"timeout_ms": 30000
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
id: str = Field(description="Unique card identifier for response correlation")
|
|
236
|
+
prompt: str = Field(description="Prompt text explaining what action is requested")
|
|
237
|
+
display_style: ActionDisplayStyle = Field(
|
|
238
|
+
default=ActionDisplayStyle.INLINE,
|
|
239
|
+
description="How to display in the UI"
|
|
240
|
+
)
|
|
241
|
+
actions: list[ActionType] = Field(
|
|
242
|
+
default_factory=list,
|
|
243
|
+
description="Available actions (buttons)"
|
|
244
|
+
)
|
|
245
|
+
inputs: list[InputType] = Field(
|
|
246
|
+
default_factory=list,
|
|
247
|
+
description="Input fields for data collection"
|
|
248
|
+
)
|
|
249
|
+
timeout_ms: int | None = Field(
|
|
250
|
+
default=None,
|
|
251
|
+
description="Auto-dismiss timeout in milliseconds"
|
|
252
|
+
)
|
|
253
|
+
fallback_text: str | None = Field(
|
|
254
|
+
default=None,
|
|
255
|
+
description="Text to show if card rendering fails"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
# =============================================================================
|
|
260
|
+
# SSE Event Payloads
|
|
261
|
+
# =============================================================================
|
|
262
|
+
|
|
263
|
+
class TextDeltaEvent(BaseModel):
|
|
264
|
+
"""Text content delta event (OpenAI-compatible)."""
|
|
265
|
+
|
|
266
|
+
type: Literal["text_delta"] = "text_delta"
|
|
267
|
+
content: str = Field(description="Text content chunk")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class ReasoningEvent(BaseModel):
|
|
271
|
+
"""
|
|
272
|
+
Reasoning/thinking event.
|
|
273
|
+
|
|
274
|
+
Used to stream model's chain-of-thought reasoning separate from
|
|
275
|
+
the main response content. UI can display this in a collapsible
|
|
276
|
+
"thinking" section.
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
type: Literal["reasoning"] = "reasoning"
|
|
280
|
+
content: str = Field(description="Reasoning text chunk")
|
|
281
|
+
step: int | None = Field(
|
|
282
|
+
default=None,
|
|
283
|
+
description="Reasoning step number (for multi-step reasoning)"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class ActionRequestEvent(BaseModel):
|
|
288
|
+
"""
|
|
289
|
+
Action request event - solicits user action.
|
|
290
|
+
|
|
291
|
+
Sent when the agent needs user input or confirmation.
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
type: Literal["action_request"] = "action_request"
|
|
295
|
+
card: ActionRequestCard = Field(description="Action card definition")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class MetadataEvent(BaseModel):
|
|
299
|
+
"""
|
|
300
|
+
Metadata event - system information (often hidden from user).
|
|
301
|
+
|
|
302
|
+
Used for confidence scores, sources, model info, message IDs, etc.
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
type: Literal["metadata"] = "metadata"
|
|
306
|
+
|
|
307
|
+
# Message correlation IDs
|
|
308
|
+
message_id: str | None = Field(
|
|
309
|
+
default=None,
|
|
310
|
+
description="Database ID of the assistant message being streamed"
|
|
311
|
+
)
|
|
312
|
+
in_reply_to: str | None = Field(
|
|
313
|
+
default=None,
|
|
314
|
+
description="Database ID of the user message this is responding to"
|
|
315
|
+
)
|
|
316
|
+
session_id: str | None = Field(
|
|
317
|
+
default=None,
|
|
318
|
+
description="Session ID for this conversation"
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
# Agent info
|
|
322
|
+
agent_schema: str | None = Field(
|
|
323
|
+
default=None,
|
|
324
|
+
description="Name of the top-level agent schema (e.g., 'siggy', 'rem')"
|
|
325
|
+
)
|
|
326
|
+
responding_agent: str | None = Field(
|
|
327
|
+
default=None,
|
|
328
|
+
description="Name of the agent that produced this response (may differ from agent_schema if delegated via ask_agent)"
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
# Session info
|
|
332
|
+
session_name: str | None = Field(
|
|
333
|
+
default=None,
|
|
334
|
+
description="Short 1-3 phrase name for the session topic (e.g., 'Prescription Drug Questions', 'AWS Setup Help')"
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Quality indicators
|
|
338
|
+
confidence: float | None = Field(
|
|
339
|
+
default=None, ge=0, le=1,
|
|
340
|
+
description="Confidence score (0-1)"
|
|
341
|
+
)
|
|
342
|
+
sources: list[str] | None = Field(
|
|
343
|
+
default=None,
|
|
344
|
+
description="Referenced sources/citations"
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Model info
|
|
348
|
+
model_version: str | None = Field(
|
|
349
|
+
default=None,
|
|
350
|
+
description="Model version used"
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
# Performance metrics
|
|
354
|
+
latency_ms: int | None = Field(
|
|
355
|
+
default=None,
|
|
356
|
+
description="Response latency in milliseconds"
|
|
357
|
+
)
|
|
358
|
+
token_count: int | None = Field(
|
|
359
|
+
default=None,
|
|
360
|
+
description="Token count for this response"
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
# Trace context for observability (deterministic, captured from OTEL)
|
|
364
|
+
trace_id: str | None = Field(
|
|
365
|
+
default=None,
|
|
366
|
+
description="OTEL trace ID for correlating with Phoenix/observability systems"
|
|
367
|
+
)
|
|
368
|
+
span_id: str | None = Field(
|
|
369
|
+
default=None,
|
|
370
|
+
description="OTEL span ID for correlating with Phoenix/observability systems"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
# System flags
|
|
374
|
+
flags: list[str] | None = Field(
|
|
375
|
+
default=None,
|
|
376
|
+
description="System flags (e.g., 'uncertain', 'needs_review')"
|
|
377
|
+
)
|
|
378
|
+
hidden: bool = Field(
|
|
379
|
+
default=False,
|
|
380
|
+
description="If true, should not be displayed to user"
|
|
381
|
+
)
|
|
382
|
+
extra: dict[str, Any] | None = Field(
|
|
383
|
+
default=None,
|
|
384
|
+
description="Additional metadata"
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class ProgressEvent(BaseModel):
|
|
389
|
+
"""Progress indicator event."""
|
|
390
|
+
|
|
391
|
+
type: Literal["progress"] = "progress"
|
|
392
|
+
step: int = Field(description="Current step number")
|
|
393
|
+
total_steps: int = Field(description="Total number of steps")
|
|
394
|
+
label: str = Field(description="Step description")
|
|
395
|
+
status: Literal["pending", "in_progress", "completed", "failed"] = Field(
|
|
396
|
+
description="Step status"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class ToolCallEvent(BaseModel):
|
|
401
|
+
"""Tool invocation event."""
|
|
402
|
+
|
|
403
|
+
type: Literal["tool_call"] = "tool_call"
|
|
404
|
+
tool_name: str = Field(description="Name of tool being called")
|
|
405
|
+
tool_id: str | None = Field(
|
|
406
|
+
default=None,
|
|
407
|
+
description="Unique call identifier"
|
|
408
|
+
)
|
|
409
|
+
status: Literal["started", "completed", "failed"] = Field(
|
|
410
|
+
description="Tool call status"
|
|
411
|
+
)
|
|
412
|
+
arguments: dict[str, Any] | None = Field(
|
|
413
|
+
default=None,
|
|
414
|
+
description="Tool arguments (for 'started' status)"
|
|
415
|
+
)
|
|
416
|
+
result: str | dict[str, Any] | None = Field(
|
|
417
|
+
default=None,
|
|
418
|
+
description="Tool result - full dict for finalize_intake, summary string for others"
|
|
419
|
+
)
|
|
420
|
+
error: str | None = Field(
|
|
421
|
+
default=None,
|
|
422
|
+
description="Error message (for 'failed' status)"
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
class ErrorEvent(BaseModel):
|
|
427
|
+
"""Error notification event."""
|
|
428
|
+
|
|
429
|
+
type: Literal["error"] = "error"
|
|
430
|
+
code: str = Field(description="Error code")
|
|
431
|
+
message: str = Field(description="Human-readable error message")
|
|
432
|
+
details: dict[str, Any] | None = Field(
|
|
433
|
+
default=None,
|
|
434
|
+
description="Additional error details"
|
|
435
|
+
)
|
|
436
|
+
recoverable: bool = Field(
|
|
437
|
+
default=True,
|
|
438
|
+
description="Whether error is recoverable"
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class DoneEvent(BaseModel):
|
|
443
|
+
"""Stream completion event."""
|
|
444
|
+
|
|
445
|
+
type: Literal["done"] = "done"
|
|
446
|
+
reason: Literal["stop", "length", "error", "cancelled"] = Field(
|
|
447
|
+
default="stop",
|
|
448
|
+
description="Completion reason"
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
# Union type for all SSE events
|
|
453
|
+
SSEEvent = (
|
|
454
|
+
TextDeltaEvent
|
|
455
|
+
| ReasoningEvent
|
|
456
|
+
| ActionRequestEvent
|
|
457
|
+
| MetadataEvent
|
|
458
|
+
| ProgressEvent
|
|
459
|
+
| ToolCallEvent
|
|
460
|
+
| ErrorEvent
|
|
461
|
+
| DoneEvent
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
# =============================================================================
|
|
466
|
+
# SSE Formatting Helpers
|
|
467
|
+
# =============================================================================
|
|
468
|
+
|
|
469
|
+
def format_sse_event(event: SSEEvent) -> str:
|
|
470
|
+
"""
|
|
471
|
+
Format an SSE event for transmission.
|
|
472
|
+
|
|
473
|
+
Standard data: format for text_delta (OpenAI compatibility).
|
|
474
|
+
Named event: format for other event types.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
event: SSE event to format
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
Formatted SSE string ready for transmission
|
|
481
|
+
|
|
482
|
+
Example:
|
|
483
|
+
>>> event = ReasoningEvent(content="Analyzing...")
|
|
484
|
+
>>> format_sse_event(event)
|
|
485
|
+
'event: reasoning\\ndata: {"type": "reasoning", "content": "Analyzing..."}\\n\\n'
|
|
486
|
+
"""
|
|
487
|
+
import json
|
|
488
|
+
|
|
489
|
+
event_json = event.model_dump_json()
|
|
490
|
+
|
|
491
|
+
# TextDeltaEvent uses standard data: format for OpenAI compatibility
|
|
492
|
+
if isinstance(event, TextDeltaEvent):
|
|
493
|
+
return f"data: {event_json}\n\n"
|
|
494
|
+
|
|
495
|
+
# DoneEvent uses special marker
|
|
496
|
+
if isinstance(event, DoneEvent):
|
|
497
|
+
return f"event: done\ndata: {event_json}\n\n"
|
|
498
|
+
|
|
499
|
+
# All other events use named event format
|
|
500
|
+
event_type = event.type
|
|
501
|
+
return f"event: {event_type}\ndata: {event_json}\n\n"
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def format_openai_sse_chunk(
|
|
505
|
+
request_id: str,
|
|
506
|
+
created: int,
|
|
507
|
+
model: str,
|
|
508
|
+
content: str | None = None,
|
|
509
|
+
role: str | None = None,
|
|
510
|
+
finish_reason: str | None = None,
|
|
511
|
+
) -> str:
|
|
512
|
+
"""
|
|
513
|
+
Format OpenAI-compatible SSE chunk.
|
|
514
|
+
|
|
515
|
+
Args:
|
|
516
|
+
request_id: Request/response ID
|
|
517
|
+
created: Unix timestamp
|
|
518
|
+
model: Model name
|
|
519
|
+
content: Delta content
|
|
520
|
+
role: Message role (usually 'assistant')
|
|
521
|
+
finish_reason: Finish reason (e.g., 'stop')
|
|
522
|
+
|
|
523
|
+
Returns:
|
|
524
|
+
Formatted SSE data line
|
|
525
|
+
"""
|
|
526
|
+
import json
|
|
527
|
+
|
|
528
|
+
delta = {}
|
|
529
|
+
if role:
|
|
530
|
+
delta["role"] = role
|
|
531
|
+
if content is not None:
|
|
532
|
+
delta["content"] = content
|
|
533
|
+
|
|
534
|
+
chunk = {
|
|
535
|
+
"id": request_id,
|
|
536
|
+
"object": "chat.completion.chunk",
|
|
537
|
+
"created": created,
|
|
538
|
+
"model": model,
|
|
539
|
+
"choices": [{
|
|
540
|
+
"index": 0,
|
|
541
|
+
"delta": delta,
|
|
542
|
+
"finish_reason": finish_reason
|
|
543
|
+
}]
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return f"data: {json.dumps(chunk)}\n\n"
|