copilotkit-intelligence-runtime 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.
@@ -0,0 +1,142 @@
1
+ """Typed Runtime entitlement responses and strict platform normalization."""
2
+
3
+ import math
4
+ from typing import Any, Literal, NotRequired, TypedDict
5
+
6
+
7
+ class RuntimeEntitlement(TypedDict):
8
+ """The Runtime grant and its platform-defined features and limits."""
9
+
10
+ active: bool
11
+ source: Literal[
12
+ "managedOrgSubscription", "selfHostedDeploymentLicense", "awsMarketplaceDeploymentLicense"
13
+ ]
14
+ features: dict[str, bool]
15
+ limits: dict[str, float]
16
+ planCode: NotRequired[str]
17
+ entitlementSource: NotRequired[str]
18
+
19
+
20
+ class RuntimeEntitlementProblem(TypedDict):
21
+ """A structured reason why the platform cannot supply a ready grant."""
22
+
23
+ code: str
24
+ message: str
25
+ retryable: bool
26
+ requestId: NotRequired[str]
27
+ traceId: NotRequired[str]
28
+
29
+
30
+ class RuntimeEntitlementReady(TypedDict):
31
+ """A resolved grant. An inactive grant does not authorize Runtime access."""
32
+
33
+ status: Literal["ready"]
34
+ entitlement: RuntimeEntitlement
35
+
36
+
37
+ class RuntimeEntitlementUnavailable(TypedDict):
38
+ """A non-ready platform result with retry and correlation details."""
39
+
40
+ status: Literal["degraded", "misconfigured", "unavailable"]
41
+ error: RuntimeEntitlementProblem
42
+
43
+
44
+ RuntimeEntitlementResponse = RuntimeEntitlementReady | RuntimeEntitlementUnavailable
45
+
46
+
47
+ def _finite_number(value: Any) -> bool:
48
+ """Reject booleans and numbers outside the finite JavaScript number range."""
49
+ if type(value) not in (int, float):
50
+ return False
51
+ try:
52
+ return math.isfinite(value)
53
+ except OverflowError:
54
+ return False
55
+
56
+
57
+ def _entitlement(value: Any) -> RuntimeEntitlement | None:
58
+ """Reject malformed or unknown authority fields instead of widening a grant."""
59
+ required = {"active", "source", "features", "limits"}
60
+ if (
61
+ not isinstance(value, dict)
62
+ or not required <= value.keys()
63
+ or value.keys() - required - {"planCode", "entitlementSource"}
64
+ ):
65
+ return None
66
+ if type(value["active"]) is not bool or value["source"] not in (
67
+ "managedOrgSubscription",
68
+ "selfHostedDeploymentLicense",
69
+ "awsMarketplaceDeploymentLicense",
70
+ ):
71
+ return None
72
+ if not isinstance(value["features"], dict) or any(
73
+ not isinstance(key, str) or type(flag) is not bool
74
+ for key, flag in value["features"].items()
75
+ ):
76
+ return None
77
+ if not isinstance(value["limits"], dict) or any(
78
+ not isinstance(key, str) or not _finite_number(limit)
79
+ for key, limit in value["limits"].items()
80
+ ):
81
+ return None
82
+ result: RuntimeEntitlement = {
83
+ "active": value["active"],
84
+ "source": value["source"],
85
+ "features": dict(value["features"]),
86
+ "limits": dict(value["limits"]),
87
+ }
88
+ if "planCode" in value:
89
+ if not isinstance(value["planCode"], str):
90
+ return None
91
+ result["planCode"] = value["planCode"]
92
+ if "entitlementSource" in value:
93
+ if not isinstance(value["entitlementSource"], str):
94
+ return None
95
+ result["entitlementSource"] = value["entitlementSource"]
96
+ return result
97
+
98
+
99
+ def normalize_runtime_entitlements(value: Any) -> RuntimeEntitlementResponse | None:
100
+ """Accept the current strict union or the legacy flat organization response."""
101
+ if not isinstance(value, dict):
102
+ return None
103
+ if value.get("status") == "ready" and value.keys() == {"status", "entitlement"}:
104
+ grant = _entitlement(value["entitlement"])
105
+ return {"status": "ready", "entitlement": grant} if grant is not None else None
106
+ if value.get("status") in ("degraded", "misconfigured", "unavailable") and value.keys() == {
107
+ "status",
108
+ "error",
109
+ }:
110
+ error = value["error"]
111
+ required = {"code", "message", "retryable"}
112
+ if (
113
+ not isinstance(error, dict)
114
+ or not required <= error.keys()
115
+ or error.keys() - required - {"requestId", "traceId"}
116
+ ):
117
+ return None
118
+ if (
119
+ not isinstance(error["code"], str)
120
+ or not isinstance(error["message"], str)
121
+ or type(error["retryable"]) is not bool
122
+ ):
123
+ return None
124
+ problem: RuntimeEntitlementProblem = {
125
+ "code": error["code"],
126
+ "message": error["message"],
127
+ "retryable": error["retryable"],
128
+ }
129
+ if "requestId" in error:
130
+ if not isinstance(error["requestId"], str):
131
+ return None
132
+ problem["requestId"] = error["requestId"]
133
+ if "traceId" in error:
134
+ if not isinstance(error["traceId"], str):
135
+ return None
136
+ problem["traceId"] = error["traceId"]
137
+ return {"status": value["status"], "error": problem}
138
+ if isinstance(value.get("organizationId"), str):
139
+ grant = _entitlement({key: item for key, item in value.items() if key != "organizationId"})
140
+ if grant is not None:
141
+ return {"status": "ready", "entitlement": grant}
142
+ return None
@@ -0,0 +1,182 @@
1
+ """Typed, sanitized Inspector metadata from the Intelligence project."""
2
+
3
+ from typing import Literal, NotRequired, TypedDict
4
+ from urllib.parse import unquote, urlsplit
5
+
6
+ import httpx
7
+
8
+
9
+ class InspectorIdentity(TypedDict):
10
+ """Project and organization display names."""
11
+
12
+ organizationName: str
13
+ projectName: str
14
+
15
+
16
+ class InspectorPlan(TypedDict):
17
+ """The plan identifier and display label."""
18
+
19
+ code: str
20
+ label: str
21
+
22
+
23
+ class InspectorLicense(TypedDict):
24
+ """The displayed license state, not an authorization grant."""
25
+
26
+ state: Literal["valid", "none", "expired", "unknown"]
27
+
28
+
29
+ class InspectorAction(TypedDict):
30
+ """A plan action with a URL that excludes credentials, queries, and fragments."""
31
+
32
+ kind: Literal["manage_plan", "renew", "enable_intelligence"]
33
+ url: str
34
+
35
+
36
+ class InspectorFiniteLimit(TypedDict):
37
+ """A positive, finite usage limit."""
38
+
39
+ kind: Literal["finite"]
40
+ value: int
41
+
42
+
43
+ class InspectorUnlimitedLimit(TypedDict):
44
+ """A plan with no finite usage limit."""
45
+
46
+ kind: Literal["unlimited"]
47
+
48
+
49
+ class InspectorUnknownLimit(TypedDict):
50
+ """A plan whose usage limit is not available."""
51
+
52
+ kind: Literal["unknown"]
53
+
54
+
55
+ InspectorUsageLimit = InspectorFiniteLimit | InspectorUnlimitedLimit | InspectorUnknownLimit
56
+
57
+
58
+ class InspectorUsage(TypedDict):
59
+ """Usage counts and the plan limit."""
60
+
61
+ used: int
62
+ limit: InspectorUsageLimit
63
+ expiringSoonCount: NotRequired[int]
64
+
65
+
66
+ class InspectorMetadata(TypedDict):
67
+ """Version 1 metadata with independent optional display modules."""
68
+
69
+ schemaVersion: Literal[1]
70
+ identity: NotRequired[InspectorIdentity]
71
+ plan: NotRequired[InspectorPlan]
72
+ license: NotRequired[InspectorLicense]
73
+ action: NotRequired[InspectorAction]
74
+ usage: NotRequired[InspectorUsage]
75
+
76
+
77
+ def _text(value: object) -> str | None:
78
+ """Trim the ECMAScript whitespace set used by the TypeScript parser."""
79
+ if not isinstance(value, str):
80
+ return None
81
+ return (
82
+ value.strip(
83
+ "\u0009\u000a\u000b\u000c\u000d\u0020\u00a0\u1680"
84
+ "\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007"
85
+ "\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff"
86
+ )
87
+ or None
88
+ )
89
+
90
+
91
+ def _integer(value: object, minimum: int = 0) -> int | None:
92
+ """Accept only JSON numbers within JavaScript's safe integer range."""
93
+ if type(value) not in (int, float):
94
+ return None
95
+ if (
96
+ isinstance(value, (int, float))
97
+ and minimum <= value <= 9007199254740991
98
+ and value == int(value)
99
+ ):
100
+ return int(value)
101
+ return None
102
+
103
+
104
+ def _action_url(value: object) -> str | None:
105
+ """Permit HTTPS and loopback HTTP links without embedded private parameters."""
106
+ url = _text(value)
107
+ if url is None or "?" in url or "#" in url or "://" not in url:
108
+ return None
109
+ authority = url.split("://", 1)[1].split("/", 1)[0]
110
+ if "@" in authority:
111
+ return None
112
+ try:
113
+ # Browsers treat backslashes as path separators in HTTP(S) URLs.
114
+ candidate = url.replace("\\", "/")
115
+ structural = urlsplit(candidate)
116
+ structural.port # Reject malformed and out-of-range ports.
117
+ parsed = httpx.URL(candidate)
118
+ host = unquote(parsed.host, errors="strict")
119
+ except (httpx.InvalidURL, ValueError, UnicodeError):
120
+ return None
121
+ if (
122
+ not host
123
+ or parsed.userinfo
124
+ or any(character in host for character in "\x00\t\n\r #%/<>?@[\\]^|")
125
+ ):
126
+ return None
127
+ if parsed.scheme == "https" or (
128
+ parsed.scheme == "http" and parsed.host in ("localhost", "127.0.0.1", "::1")
129
+ ):
130
+ return url
131
+ return None
132
+
133
+
134
+ def parse_inspector_metadata(value: object) -> InspectorMetadata | None:
135
+ """Copy supported fields without letting one invalid module hide valid modules."""
136
+ if (
137
+ not isinstance(value, dict)
138
+ or type(value.get("schemaVersion")) not in (int, float)
139
+ or value.get("schemaVersion") != 1
140
+ ):
141
+ return None
142
+ result: InspectorMetadata = {"schemaVersion": 1}
143
+ identity = value.get("identity")
144
+ if isinstance(identity, dict):
145
+ organization = _text(identity.get("organizationName"))
146
+ project = _text(identity.get("projectName"))
147
+ if organization is not None and project is not None:
148
+ result["identity"] = {"organizationName": organization, "projectName": project}
149
+ plan = value.get("plan")
150
+ if isinstance(plan, dict):
151
+ code, label = _text(plan.get("code")), _text(plan.get("label"))
152
+ if code is not None and label is not None:
153
+ result["plan"] = {"code": code, "label": label}
154
+ license = value.get("license")
155
+ if isinstance(license, dict):
156
+ state = license.get("state")
157
+ if state in ("valid", "none", "expired", "unknown"):
158
+ result["license"] = {"state": state}
159
+ action = value.get("action")
160
+ if isinstance(action, dict):
161
+ kind, url = action.get("kind"), _action_url(action.get("url"))
162
+ if kind in ("manage_plan", "renew", "enable_intelligence") and url is not None:
163
+ result["action"] = {"kind": kind, "url": url}
164
+ usage = value.get("usage")
165
+ if isinstance(usage, dict):
166
+ used, limit = _integer(usage.get("used")), usage.get("limit")
167
+ if used is not None and isinstance(limit, dict):
168
+ parsed_limit: InspectorUsageLimit | None = None
169
+ if limit.get("kind") == "finite":
170
+ count = _integer(limit.get("value"), 1)
171
+ if count is not None:
172
+ parsed_limit = {"kind": "finite", "value": count}
173
+ elif limit.get("kind") == "unlimited":
174
+ parsed_limit = {"kind": "unlimited"}
175
+ elif limit.get("kind") == "unknown":
176
+ parsed_limit = {"kind": "unknown"}
177
+ if parsed_limit is not None:
178
+ result["usage"] = {"used": used, "limit": parsed_limit}
179
+ expiring = _integer(usage.get("expiringSoonCount"))
180
+ if expiring is not None:
181
+ result["usage"]["expiringSoonCount"] = expiring
182
+ return result
@@ -0,0 +1,98 @@
1
+ """Safe learned-skill delivery errors and raw snapshot result shapes."""
2
+
3
+ from typing import Literal, TypeAlias, TypedDict, cast
4
+
5
+ LearnedSkillsErrorCode: TypeAlias = Literal[
6
+ "INVALID_CONFIG",
7
+ "AUTHENTICATION_FAILED",
8
+ "AUTHORIZATION_FAILED",
9
+ "ENTITLEMENT_REQUIRED",
10
+ "DELIVERY_DISABLED",
11
+ "CONTAINER_NOT_FOUND",
12
+ "REVISION_NOT_FOUND",
13
+ "REVISION_REVOKED",
14
+ "NETWORK_ERROR",
15
+ "TIMEOUT",
16
+ "INVALID_SNAPSHOT",
17
+ "UNSUPPORTED_SERVER",
18
+ ]
19
+ _MESSAGES: dict[LearnedSkillsErrorCode, str] = {
20
+ "INVALID_CONFIG": "Invalid learned-skills request configuration.",
21
+ "AUTHENTICATION_FAILED": "Learned-skills authentication failed.",
22
+ "AUTHORIZATION_FAILED": "Learned-skills access was denied.",
23
+ "ENTITLEMENT_REQUIRED": "Learned-skills delivery requires an entitlement.",
24
+ "DELIVERY_DISABLED": "Learned-skills delivery is disabled.",
25
+ "CONTAINER_NOT_FOUND": "The learning container was not found.",
26
+ "REVISION_NOT_FOUND": "The learned-skills revision was not found.",
27
+ "REVISION_REVOKED": "The learned-skills revision was revoked.",
28
+ "NETWORK_ERROR": "The learned-skills request failed during transport.",
29
+ "TIMEOUT": "The learned-skills request timed out.",
30
+ "INVALID_SNAPSHOT": "The learned-skills response metadata is invalid.",
31
+ "UNSUPPORTED_SERVER": "The server returned an unsupported learned-skills response.",
32
+ }
33
+ _DENIAL_CODES = frozenset(
34
+ {
35
+ "AUTHENTICATION_FAILED",
36
+ "AUTHORIZATION_FAILED",
37
+ "ENTITLEMENT_REQUIRED",
38
+ "DELIVERY_DISABLED",
39
+ "CONTAINER_NOT_FOUND",
40
+ "REVISION_NOT_FOUND",
41
+ "REVISION_REVOKED",
42
+ }
43
+ )
44
+
45
+
46
+ class LearnedSkillsError(Exception):
47
+ """Stable safe failure; an optional cause is available for explicit diagnostics."""
48
+
49
+ def __init__(
50
+ self, code: LearnedSkillsErrorCode, retryable: bool, cause: BaseException | None = None
51
+ ) -> None:
52
+ self.code = code
53
+ self.message = _MESSAGES[code]
54
+ self.retryable = retryable
55
+ self.cause = cause
56
+ super().__init__(self.message)
57
+
58
+
59
+ class LearnedSkillsSnapshot(TypedDict):
60
+ """Raw ZIP response; archive validation belongs to the framework adapter."""
61
+
62
+ status: Literal["snapshot"]
63
+ bytes: bytes
64
+ revision: str
65
+ etag: str
66
+ contentType: str
67
+
68
+
69
+ class LearnedSkillsUnchanged(TypedDict):
70
+ """Conditional response; the caller owns the previous snapshot."""
71
+
72
+ status: Literal["unchanged"]
73
+ revision: str
74
+ etag: str
75
+
76
+
77
+ LearnedSkillsSnapshotResult: TypeAlias = LearnedSkillsSnapshot | LearnedSkillsUnchanged
78
+
79
+
80
+ def response_error(status: int, body: object) -> LearnedSkillsError:
81
+ """Discard response text and preserve only recognized structured failure fields."""
82
+ if status == 401:
83
+ return LearnedSkillsError("AUTHENTICATION_FAILED", False)
84
+ error = body.get("error") if isinstance(body, dict) else None
85
+ if (
86
+ isinstance(error, dict)
87
+ and isinstance(error.get("code"), str)
88
+ and error["code"] in _MESSAGES
89
+ and isinstance(error.get("message"), str)
90
+ and isinstance(error.get("category"), str)
91
+ and isinstance(error.get("retryable"), bool)
92
+ ):
93
+ code = cast(LearnedSkillsErrorCode, error["code"])
94
+ if status != 403 or code in _DENIAL_CODES:
95
+ return LearnedSkillsError(code, error["retryable"])
96
+ return LearnedSkillsError(
97
+ "AUTHORIZATION_FAILED" if status == 403 else "UNSUPPORTED_SERVER", False
98
+ )
File without changes
@@ -0,0 +1,134 @@
1
+ """Public resource shapes. Results remain dictionaries with their wire field names."""
2
+
3
+ from typing import Literal, NotRequired, TypeAlias, TypedDict
4
+
5
+
6
+ class ThreadSummary(TypedDict):
7
+ """Thread metadata without message history."""
8
+
9
+ id: str
10
+ name: str | None
11
+ lastRunAt: NotRequired[str]
12
+ lastUpdatedAt: NotRequired[str]
13
+ createdAt: NotRequired[str]
14
+ updatedAt: NotRequired[str]
15
+ archived: NotRequired[bool]
16
+ agentId: NotRequired[str]
17
+ createdById: NotRequired[str]
18
+ organizationId: NotRequired[str]
19
+
20
+
21
+ class ListThreadsResponse(TypedDict):
22
+ """A page of threads with its cursor and realtime join credentials."""
23
+
24
+ threads: list[ThreadSummary]
25
+ joinCode: str
26
+ joinToken: NotRequired[str]
27
+ nextCursor: NotRequired[str | None]
28
+
29
+
30
+ class ThreadResolution(TypedDict):
31
+ """A thread and whether this call created it."""
32
+
33
+ thread: ThreadSummary
34
+ created: bool
35
+
36
+
37
+ class ThreadToolCall(TypedDict):
38
+ """A persisted tool call with JSON-encoded arguments."""
39
+
40
+ id: str
41
+ name: str
42
+ args: str
43
+
44
+
45
+ class ThreadMessage(TypedDict):
46
+ """A persisted AG-UI message with optional structured content."""
47
+
48
+ id: str
49
+ role: str
50
+ content: NotRequired[object]
51
+ activityType: NotRequired[str]
52
+ toolCalls: NotRequired[list[ThreadToolCall]]
53
+ toolCallId: NotRequired[str]
54
+
55
+
56
+ class ThreadMessagesResponse(TypedDict):
57
+ """Persisted messages in chronological order."""
58
+
59
+ messages: list[ThreadMessage]
60
+
61
+
62
+ class ThreadInspectEvent(TypedDict):
63
+ """A persisted event. Additional event fields remain in the dictionary."""
64
+
65
+ type: str
66
+
67
+
68
+ class ThreadEventsResponse(TypedDict):
69
+ """Persisted events with decode failures and the event-cap marker."""
70
+
71
+ events: list[ThreadInspectEvent]
72
+ decodeErrorRowIds: list[str]
73
+ truncated: bool
74
+
75
+
76
+ class ThreadNoSnapshot(TypedDict):
77
+ """The thread has no state snapshot."""
78
+
79
+ kind: Literal["no-snapshot"]
80
+
81
+
82
+ class ThreadSnapshotDecodeError(TypedDict):
83
+ """The platform could not decode the stored snapshot."""
84
+
85
+ kind: Literal["snapshot-decode-error"]
86
+
87
+
88
+ class ThreadSnapshot(TypedDict):
89
+ """Folded state and the number of deltas the platform skipped."""
90
+
91
+ kind: Literal["snapshot"]
92
+ state: object
93
+ skippedDeltas: int
94
+
95
+
96
+ ThreadStateResponse: TypeAlias = ThreadNoSnapshot | ThreadSnapshotDecodeError | ThreadSnapshot
97
+
98
+
99
+ class AnnotateResponse(TypedDict):
100
+ """The annotation ID and whether the platform recognized a repeated write."""
101
+
102
+ id: str
103
+ duplicate: bool
104
+
105
+
106
+ class MemorySummary(TypedDict):
107
+ """A stored memory, with an optional relevance score from recall."""
108
+
109
+ id: str
110
+ kind: str
111
+ scope: str
112
+ content: str
113
+ sourceThreadIds: list[str]
114
+ invalidatedAt: str | None
115
+ score: NotRequired[float]
116
+
117
+
118
+ class ListMemoriesResponse(TypedDict):
119
+ """Memories visible to the application user under the supplied grant."""
120
+
121
+ memories: list[MemorySummary]
122
+
123
+
124
+ class RecallMemoriesResponse(TypedDict):
125
+ """Memories that match a recall query, with their relevance scores."""
126
+
127
+ memories: list[MemorySummary]
128
+
129
+
130
+ class SaveMemoryResponse(MemorySummary):
131
+ """The saved memory and optional merge or replacement markers."""
132
+
133
+ absorbed: NotRequired[bool]
134
+ retiredId: NotRequired[str]