risenlab-agentlogs 0.2__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.
- risenlab_agentlogs-0.2/.gitignore +4 -0
- risenlab_agentlogs-0.2/LICENSE +21 -0
- risenlab_agentlogs-0.2/PKG-INFO +59 -0
- risenlab_agentlogs-0.2/README.md +42 -0
- risenlab_agentlogs-0.2/pyproject.toml +31 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/__init__.py +91 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/cast.py +66 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/py.typed +0 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/agent_session.py +50 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/agent_session_log.py +225 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/agent_task.py +60 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/annotation.py +18 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/references.py +45 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/repository.py +55 -0
- risenlab_agentlogs-0.2/src/agentlogs/schema/types/user.py +28 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RISEN Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: risenlab-agentlogs
|
|
3
|
+
Version: 0.2
|
|
4
|
+
Summary: Schema definitions and utilities for the AgentLogs dataset
|
|
5
|
+
Project-URL: Homepage, https://github.com/risenlab/agentlogs
|
|
6
|
+
Project-URL: Documentation, https://github.com/risenlab/agentlogs/tree/main/docs/schema
|
|
7
|
+
Project-URL: Dataset, https://huggingface.co/datasets/risenlab/agentlogs
|
|
8
|
+
Author: RISEN Lab
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agentlogs,copilot,dataset,github,schema
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Typing :: Typed
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# AgentLogs
|
|
19
|
+
|
|
20
|
+
[](https://huggingface.co/datasets/risenlab/agentlogs/tree/v0.2)
|
|
21
|
+
[](https://huggingface.co/datasets/risenlab/agentlogs)
|
|
22
|
+
[](https://github.com/risenlab/agentlogs)
|
|
23
|
+
|
|
24
|
+
TypedDict schema and helpers for the [AgentLogs](https://huggingface.co/datasets/risenlab/agentlogs) dataset. Field-level documentation: [schema reference](https://github.com/risenlab/agentlogs/tree/v0.2/docs/schema).
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install risenlab-agentlogs huggingface_hub pyarrow
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
|
|
37
|
+
import pyarrow.parquet as pq
|
|
38
|
+
from huggingface_hub import snapshot_download
|
|
39
|
+
from agentlogs.schema import AgentSession, assert_dataset_version, cast_record
|
|
40
|
+
|
|
41
|
+
# Full dataset into data/dataset/; existing files are skipped
|
|
42
|
+
dataset_path = Path("data") / "dataset"
|
|
43
|
+
snapshot_download(
|
|
44
|
+
repo_id="risenlab/agentlogs",
|
|
45
|
+
repo_type="dataset",
|
|
46
|
+
revision="v0.2",
|
|
47
|
+
local_dir=dataset_path,
|
|
48
|
+
)
|
|
49
|
+
# Fail if the snapshot tag does not match this package version
|
|
50
|
+
assert_dataset_version(dataset_path)
|
|
51
|
+
|
|
52
|
+
# First session row, typed as AgentSession (nested fields included)
|
|
53
|
+
session_file = next((dataset_path / "agent_sessions").glob("*.parquet"))
|
|
54
|
+
session = cast_record(
|
|
55
|
+
AgentSession,
|
|
56
|
+
pq.read_table(session_file, memory_map=False).slice(0, 1).to_pylist()[0],
|
|
57
|
+
)
|
|
58
|
+
print(session["id"], session["name"])
|
|
59
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# AgentLogs
|
|
2
|
+
|
|
3
|
+
[](https://huggingface.co/datasets/risenlab/agentlogs/tree/v0.2)
|
|
4
|
+
[](https://huggingface.co/datasets/risenlab/agentlogs)
|
|
5
|
+
[](https://github.com/risenlab/agentlogs)
|
|
6
|
+
|
|
7
|
+
TypedDict schema and helpers for the [AgentLogs](https://huggingface.co/datasets/risenlab/agentlogs) dataset. Field-level documentation: [schema reference](https://github.com/risenlab/agentlogs/tree/v0.2/docs/schema).
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install risenlab-agentlogs huggingface_hub pyarrow
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
import pyarrow.parquet as pq
|
|
21
|
+
from huggingface_hub import snapshot_download
|
|
22
|
+
from agentlogs.schema import AgentSession, assert_dataset_version, cast_record
|
|
23
|
+
|
|
24
|
+
# Full dataset into data/dataset/; existing files are skipped
|
|
25
|
+
dataset_path = Path("data") / "dataset"
|
|
26
|
+
snapshot_download(
|
|
27
|
+
repo_id="risenlab/agentlogs",
|
|
28
|
+
repo_type="dataset",
|
|
29
|
+
revision="v0.2",
|
|
30
|
+
local_dir=dataset_path,
|
|
31
|
+
)
|
|
32
|
+
# Fail if the snapshot tag does not match this package version
|
|
33
|
+
assert_dataset_version(dataset_path)
|
|
34
|
+
|
|
35
|
+
# First session row, typed as AgentSession (nested fields included)
|
|
36
|
+
session_file = next((dataset_path / "agent_sessions").glob("*.parquet"))
|
|
37
|
+
session = cast_record(
|
|
38
|
+
AgentSession,
|
|
39
|
+
pq.read_table(session_file, memory_map=False).slice(0, 1).to_pylist()[0],
|
|
40
|
+
)
|
|
41
|
+
print(session["id"], session["name"])
|
|
42
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "risenlab-agentlogs"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "Schema definitions and utilities for the AgentLogs dataset"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
authors = [{ name = "RISEN Lab" }]
|
|
10
|
+
keywords = ["agentlogs", "github", "copilot", "dataset", "schema"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Programming Language :: Python :: 3",
|
|
13
|
+
"Programming Language :: Python :: 3.12",
|
|
14
|
+
"Typing :: Typed",
|
|
15
|
+
]
|
|
16
|
+
dependencies = []
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/risenlab/agentlogs"
|
|
20
|
+
Documentation = "https://github.com/risenlab/agentlogs/tree/main/docs/schema"
|
|
21
|
+
Dataset = "https://huggingface.co/datasets/risenlab/agentlogs"
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["hatchling>=1.27"]
|
|
25
|
+
build-backend = "hatchling.build"
|
|
26
|
+
|
|
27
|
+
[tool.hatch.version]
|
|
28
|
+
path = "src/agentlogs/schema/__init__.py"
|
|
29
|
+
|
|
30
|
+
[tool.hatch.build.targets.wheel]
|
|
31
|
+
packages = ["src/agentlogs"]
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
__version__ = "0.2"
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .types.agent_session import (
|
|
6
|
+
AgentSession,
|
|
7
|
+
AgentSessionUsage,
|
|
8
|
+
AgentSessionEvent,
|
|
9
|
+
)
|
|
10
|
+
from .types.agent_task import (
|
|
11
|
+
AgentArtifactReference,
|
|
12
|
+
AgentTask,
|
|
13
|
+
AgentTaskData,
|
|
14
|
+
CustomAgentReference,
|
|
15
|
+
)
|
|
16
|
+
from .types.repository import (
|
|
17
|
+
Repository,
|
|
18
|
+
RepositoryMetric,
|
|
19
|
+
)
|
|
20
|
+
from .types.user import (
|
|
21
|
+
User,
|
|
22
|
+
)
|
|
23
|
+
from .types.references import (
|
|
24
|
+
AgentSessionReference,
|
|
25
|
+
AgentTaskReference,
|
|
26
|
+
RepositoryReference,
|
|
27
|
+
UserReference,
|
|
28
|
+
AgentReference,
|
|
29
|
+
PullRequestIDReference,
|
|
30
|
+
PullRequestReference,
|
|
31
|
+
BranchReference,
|
|
32
|
+
)
|
|
33
|
+
from .types.agent_session_log import (
|
|
34
|
+
AgentSessionLogEntry,
|
|
35
|
+
AgentSessionLogEntryData,
|
|
36
|
+
)
|
|
37
|
+
from .cast import cast_record
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DatasetVersionError(ValueError):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def assert_version(version: str) -> None:
|
|
45
|
+
version = version.removeprefix("v")
|
|
46
|
+
if version != __version__:
|
|
47
|
+
raise DatasetVersionError(
|
|
48
|
+
f"Dataset version {version} does not match schema {__version__}. "
|
|
49
|
+
f"Install risenlab-agentlogs {version} or snapshot revision v{__version__}."
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def assert_dataset_version(dataset_path: str | Path) -> None:
|
|
54
|
+
assert_version(Path(dataset_path).joinpath("VERSION").read_text().strip())
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
__all__ = [
|
|
58
|
+
"AgentSession",
|
|
59
|
+
"AgentSessionUsage",
|
|
60
|
+
"AgentSessionEvent",
|
|
61
|
+
|
|
62
|
+
"AgentSessionLogEntry",
|
|
63
|
+
"AgentSessionLogEntryData",
|
|
64
|
+
|
|
65
|
+
"AgentArtifactReference",
|
|
66
|
+
"PullRequestReference",
|
|
67
|
+
"BranchReference",
|
|
68
|
+
"AgentTask",
|
|
69
|
+
"AgentTaskData",
|
|
70
|
+
"CustomAgentReference",
|
|
71
|
+
"PullRequestIDReference",
|
|
72
|
+
"PullRequestReference",
|
|
73
|
+
"BranchReference",
|
|
74
|
+
|
|
75
|
+
"Repository",
|
|
76
|
+
"RepositoryMetric",
|
|
77
|
+
|
|
78
|
+
"User",
|
|
79
|
+
|
|
80
|
+
"AgentSessionReference",
|
|
81
|
+
"AgentTaskReference",
|
|
82
|
+
"RepositoryReference",
|
|
83
|
+
"UserReference",
|
|
84
|
+
"AgentReference",
|
|
85
|
+
|
|
86
|
+
"cast_record",
|
|
87
|
+
"DatasetVersionError",
|
|
88
|
+
"assert_dataset_version",
|
|
89
|
+
"assert_version",
|
|
90
|
+
"__version__",
|
|
91
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime as dt
|
|
4
|
+
from typing import Any, Mapping, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from .types.agent_session import AgentSession
|
|
7
|
+
from .types.agent_session_log import AgentSessionLogEntry
|
|
8
|
+
from .types.agent_task import AgentTask
|
|
9
|
+
from .types.repository import Repository
|
|
10
|
+
from .types.user import User
|
|
11
|
+
|
|
12
|
+
T = TypeVar("T", bound=Mapping[str, Any])
|
|
13
|
+
|
|
14
|
+
TABLE_TYPES = frozenset(
|
|
15
|
+
{
|
|
16
|
+
Repository,
|
|
17
|
+
AgentTask,
|
|
18
|
+
AgentSession,
|
|
19
|
+
AgentSessionLogEntry,
|
|
20
|
+
User,
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def cast_record(cls: type[T], row: Mapping[str, Any]) -> T:
|
|
25
|
+
if cls not in TABLE_TYPES:
|
|
26
|
+
raise TypeError("cast_record only supports Repository, AgentTask, AgentSession, AgentSessionLogEntry, and User")
|
|
27
|
+
|
|
28
|
+
record = cast(dict[str, Any], row)
|
|
29
|
+
|
|
30
|
+
if cls is Repository:
|
|
31
|
+
for key in ("created_at", "pushed_at", "updated_at", "last_commit_at"):
|
|
32
|
+
value = record.get(key)
|
|
33
|
+
if isinstance(value, dt.datetime) and value.tzinfo is None:
|
|
34
|
+
record[key] = value.replace(tzinfo=dt.timezone.utc)
|
|
35
|
+
|
|
36
|
+
languages = record.get("languages")
|
|
37
|
+
if isinstance(languages, list):
|
|
38
|
+
if not languages:
|
|
39
|
+
record["languages"] = {}
|
|
40
|
+
elif isinstance(languages[0], dict):
|
|
41
|
+
record["languages"] = {entry["key"]: entry["value"] for entry in languages}
|
|
42
|
+
else:
|
|
43
|
+
record["languages"] = dict(languages)
|
|
44
|
+
|
|
45
|
+
elif cls is AgentTask:
|
|
46
|
+
data = record.get("data")
|
|
47
|
+
if isinstance(data, dict):
|
|
48
|
+
for key in ("created_at", "updated_at", "archived_at"):
|
|
49
|
+
value = data.get(key)
|
|
50
|
+
if isinstance(value, dt.datetime) and value.tzinfo is None:
|
|
51
|
+
data[key] = value.replace(tzinfo=dt.timezone.utc)
|
|
52
|
+
|
|
53
|
+
elif cls is AgentSession:
|
|
54
|
+
for key in ("created_at", "updated_at", "completed_at"):
|
|
55
|
+
value = record.get(key)
|
|
56
|
+
if isinstance(value, dt.datetime) and value.tzinfo is None:
|
|
57
|
+
record[key] = value.replace(tzinfo=dt.timezone.utc)
|
|
58
|
+
|
|
59
|
+
elif cls is AgentSessionLogEntry:
|
|
60
|
+
data = record.get("data")
|
|
61
|
+
if isinstance(data, dict):
|
|
62
|
+
created = data.get("created")
|
|
63
|
+
if isinstance(created, dt.datetime) and created.tzinfo is None:
|
|
64
|
+
data["created"] = created.replace(tzinfo=dt.timezone.utc)
|
|
65
|
+
|
|
66
|
+
return cast(T, record)
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
from typing import Annotated, TypedDict
|
|
3
|
+
|
|
4
|
+
from .annotation import GitHubField, Relation
|
|
5
|
+
from .references import (
|
|
6
|
+
AgentTaskReference,
|
|
7
|
+
BranchReference,
|
|
8
|
+
PullRequestReference,
|
|
9
|
+
UserReference,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
class AgentSessionUsage(TypedDict):
|
|
13
|
+
type: Annotated[str, GitHubField("type")]
|
|
14
|
+
amount: Annotated[float | None, GitHubField("amount")]
|
|
15
|
+
credits: Annotated[float | None, GitHubField("credits")]
|
|
16
|
+
|
|
17
|
+
class AgentSessionEvent(TypedDict):
|
|
18
|
+
type: Annotated[str | None, GitHubField("event_type")]
|
|
19
|
+
url: Annotated[str | None, GitHubField("event_url")]
|
|
20
|
+
ids: Annotated[list[str] | None, GitHubField("event_identifiers")]
|
|
21
|
+
content: Annotated[str | None, GitHubField("event_content")]
|
|
22
|
+
|
|
23
|
+
class AgentSession(TypedDict):
|
|
24
|
+
id: Annotated[str, GitHubField("id")]
|
|
25
|
+
|
|
26
|
+
task: Annotated[AgentTaskReference, Relation()]
|
|
27
|
+
log_found: bool
|
|
28
|
+
|
|
29
|
+
user: Annotated[
|
|
30
|
+
UserReference,
|
|
31
|
+
GitHubField("user", leaves={"id": "id", "login": "login"}),
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
name: Annotated[str, GitHubField("name")]
|
|
35
|
+
model: Annotated[str | None, GitHubField("model")]
|
|
36
|
+
prompt: Annotated[str | None, GitHubField("prompt")]
|
|
37
|
+
state: Annotated[str, GitHubField("state")]
|
|
38
|
+
usage: Annotated[AgentSessionUsage | None, GitHubField("usage")]
|
|
39
|
+
premium_requests: Annotated[float, GitHubField("premium_requests")]
|
|
40
|
+
error: Annotated[str | None, GitHubField("error.message")]
|
|
41
|
+
remote_steerable: Annotated[bool | None, GitHubField("remote_steerable")]
|
|
42
|
+
workflow_run_id: Annotated[int | None, GitHubField("workflow_run_id")]
|
|
43
|
+
|
|
44
|
+
event: AgentSessionEvent
|
|
45
|
+
pull_request: PullRequestReference | None
|
|
46
|
+
branch: BranchReference | None
|
|
47
|
+
|
|
48
|
+
created_at: Annotated[dt.datetime, GitHubField("created_at")]
|
|
49
|
+
updated_at: Annotated[dt.datetime, GitHubField("updated_at")]
|
|
50
|
+
completed_at: Annotated[dt.datetime | None, GitHubField("completed_at")]
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime as dt
|
|
4
|
+
from typing import Annotated, TypedDict
|
|
5
|
+
|
|
6
|
+
from .annotation import GitHubField, Note, Relation
|
|
7
|
+
from .references import AgentSessionReference
|
|
8
|
+
|
|
9
|
+
class AgentSessionLogEntry(TypedDict):
|
|
10
|
+
session: Annotated[AgentSessionReference, Relation()]
|
|
11
|
+
entry_index: int
|
|
12
|
+
|
|
13
|
+
parsed: bool
|
|
14
|
+
raw: Annotated[
|
|
15
|
+
str | None,
|
|
16
|
+
Note("Not set when `parsed` is true"),
|
|
17
|
+
]
|
|
18
|
+
data: Annotated[
|
|
19
|
+
AgentSessionLogEntryData | None,
|
|
20
|
+
GitHubField(""),
|
|
21
|
+
Note("Not set when `parsed` is false. Refer to `raw` instead"),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
class AgentSessionLogEntryData(TypedDict):
|
|
25
|
+
id: Annotated[str | None, GitHubField("id")]
|
|
26
|
+
agentId: Annotated[str | None, GitHubField("agentId")]
|
|
27
|
+
arguments: ToolArguments | None
|
|
28
|
+
callId: Annotated[str | None, GitHubField("callId")]
|
|
29
|
+
choices: list[Choice] | None
|
|
30
|
+
content: list[ContentPart] | None
|
|
31
|
+
copilotBillingMetadata: CopilotBillingMetadata | None
|
|
32
|
+
copilot_info_messages: Annotated[list[CopilotInfoMessage] | None, GitHubField("copilot_info_messages")]
|
|
33
|
+
copilot_model_warning_message: Annotated[str | None, GitHubField("copilot_model_warning_message")]
|
|
34
|
+
copilot_usage: CopilotUsage | None
|
|
35
|
+
copilot_warning_messages: Annotated[list[CopilotWarningMessage] | None, GitHubField("copilot_warning_messages")]
|
|
36
|
+
created: Annotated[dt.datetime | None, GitHubField("created")]
|
|
37
|
+
data: EventData | None
|
|
38
|
+
ephemeral: Annotated[bool | None, GitHubField("ephemeral")]
|
|
39
|
+
error: ErrorInfo | None
|
|
40
|
+
kind: Annotated[str | None, GitHubField("kind")]
|
|
41
|
+
model: Annotated[str | None, GitHubField("model")]
|
|
42
|
+
modelCall_error: Annotated[str | None, GitHubField("modelCall.error")]
|
|
43
|
+
modelCallDurationMs: Annotated[int | None, GitHubField("modelCallDurationMs")]
|
|
44
|
+
object: Annotated[str | None, GitHubField("object")]
|
|
45
|
+
output: Annotated[str | None, GitHubField("output")]
|
|
46
|
+
parentId: Annotated[str | None, GitHubField("parentId")]
|
|
47
|
+
performedBy: Annotated[str | None, GitHubField("performedBy")]
|
|
48
|
+
prompt_filter_results: list[PromptFilterResult] | None
|
|
49
|
+
role: Annotated[str | None, GitHubField("role")]
|
|
50
|
+
source: Annotated[str | None, GitHubField("source")]
|
|
51
|
+
system_fingerprint: Annotated[str | None, GitHubField("system_fingerprint")]
|
|
52
|
+
timestamp: Annotated[str | None, GitHubField("timestamp")]
|
|
53
|
+
toolCallId: Annotated[str | None, GitHubField("toolCallId")]
|
|
54
|
+
toolName: Annotated[str | None, GitHubField("toolName")]
|
|
55
|
+
tool_call_id: Annotated[str | None, GitHubField("tool_call_id")]
|
|
56
|
+
truncateResult: TruncateResult | None
|
|
57
|
+
turn: Annotated[int | None, GitHubField("turn")]
|
|
58
|
+
type: Annotated[str | None, GitHubField("type")]
|
|
59
|
+
usage: Usage | None
|
|
60
|
+
|
|
61
|
+
class ContentFilterCategory(TypedDict):
|
|
62
|
+
filtered: bool
|
|
63
|
+
severity: str
|
|
64
|
+
|
|
65
|
+
class ContentFilterResults(TypedDict):
|
|
66
|
+
hate: ContentFilterCategory | None
|
|
67
|
+
self_harm: ContentFilterCategory | None
|
|
68
|
+
sexual: ContentFilterCategory | None
|
|
69
|
+
violence: ContentFilterCategory | None
|
|
70
|
+
|
|
71
|
+
class PromptFilterResult(TypedDict):
|
|
72
|
+
prompt_index: int
|
|
73
|
+
content_filter_results: ContentFilterResults
|
|
74
|
+
|
|
75
|
+
class IPCitation(TypedDict):
|
|
76
|
+
citation_type: str | None
|
|
77
|
+
ip_type: str
|
|
78
|
+
license: str
|
|
79
|
+
snippet: str
|
|
80
|
+
url: str
|
|
81
|
+
|
|
82
|
+
class IPCitationEntry(TypedDict):
|
|
83
|
+
citations: IPCitation
|
|
84
|
+
end_offset: int
|
|
85
|
+
id: int
|
|
86
|
+
start_offset: int | None
|
|
87
|
+
|
|
88
|
+
class CopilotAnnotations(TypedDict):
|
|
89
|
+
IPCodeCitations: list[IPCitationEntry] | None
|
|
90
|
+
raw: str | None
|
|
91
|
+
|
|
92
|
+
class DeltaToolCall(TypedDict):
|
|
93
|
+
function_name: str | None
|
|
94
|
+
function_arguments: str | None
|
|
95
|
+
custom_name: str | None
|
|
96
|
+
custom_input: str | None
|
|
97
|
+
id: str | None
|
|
98
|
+
index: int | None
|
|
99
|
+
type: str | None
|
|
100
|
+
|
|
101
|
+
class MessageToolCall(TypedDict):
|
|
102
|
+
function_name: str | None
|
|
103
|
+
function_arguments: str | None
|
|
104
|
+
id: str | None
|
|
105
|
+
type: str | None
|
|
106
|
+
|
|
107
|
+
class Delta(TypedDict):
|
|
108
|
+
content: str | None
|
|
109
|
+
copilot_annotations: CopilotAnnotations | None
|
|
110
|
+
encrypted_content: str | None
|
|
111
|
+
padding: str | None
|
|
112
|
+
phase: str | None
|
|
113
|
+
reasoning_opaque: str | None
|
|
114
|
+
reasoning_text: str | None
|
|
115
|
+
role: str | None
|
|
116
|
+
tool_calls: list[DeltaToolCall] | None
|
|
117
|
+
|
|
118
|
+
class Message(TypedDict):
|
|
119
|
+
content: str | None
|
|
120
|
+
role: str | None
|
|
121
|
+
tool_calls: list[MessageToolCall] | None
|
|
122
|
+
|
|
123
|
+
class Choice(TypedDict):
|
|
124
|
+
content_filter_results: ContentFilterResults | None
|
|
125
|
+
delta: Delta
|
|
126
|
+
finish_reason: str | None
|
|
127
|
+
index: int | None
|
|
128
|
+
message: Message | None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ToolArguments(TypedDict):
|
|
132
|
+
canOfferSessionApproval: bool | None
|
|
133
|
+
command: str | None
|
|
134
|
+
description: str | None
|
|
135
|
+
diff: str | None
|
|
136
|
+
filePath: str | None
|
|
137
|
+
kind: str | None
|
|
138
|
+
toolName: str | None
|
|
139
|
+
|
|
140
|
+
class ContentPart(TypedDict):
|
|
141
|
+
type: str
|
|
142
|
+
text: str | None
|
|
143
|
+
image_url: str | None
|
|
144
|
+
|
|
145
|
+
class CopilotBillingMetadata(TypedDict):
|
|
146
|
+
billable: bool
|
|
147
|
+
|
|
148
|
+
class CopilotInfoMessage(TypedDict):
|
|
149
|
+
code: Annotated[str, GitHubField("code")]
|
|
150
|
+
message: Annotated[str, GitHubField("message")]
|
|
151
|
+
|
|
152
|
+
class CopilotWarningMessage(TypedDict):
|
|
153
|
+
code: Annotated[str, GitHubField("code")]
|
|
154
|
+
message: Annotated[str, GitHubField("message")]
|
|
155
|
+
|
|
156
|
+
class TokenDetail(TypedDict):
|
|
157
|
+
batch_size: int
|
|
158
|
+
cost_per_batch: int
|
|
159
|
+
token_count: int
|
|
160
|
+
token_type: str
|
|
161
|
+
|
|
162
|
+
class CopilotUsage(TypedDict):
|
|
163
|
+
token_details: list[TokenDetail]
|
|
164
|
+
total_nano_aiu: int
|
|
165
|
+
|
|
166
|
+
class EventData(TypedDict):
|
|
167
|
+
actions: list[str] | None
|
|
168
|
+
alreadyInUse: bool | None
|
|
169
|
+
approved: bool | None
|
|
170
|
+
autoApproveEdits: bool | None
|
|
171
|
+
eventCount: int | None
|
|
172
|
+
eventsFileSizeBytes: int | None
|
|
173
|
+
feedback: str | None
|
|
174
|
+
intent: str | None
|
|
175
|
+
newMode: str | None
|
|
176
|
+
planContent: str | None
|
|
177
|
+
previousMode: str | None
|
|
178
|
+
reason: str | None
|
|
179
|
+
reasoningEffort: str | None
|
|
180
|
+
recommendedAction: str | None
|
|
181
|
+
remoteSteerable: bool | None
|
|
182
|
+
requestId: str | None
|
|
183
|
+
selectedAction: str | None
|
|
184
|
+
selectedModel: str | None
|
|
185
|
+
summary: str | None
|
|
186
|
+
toolCallId: str | None
|
|
187
|
+
turnId: str | None
|
|
188
|
+
|
|
189
|
+
class ErrorInfo(TypedDict):
|
|
190
|
+
code: str
|
|
191
|
+
message: str
|
|
192
|
+
|
|
193
|
+
class CompletionTokensDetails(TypedDict):
|
|
194
|
+
accepted_prediction_tokens: int | None
|
|
195
|
+
reasoning_tokens: int | None
|
|
196
|
+
rejected_prediction_tokens: int | None
|
|
197
|
+
|
|
198
|
+
class PromptTokensDetails(TypedDict):
|
|
199
|
+
cache_creation_tokens: int | None
|
|
200
|
+
cached_tokens: int
|
|
201
|
+
input_tokens: int | None
|
|
202
|
+
output_tokens: int | None
|
|
203
|
+
|
|
204
|
+
class UsageCopilotUsage(TypedDict):
|
|
205
|
+
token_details: list[TokenDetail]
|
|
206
|
+
total_nano_aiu: int
|
|
207
|
+
|
|
208
|
+
class Usage(TypedDict):
|
|
209
|
+
completion_tokens: int
|
|
210
|
+
completion_tokens_details: CompletionTokensDetails | None
|
|
211
|
+
copilot_usage: UsageCopilotUsage | None
|
|
212
|
+
prompt_tokens: int
|
|
213
|
+
prompt_tokens_details: PromptTokensDetails | None
|
|
214
|
+
reasoning_tokens: int | None
|
|
215
|
+
time_in_ms: int | None
|
|
216
|
+
total_tokens: int
|
|
217
|
+
|
|
218
|
+
class TruncateResult(TypedDict):
|
|
219
|
+
messagesRemovedDuringTruncation: int
|
|
220
|
+
postTruncationMessagesLength: int
|
|
221
|
+
postTruncationTokensInMessages: int
|
|
222
|
+
preTruncationMessagesLength: int
|
|
223
|
+
preTruncationTokensInMessages: int
|
|
224
|
+
tokenLimit: int
|
|
225
|
+
tokensRemovedDuringTruncation: int
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
from typing import Annotated, TypedDict
|
|
3
|
+
|
|
4
|
+
from .annotation import GitHubField, Note, Relation
|
|
5
|
+
from .references import (
|
|
6
|
+
AgentReference,
|
|
7
|
+
AgentSessionReference,
|
|
8
|
+
BranchReference,
|
|
9
|
+
PullRequestIDReference,
|
|
10
|
+
RepositoryReference,
|
|
11
|
+
UserReference,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
class CustomAgentReference(TypedDict):
|
|
15
|
+
id: Annotated[str | None, GitHubField("id")]
|
|
16
|
+
name: Annotated[str | None, GitHubField("name")]
|
|
17
|
+
is_automation: Annotated[bool | None, GitHubField("is_automation")]
|
|
18
|
+
|
|
19
|
+
class AgentArtifactReference(TypedDict):
|
|
20
|
+
type: str
|
|
21
|
+
pull_request: Annotated[PullRequestIDReference | None, GitHubField("data")]
|
|
22
|
+
branch: Annotated[BranchReference | None, GitHubField("data")]
|
|
23
|
+
|
|
24
|
+
class AgentTaskData(TypedDict):
|
|
25
|
+
name: Annotated[str | None, GitHubField("name")]
|
|
26
|
+
state: Annotated[str, GitHubField("state")]
|
|
27
|
+
archived: bool
|
|
28
|
+
remote_steerable: Annotated[bool, GitHubField("remote_steerable")]
|
|
29
|
+
sharing_status: Annotated[str, GitHubField("sharing_status")]
|
|
30
|
+
|
|
31
|
+
created_at: Annotated[dt.datetime, GitHubField("created_at")]
|
|
32
|
+
updated_at: Annotated[dt.datetime, GitHubField("updated_at")]
|
|
33
|
+
archived_at: Annotated[dt.datetime | None, GitHubField("archived_at")]
|
|
34
|
+
|
|
35
|
+
custom_agent: Annotated[CustomAgentReference | None, GitHubField("custom_agent")]
|
|
36
|
+
agent_collaborators: Annotated[list[AgentReference], GitHubField("agent_collaborators[]")]
|
|
37
|
+
artifacts: Annotated[list[AgentArtifactReference], GitHubField("artifacts[]")]
|
|
38
|
+
|
|
39
|
+
class AgentTask(TypedDict):
|
|
40
|
+
id: Annotated[str, GitHubField("id")]
|
|
41
|
+
|
|
42
|
+
repository: Annotated[RepositoryReference, Relation()]
|
|
43
|
+
sessions: Annotated[list[AgentSessionReference], GitHubField("sessions[]")]
|
|
44
|
+
|
|
45
|
+
creator: Annotated[
|
|
46
|
+
UserReference | None,
|
|
47
|
+
GitHubField("creator", leaves={"id": "id", "login": "login"}),
|
|
48
|
+
Note("Not set when `found` is false"),
|
|
49
|
+
]
|
|
50
|
+
collaborators: Annotated[
|
|
51
|
+
list[UserReference] | None,
|
|
52
|
+
GitHubField("user_collaborators[]", leaves={"id": ""}),
|
|
53
|
+
Note("Not set when `found` is false"),
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
found: bool
|
|
57
|
+
data: Annotated[
|
|
58
|
+
AgentTaskData | None,
|
|
59
|
+
Note("Not set when `found` is false"),
|
|
60
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
@dataclass(frozen=True)
|
|
4
|
+
class Description:
|
|
5
|
+
text: str
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True)
|
|
8
|
+
class Note:
|
|
9
|
+
text: str
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class Relation:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class GitHubField:
|
|
17
|
+
field: str
|
|
18
|
+
leaves: dict[str, str] | None = None
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import Annotated, TypedDict
|
|
2
|
+
|
|
3
|
+
from .annotation import GitHubField
|
|
4
|
+
|
|
5
|
+
class AgentSessionReference(TypedDict):
|
|
6
|
+
id: Annotated[str, GitHubField("id")]
|
|
7
|
+
|
|
8
|
+
class AgentTaskReference(TypedDict):
|
|
9
|
+
id: Annotated[str, GitHubField("id")]
|
|
10
|
+
|
|
11
|
+
class RepositoryReference(TypedDict):
|
|
12
|
+
full_name: str
|
|
13
|
+
|
|
14
|
+
class UserReference(TypedDict):
|
|
15
|
+
id: Annotated[int, GitHubField("id")]
|
|
16
|
+
login: Annotated[str | None, GitHubField("login")]
|
|
17
|
+
|
|
18
|
+
class AgentReference(TypedDict):
|
|
19
|
+
id: Annotated[int, GitHubField("agent_id")]
|
|
20
|
+
|
|
21
|
+
# "copilot-developer" | "copilot-developer-cli" | "copilot-pr-reviews" | "vscode-chat"
|
|
22
|
+
slug: Annotated[str, GitHubField("slug")]
|
|
23
|
+
|
|
24
|
+
# Seems to be combination of the following three IDs:
|
|
25
|
+
# - Owner ID (internal, not queryable)
|
|
26
|
+
# - Repository ID (internal, not queryable)
|
|
27
|
+
# - PR GraphQL ID (queryable) / some uuid (not clear what resource)
|
|
28
|
+
task_id: Annotated[str | None, GitHubField("agent_task_id")]
|
|
29
|
+
|
|
30
|
+
# "Integration" | "UserToServerToken" | "OauthApplication" | "IntegrationInstallation" | None
|
|
31
|
+
type: Annotated[str | None, GitHubField("agent_type")]
|
|
32
|
+
|
|
33
|
+
class PullRequestIDReference(TypedDict):
|
|
34
|
+
id: Annotated[int | None, GitHubField("id")]
|
|
35
|
+
global_id: Annotated[str | None, GitHubField("global_id")]
|
|
36
|
+
|
|
37
|
+
class PullRequestReference(TypedDict):
|
|
38
|
+
id: Annotated[int | None, GitHubField("resource_id")]
|
|
39
|
+
global_id: Annotated[str | None, GitHubField("resource_global_id")]
|
|
40
|
+
number: Annotated[int | None, GitHubField("resource_number")]
|
|
41
|
+
state: Annotated[str | None, GitHubField("resource_state")]
|
|
42
|
+
|
|
43
|
+
class BranchReference(TypedDict):
|
|
44
|
+
base_ref: Annotated[str, GitHubField("base_ref")]
|
|
45
|
+
head_ref: Annotated[str | None, GitHubField("head_ref")]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
from typing import Annotated, TypedDict
|
|
3
|
+
|
|
4
|
+
from .annotation import GitHubField, Relation
|
|
5
|
+
from .references import AgentTaskReference
|
|
6
|
+
|
|
7
|
+
class RepositoryMetric(TypedDict):
|
|
8
|
+
language: str
|
|
9
|
+
blank_lines: int
|
|
10
|
+
code_lines: int
|
|
11
|
+
comment_lines: int
|
|
12
|
+
|
|
13
|
+
class Repository(TypedDict):
|
|
14
|
+
full_name: str
|
|
15
|
+
|
|
16
|
+
agent_tasks: Annotated[list[AgentTaskReference], GitHubField("tasks[]")]
|
|
17
|
+
|
|
18
|
+
archived: Annotated[bool, GitHubField("isArchived")]
|
|
19
|
+
disabled: Annotated[bool, GitHubField("isDisabled")]
|
|
20
|
+
locked: Annotated[bool, GitHubField("isLocked")]
|
|
21
|
+
fork: Annotated[bool, GitHubField("isFork")]
|
|
22
|
+
|
|
23
|
+
homepage: Annotated[str | None, GitHubField("homepageUrl")]
|
|
24
|
+
has_wiki: Annotated[bool, GitHubField("hasWikiEnabled")]
|
|
25
|
+
license: Annotated[str | None, GitHubField("licenseInfo.name")]
|
|
26
|
+
main_language: str
|
|
27
|
+
default_branch: Annotated[str | None, GitHubField("defaultBranchRef.name")]
|
|
28
|
+
size: Annotated[int, GitHubField("diskUsage")]
|
|
29
|
+
|
|
30
|
+
created_at: Annotated[dt.datetime, GitHubField("created_at")]
|
|
31
|
+
pushed_at: Annotated[dt.datetime, GitHubField("pushed_at")]
|
|
32
|
+
updated_at: Annotated[dt.datetime, GitHubField("updated_at")]
|
|
33
|
+
last_commit_at: Annotated[dt.datetime | None, GitHubField("defaultBranchRef.target.committedDate")]
|
|
34
|
+
last_commit_SHA: Annotated[str | None, GitHubField("defaultBranchRef.target.oid")]
|
|
35
|
+
|
|
36
|
+
forks_count: Annotated[int, GitHubField("forkCount")]
|
|
37
|
+
stargazers_count: Annotated[int, GitHubField("stargazers.totalCount")]
|
|
38
|
+
watchers_count: Annotated[int | None, GitHubField("watchers.totalCount")]
|
|
39
|
+
commits_count: Annotated[int | None, GitHubField("defaultBranchRef.target.history.totalCount")]
|
|
40
|
+
branches_count: Annotated[int | None, GitHubField("refs.totalCount")]
|
|
41
|
+
releases_count: Annotated[int | None, GitHubField("releases.totalCount")]
|
|
42
|
+
contributors_count: int | None
|
|
43
|
+
total_issues_count: Annotated[int | None, GitHubField("issues.totalCount")]
|
|
44
|
+
open_issues_count: Annotated[int | None, GitHubField("issues(states: OPEN).totalCount")]
|
|
45
|
+
total_pull_requests_count: Annotated[int | None, GitHubField("pullRequests.totalCount")]
|
|
46
|
+
open_pull_requests_count: Annotated[int | None, GitHubField("pullRequests(states: OPEN).totalCount")]
|
|
47
|
+
|
|
48
|
+
labels: Annotated[list[str], GitHubField("labels.nodes[].name")]
|
|
49
|
+
topics: Annotated[list[str], GitHubField("repositoryTopics.nodes[].topic.name")]
|
|
50
|
+
languages: Annotated[dict[str, int], GitHubField("languages")]
|
|
51
|
+
|
|
52
|
+
blank_lines: int | None
|
|
53
|
+
code_lines: int | None
|
|
54
|
+
comment_lines: int | None
|
|
55
|
+
metrics: list[RepositoryMetric]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from typing import Annotated, TypedDict
|
|
2
|
+
|
|
3
|
+
from .annotation import Note, Relation
|
|
4
|
+
from .references import AgentSessionReference, AgentTaskReference
|
|
5
|
+
|
|
6
|
+
class User(TypedDict):
|
|
7
|
+
"""
|
|
8
|
+
A GitHub user or organization
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
id: int
|
|
12
|
+
found: bool
|
|
13
|
+
found_using: Annotated[
|
|
14
|
+
str | None,
|
|
15
|
+
Note("`'id' | 'login'`. Not set when `found` is false"),
|
|
16
|
+
]
|
|
17
|
+
login: Annotated[
|
|
18
|
+
str | None,
|
|
19
|
+
Note("Not set when `found` is false"),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
created_tasks: Annotated[list[AgentTaskReference], Relation()]
|
|
23
|
+
collaborated_tasks: Annotated[
|
|
24
|
+
list[AgentTaskReference],
|
|
25
|
+
Relation(),
|
|
26
|
+
Note("Taken from GitHub's API and may not be complete. Use together with created_tasks and sessions."),
|
|
27
|
+
]
|
|
28
|
+
sessions: Annotated[list[AgentSessionReference], Relation()]
|