sonf 0.1.0__tar.gz

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.
sonf-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.3
2
+ Name: sonf
3
+ Version: 0.1.0
4
+ Summary: Python SDK primitives for Sonf, work management for AI agents.
5
+ Author: Syeda Nawal Fatima
6
+ Author-email: Syeda Nawal Fatima <177872742+nawal-syeda@users.noreply.github.com>
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+
10
+ # Sonf
11
+
12
+ **Work management for AI agents.**
13
+
14
+ Sonf is an agent-native platform for monitoring, coordinating, and supervising AI agents.
15
+
16
+ The project is currently under active development.
17
+
18
+ ## License
19
+
20
+ No open-source license is granted at this time.
21
+
22
+ Copyright © 2026 Wishlabs AI. All rights reserved.
23
+
24
+ Unauthorized copying, redistribution, modification, publication, or commercial use of this source code is prohibited without prior written permission.
sonf-0.1.0/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # Sonf
2
+
3
+ **Work management for AI agents.**
4
+
5
+ Sonf is an agent-native platform for monitoring, coordinating, and supervising AI agents.
6
+
7
+ The project is currently under active development.
8
+
9
+ ## License
10
+
11
+ No open-source license is granted at this time.
12
+
13
+ Copyright © 2026 Wishlabs AI. All rights reserved.
14
+
15
+ Unauthorized copying, redistribution, modification, publication, or commercial use of this source code is prohibited without prior written permission.
@@ -0,0 +1,23 @@
1
+ [project]
2
+ name = "sonf"
3
+ version = "0.1.0"
4
+ description = "Python SDK primitives for Sonf, work management for AI agents."
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Syeda Nawal Fatima", email = "177872742+nawal-syeda@users.noreply.github.com" }
8
+ ]
9
+ requires-python = ">=3.10"
10
+ dependencies = []
11
+
12
+
13
+ [build-system]
14
+ requires = ["uv_build>=0.11.12,<0.12.0"]
15
+ build-backend = "uv_build"
16
+ [tool.uv.build-backend]
17
+ module-name = "sonf"
18
+
19
+ [dependency-groups]
20
+ dev = [
21
+ "pytest>=9.1.1",
22
+ "ruff>=0.16.9",
23
+ ]
@@ -0,0 +1,10 @@
1
+ # src/sonf/__init__.py
2
+
3
+ from sonf.events import EventType, SonfEvent
4
+
5
+ __version__ = "0.0.1"
6
+
7
+ __all__ = [
8
+ "EventType",
9
+ "SonfEvent",
10
+ ]
@@ -0,0 +1,100 @@
1
+ # src/sonf/events.py
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from dataclasses import dataclass, field
7
+ from datetime import UTC, datetime
8
+ from enum import Enum
9
+ from typing import Any
10
+ from uuid import UUID, uuid4
11
+
12
+
13
+ class EventType(str, Enum):
14
+ """Events that an agent can report to Sonf."""
15
+
16
+ TASK_STARTED = "task_started"
17
+ TASK_PROGRESS = "task_progress"
18
+ TASK_COMPLETED = "task_completed"
19
+ TASK_FAILED = "task_failed"
20
+ TASK_CANCELLED = "task_cancelled"
21
+
22
+ MESSAGE_SENT = "message_sent"
23
+
24
+ TOOL_STARTED = "tool_started"
25
+ TOOL_COMPLETED = "tool_completed"
26
+ TOOL_FAILED = "tool_failed"
27
+
28
+ APPROVAL_REQUESTED = "approval_requested"
29
+ APPROVAL_RESOLVED = "approval_resolved"
30
+
31
+
32
+ @dataclass(frozen=True, slots=True)
33
+ class SonfEvent:
34
+ """A single event emitted by an agent or agent runtime."""
35
+
36
+ agent_id: str
37
+ event_type: EventType
38
+
39
+ task_id: str | None = None
40
+ run_id: str | None = None
41
+
42
+ payload: dict[str, Any] = field(default_factory=dict)
43
+
44
+ event_id: UUID = field(default_factory=uuid4)
45
+
46
+ occurred_at: datetime = field(
47
+ default_factory=lambda: datetime.now(UTC)
48
+ )
49
+
50
+ schema_version: int = field(default=1, init=False)
51
+
52
+ def __post_init__(self) -> None:
53
+ self._validate_identifier("agent_id", self.agent_id)
54
+
55
+ if self.task_id is not None:
56
+ self._validate_identifier("task_id", self.task_id)
57
+
58
+ if self.run_id is not None:
59
+ self._validate_identifier("run_id", self.run_id)
60
+
61
+ if (
62
+ self.occurred_at.tzinfo is None
63
+ or self.occurred_at.utcoffset() is None
64
+ ):
65
+ raise ValueError("occurred_at must be timezone-aware")
66
+
67
+ try:
68
+ json.dumps(self.payload)
69
+ except (TypeError, ValueError) as exc:
70
+ raise ValueError(
71
+ "payload must contain only JSON-serializable values"
72
+ ) from exc
73
+
74
+ @staticmethod
75
+ def _validate_identifier(name: str, value: str) -> None:
76
+ if not isinstance(value, str) or not value.strip():
77
+ raise ValueError(f"{name} must be a non-empty string")
78
+
79
+ def to_dict(self) -> dict[str, Any]:
80
+ """Return a JSON-serializable representation of the event."""
81
+
82
+ return {
83
+ "schema_version": self.schema_version,
84
+ "event_id": str(self.event_id),
85
+ "event_type": self.event_type.value,
86
+ "agent_id": self.agent_id,
87
+ "task_id": self.task_id,
88
+ "run_id": self.run_id,
89
+ "occurred_at": self.occurred_at.isoformat(),
90
+ "payload": self.payload,
91
+ }
92
+
93
+ def to_json(self) -> str:
94
+ """Serialize the event to JSON."""
95
+
96
+ return json.dumps(
97
+ self.to_dict(),
98
+ ensure_ascii=False,
99
+ separators=(",", ":"),
100
+ )
File without changes