composer-agent 0.1.0__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.
- chat/__init__.py +0 -0
- chat/apps.py +6 -0
- chat/migrations/0001_initial.py +83 -0
- chat/migrations/__init__.py +0 -0
- chat/models.py +88 -0
- composer/__init__.py +97 -0
- composer/agent.py +1057 -0
- composer/image.py +216 -0
- composer/mcp.py +226 -0
- composer/persistence/__init__.py +3 -0
- composer/persistence/chat_session.py +336 -0
- composer/persistence/cli.py +16 -0
- composer/persistence/django_setup.py +38 -0
- composer/persistence/repository.py +195 -0
- composer/persistence/serializers.py +166 -0
- composer/stream.py +520 -0
- composer/stream_events.py +27 -0
- composer/thread.py +539 -0
- composer/thread_branch.py +287 -0
- composer/tool_hide.py +516 -0
- composer/tools.py +138 -0
- composer/vector.py +110 -0
- composer_agent-0.1.0.dist-info/METADATA +111 -0
- composer_agent-0.1.0.dist-info/RECORD +31 -0
- composer_agent-0.1.0.dist-info/WHEEL +4 -0
- composer_agent-0.1.0.dist-info/entry_points.txt +2 -0
- composer_agent-0.1.0.dist-info/licenses/LICENSE +21 -0
- composer_site/__init__.py +0 -0
- composer_site/settings.py +43 -0
- composer_site/urls.py +1 -0
- composer_site/wsgi.py +7 -0
chat/__init__.py
ADDED
|
File without changes
|
chat/apps.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Generated by Django 6.0.6 on 2026-06-07 17:56
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
import uuid
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
initial = True
|
|
11
|
+
|
|
12
|
+
dependencies = [
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.CreateModel(
|
|
17
|
+
name='ChatSession',
|
|
18
|
+
fields=[
|
|
19
|
+
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
20
|
+
('name', models.CharField(blank=True, default='', max_length=255)),
|
|
21
|
+
('config', models.JSONField(default=dict)),
|
|
22
|
+
('active_branch_id', models.UUIDField()),
|
|
23
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
24
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
25
|
+
],
|
|
26
|
+
options={
|
|
27
|
+
'ordering': ['-updated_at'],
|
|
28
|
+
},
|
|
29
|
+
),
|
|
30
|
+
migrations.CreateModel(
|
|
31
|
+
name='Project',
|
|
32
|
+
fields=[
|
|
33
|
+
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
34
|
+
('name', models.CharField(max_length=255, unique=True)),
|
|
35
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
36
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
37
|
+
],
|
|
38
|
+
options={
|
|
39
|
+
'ordering': ['name'],
|
|
40
|
+
},
|
|
41
|
+
),
|
|
42
|
+
migrations.CreateModel(
|
|
43
|
+
name='BranchNodeRecord',
|
|
44
|
+
fields=[
|
|
45
|
+
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
46
|
+
('compressed_payload', models.JSONField(blank=True, null=True)),
|
|
47
|
+
('compressed_through', models.PositiveIntegerField()),
|
|
48
|
+
('visible_end', models.PositiveIntegerField(blank=True, null=True)),
|
|
49
|
+
('child_order', models.JSONField(default=list)),
|
|
50
|
+
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children_nodes', to='chat.branchnoderecord')),
|
|
51
|
+
('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='branch_nodes', to='chat.chatsession')),
|
|
52
|
+
],
|
|
53
|
+
options={
|
|
54
|
+
'ordering': ['compressed_through'],
|
|
55
|
+
},
|
|
56
|
+
),
|
|
57
|
+
migrations.AddField(
|
|
58
|
+
model_name='chatsession',
|
|
59
|
+
name='project',
|
|
60
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to='chat.project'),
|
|
61
|
+
),
|
|
62
|
+
migrations.CreateModel(
|
|
63
|
+
name='StoredMessage',
|
|
64
|
+
fields=[
|
|
65
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
66
|
+
('position', models.PositiveIntegerField()),
|
|
67
|
+
('message_type', models.CharField(max_length=32)),
|
|
68
|
+
('payload', models.JSONField()),
|
|
69
|
+
('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='chat.chatsession')),
|
|
70
|
+
],
|
|
71
|
+
options={
|
|
72
|
+
'ordering': ['position'],
|
|
73
|
+
},
|
|
74
|
+
),
|
|
75
|
+
migrations.AddConstraint(
|
|
76
|
+
model_name='chatsession',
|
|
77
|
+
constraint=models.UniqueConstraint(condition=models.Q(('name', ''), _negated=True), fields=('project', 'name'), name='uniq_named_session_per_project'),
|
|
78
|
+
),
|
|
79
|
+
migrations.AddConstraint(
|
|
80
|
+
model_name='storedmessage',
|
|
81
|
+
constraint=models.UniqueConstraint(fields=('session', 'position'), name='uniq_message_position_per_session'),
|
|
82
|
+
),
|
|
83
|
+
]
|
|
File without changes
|
chat/models.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from django.db import models
|
|
4
|
+
from django.db.models import Q
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Project(models.Model):
|
|
8
|
+
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
9
|
+
name = models.CharField(max_length=255, unique=True)
|
|
10
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
11
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
12
|
+
|
|
13
|
+
class Meta:
|
|
14
|
+
ordering = ["name"]
|
|
15
|
+
|
|
16
|
+
def __str__(self) -> str:
|
|
17
|
+
return self.name
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ChatSession(models.Model):
|
|
21
|
+
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
22
|
+
project = models.ForeignKey(
|
|
23
|
+
Project,
|
|
24
|
+
on_delete=models.CASCADE,
|
|
25
|
+
related_name="sessions",
|
|
26
|
+
)
|
|
27
|
+
name = models.CharField(max_length=255, blank=True, default="")
|
|
28
|
+
config = models.JSONField(default=dict)
|
|
29
|
+
active_branch_id = models.UUIDField()
|
|
30
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
31
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
32
|
+
|
|
33
|
+
class Meta:
|
|
34
|
+
ordering = ["-updated_at"]
|
|
35
|
+
constraints = [
|
|
36
|
+
models.UniqueConstraint(
|
|
37
|
+
fields=["project", "name"],
|
|
38
|
+
condition=~Q(name=""),
|
|
39
|
+
name="uniq_named_session_per_project",
|
|
40
|
+
),
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
def __str__(self) -> str:
|
|
44
|
+
label = self.name or str(self.id)
|
|
45
|
+
return f"{self.project.name}:{label}"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class StoredMessage(models.Model):
|
|
49
|
+
session = models.ForeignKey(
|
|
50
|
+
ChatSession,
|
|
51
|
+
on_delete=models.CASCADE,
|
|
52
|
+
related_name="messages",
|
|
53
|
+
)
|
|
54
|
+
position = models.PositiveIntegerField()
|
|
55
|
+
message_type = models.CharField(max_length=32)
|
|
56
|
+
payload = models.JSONField()
|
|
57
|
+
|
|
58
|
+
class Meta:
|
|
59
|
+
ordering = ["position"]
|
|
60
|
+
constraints = [
|
|
61
|
+
models.UniqueConstraint(
|
|
62
|
+
fields=["session", "position"],
|
|
63
|
+
name="uniq_message_position_per_session",
|
|
64
|
+
),
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class BranchNodeRecord(models.Model):
|
|
69
|
+
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
70
|
+
session = models.ForeignKey(
|
|
71
|
+
ChatSession,
|
|
72
|
+
on_delete=models.CASCADE,
|
|
73
|
+
related_name="branch_nodes",
|
|
74
|
+
)
|
|
75
|
+
parent = models.ForeignKey(
|
|
76
|
+
"self",
|
|
77
|
+
on_delete=models.CASCADE,
|
|
78
|
+
null=True,
|
|
79
|
+
blank=True,
|
|
80
|
+
related_name="children_nodes",
|
|
81
|
+
)
|
|
82
|
+
compressed_payload = models.JSONField(null=True, blank=True)
|
|
83
|
+
compressed_through = models.PositiveIntegerField()
|
|
84
|
+
visible_end = models.PositiveIntegerField(null=True, blank=True)
|
|
85
|
+
child_order = models.JSONField(default=list)
|
|
86
|
+
|
|
87
|
+
class Meta:
|
|
88
|
+
ordering = ["compressed_through"]
|
composer/__init__.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Composer — thread-based agents with typed streaming."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
from .agent import (
|
|
6
|
+
Agent,
|
|
7
|
+
MCPClient,
|
|
8
|
+
MCPPromptInfo,
|
|
9
|
+
MCPResourceInfo,
|
|
10
|
+
StreamEvent,
|
|
11
|
+
StreamEventKind,
|
|
12
|
+
StreamEventProcessor,
|
|
13
|
+
ThinkingEvent,
|
|
14
|
+
AssistantEvent,
|
|
15
|
+
ToolCallEvent,
|
|
16
|
+
ToolResultEvent,
|
|
17
|
+
ToolCall,
|
|
18
|
+
ToolResult,
|
|
19
|
+
combine_tools,
|
|
20
|
+
extract_thinking,
|
|
21
|
+
extract_assistant_text,
|
|
22
|
+
)
|
|
23
|
+
from .tools import run_tool_call
|
|
24
|
+
from .vector import Vector
|
|
25
|
+
from .image import ImageAttach
|
|
26
|
+
from .thread import (
|
|
27
|
+
Thread,
|
|
28
|
+
HumanMessage,
|
|
29
|
+
ImageMessage,
|
|
30
|
+
AIMessage,
|
|
31
|
+
SystemMessage,
|
|
32
|
+
ToolMessage,
|
|
33
|
+
CompressedMessage,
|
|
34
|
+
Message,
|
|
35
|
+
EncoderType,
|
|
36
|
+
TokenCalculator,
|
|
37
|
+
)
|
|
38
|
+
from .tool_hide import (
|
|
39
|
+
ToolResultHideRule,
|
|
40
|
+
HideMode,
|
|
41
|
+
get_original_content,
|
|
42
|
+
is_hidden_for_model,
|
|
43
|
+
message_matches_rule,
|
|
44
|
+
resolve_full_tool_name,
|
|
45
|
+
restore_hidden_tool_messages,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
"Agent",
|
|
50
|
+
"Vector",
|
|
51
|
+
"MCPClient",
|
|
52
|
+
"MCPPromptInfo",
|
|
53
|
+
"MCPResourceInfo",
|
|
54
|
+
"Thread",
|
|
55
|
+
"HumanMessage",
|
|
56
|
+
"ImageMessage",
|
|
57
|
+
"ImageAttach",
|
|
58
|
+
"AIMessage",
|
|
59
|
+
"SystemMessage",
|
|
60
|
+
"ToolMessage",
|
|
61
|
+
"CompressedMessage",
|
|
62
|
+
"Message",
|
|
63
|
+
"EncoderType",
|
|
64
|
+
"TokenCalculator",
|
|
65
|
+
"HideMode",
|
|
66
|
+
"ToolResultHideRule",
|
|
67
|
+
"get_original_content",
|
|
68
|
+
"is_hidden_for_model",
|
|
69
|
+
"message_matches_rule",
|
|
70
|
+
"resolve_full_tool_name",
|
|
71
|
+
"restore_hidden_tool_messages",
|
|
72
|
+
"ThinkingEvent",
|
|
73
|
+
"AssistantEvent",
|
|
74
|
+
"ToolCallEvent",
|
|
75
|
+
"ToolResultEvent",
|
|
76
|
+
"StreamEvent",
|
|
77
|
+
"StreamEventKind",
|
|
78
|
+
"StreamEventProcessor",
|
|
79
|
+
"ToolCall",
|
|
80
|
+
"ToolResult",
|
|
81
|
+
"combine_tools",
|
|
82
|
+
"run_tool_call",
|
|
83
|
+
"extract_thinking",
|
|
84
|
+
"extract_assistant_text",
|
|
85
|
+
"ChatProject",
|
|
86
|
+
"ChatSession",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
_LAZY_IMPORTS = {"ChatProject", "ChatSession"}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def __getattr__(name: str):
|
|
93
|
+
if name in _LAZY_IMPORTS:
|
|
94
|
+
from .persistence import ChatProject, ChatSession
|
|
95
|
+
|
|
96
|
+
return {"ChatProject": ChatProject, "ChatSession": ChatSession}[name]
|
|
97
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|