agent-runtime-core 0.8.0__py3-none-any.whl → 0.9.1__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,250 @@
1
+ """
2
+ Privacy and user isolation abstractions for agent_runtime_core.
3
+
4
+ This module provides framework-agnostic definitions for:
5
+
6
+ 1. **PrivacyConfig** - Settings that control what data is persisted and when.
7
+ Defaults to maximum privacy (auth required for all persistent data).
8
+
9
+ 2. **UserContext** - Represents the current user (authenticated or anonymous).
10
+ Used to scope data access and enforce privacy rules.
11
+
12
+ 3. **MemoryScope** - Defines how memory is scoped (conversation, user, system).
13
+
14
+ These abstractions are designed to be implemented by framework-specific code
15
+ (e.g., django_agent_runtime) while providing consistent privacy guarantees.
16
+
17
+ Example:
18
+ from agent_runtime_core.privacy import PrivacyConfig, UserContext, MemoryScope
19
+
20
+ # Maximum privacy (default)
21
+ config = PrivacyConfig()
22
+ assert config.require_auth_for_memory == True
23
+ assert config.require_auth_for_conversations == True
24
+
25
+ # Authenticated user
26
+ user = UserContext(
27
+ user_id="user-123",
28
+ is_authenticated=True,
29
+ )
30
+
31
+ # Anonymous user (no persistent data allowed by default)
32
+ anon = UserContext.anonymous()
33
+ assert anon.is_authenticated == False
34
+ """
35
+
36
+ from dataclasses import dataclass, field
37
+ from enum import Enum
38
+ from typing import Any, Optional
39
+
40
+
41
+ class MemoryScope(str, Enum):
42
+ """
43
+ Defines how memory is scoped.
44
+
45
+ CONVERSATION: Memory is scoped to a single conversation.
46
+ Lost when conversation ends. Safest option.
47
+
48
+ USER: Memory persists across conversations for a user.
49
+ Requires authentication. Good for preferences, learned facts.
50
+
51
+ SYSTEM: Memory is shared across all agents in a system for a user.
52
+ Requires authentication. Good for cross-agent knowledge sharing.
53
+ """
54
+ CONVERSATION = "conversation"
55
+ USER = "user"
56
+ SYSTEM = "system"
57
+
58
+
59
+ @dataclass
60
+ class PrivacyConfig:
61
+ """
62
+ Configuration for privacy and data persistence.
63
+
64
+ All settings default to maximum privacy (auth required for everything).
65
+ Framework implementations should respect these settings.
66
+
67
+ Attributes:
68
+ require_auth_for_memory: If True, memory is only stored for authenticated users.
69
+ Anonymous users get no persistent memory. Default: True.
70
+
71
+ require_auth_for_conversations: If True, conversations are only persisted for
72
+ authenticated users. Anonymous conversations
73
+ are ephemeral. Default: True.
74
+
75
+ require_auth_for_tool_tracking: If True, tool calls are only logged for
76
+ authenticated users. Default: True.
77
+
78
+ default_memory_scope: Default scope for new memories. Default: CONVERSATION.
79
+
80
+ allow_cross_agent_memory: If True, agents in a system can share memories
81
+ about a user. Requires SYSTEM scope. Default: True.
82
+
83
+ memory_retention_days: How long to retain user memories. None = forever.
84
+ Default: None.
85
+
86
+ conversation_retention_days: How long to retain conversations. None = forever.
87
+ Default: None.
88
+
89
+ metadata: Additional configuration metadata.
90
+
91
+ Example:
92
+ # Maximum privacy (default)
93
+ config = PrivacyConfig()
94
+
95
+ # Allow anonymous conversations but not memory
96
+ config = PrivacyConfig(
97
+ require_auth_for_conversations=False,
98
+ require_auth_for_memory=True,
99
+ )
100
+
101
+ # Strict retention policy
102
+ config = PrivacyConfig(
103
+ memory_retention_days=30,
104
+ conversation_retention_days=90,
105
+ )
106
+ """
107
+ require_auth_for_memory: bool = True
108
+ require_auth_for_conversations: bool = True
109
+ require_auth_for_tool_tracking: bool = True
110
+ default_memory_scope: MemoryScope = MemoryScope.CONVERSATION
111
+ allow_cross_agent_memory: bool = True
112
+ memory_retention_days: Optional[int] = None
113
+ conversation_retention_days: Optional[int] = None
114
+ metadata: dict = field(default_factory=dict)
115
+
116
+ def allows_memory(self, user: "UserContext") -> bool:
117
+ """Check if memory storage is allowed for this user."""
118
+ if self.require_auth_for_memory:
119
+ return user.is_authenticated
120
+ return True
121
+
122
+ def allows_conversation_persistence(self, user: "UserContext") -> bool:
123
+ """Check if conversation persistence is allowed for this user."""
124
+ if self.require_auth_for_conversations:
125
+ return user.is_authenticated
126
+ return True
127
+
128
+ def allows_tool_tracking(self, user: "UserContext") -> bool:
129
+ """Check if tool call tracking is allowed for this user."""
130
+ if self.require_auth_for_tool_tracking:
131
+ return user.is_authenticated
132
+ return True
133
+
134
+ def to_dict(self) -> dict:
135
+ """Serialize to dictionary."""
136
+ return {
137
+ "require_auth_for_memory": self.require_auth_for_memory,
138
+ "require_auth_for_conversations": self.require_auth_for_conversations,
139
+ "require_auth_for_tool_tracking": self.require_auth_for_tool_tracking,
140
+ "default_memory_scope": self.default_memory_scope.value,
141
+ "allow_cross_agent_memory": self.allow_cross_agent_memory,
142
+ "memory_retention_days": self.memory_retention_days,
143
+ "conversation_retention_days": self.conversation_retention_days,
144
+ "metadata": self.metadata,
145
+ }
146
+
147
+ @classmethod
148
+ def from_dict(cls, data: dict) -> "PrivacyConfig":
149
+ """Deserialize from dictionary."""
150
+ return cls(
151
+ require_auth_for_memory=data.get("require_auth_for_memory", True),
152
+ require_auth_for_conversations=data.get("require_auth_for_conversations", True),
153
+ require_auth_for_tool_tracking=data.get("require_auth_for_tool_tracking", True),
154
+ default_memory_scope=MemoryScope(data.get("default_memory_scope", "conversation")),
155
+ allow_cross_agent_memory=data.get("allow_cross_agent_memory", True),
156
+ memory_retention_days=data.get("memory_retention_days"),
157
+ conversation_retention_days=data.get("conversation_retention_days"),
158
+ metadata=data.get("metadata", {}),
159
+ )
160
+
161
+
162
+ @dataclass
163
+ class UserContext:
164
+ """
165
+ Represents the current user for privacy and data isolation.
166
+
167
+ This is a framework-agnostic representation of a user. Framework
168
+ implementations (e.g., Django) should create UserContext from their
169
+ native user objects.
170
+
171
+ Attributes:
172
+ user_id: Unique identifier for the user. None for anonymous users.
173
+ is_authenticated: Whether the user is authenticated.
174
+ username: Optional username for display purposes.
175
+ email: Optional email address.
176
+ metadata: Additional user metadata (roles, permissions, etc.)
177
+
178
+ Example:
179
+ # From Django user
180
+ user_ctx = UserContext(
181
+ user_id=str(request.user.id),
182
+ is_authenticated=request.user.is_authenticated,
183
+ username=request.user.username,
184
+ email=request.user.email,
185
+ )
186
+
187
+ # Anonymous user
188
+ user_ctx = UserContext.anonymous()
189
+
190
+ # Check permissions
191
+ if privacy_config.allows_memory(user_ctx):
192
+ store.save_memory(...)
193
+ """
194
+ user_id: Optional[str] = None
195
+ is_authenticated: bool = False
196
+ username: Optional[str] = None
197
+ email: Optional[str] = None
198
+ metadata: dict = field(default_factory=dict)
199
+
200
+ @classmethod
201
+ def anonymous(cls) -> "UserContext":
202
+ """Create an anonymous user context."""
203
+ return cls(
204
+ user_id=None,
205
+ is_authenticated=False,
206
+ username=None,
207
+ email=None,
208
+ metadata={"anonymous": True},
209
+ )
210
+
211
+ @classmethod
212
+ def from_user_id(cls, user_id: str, **kwargs) -> "UserContext":
213
+ """Create an authenticated user context from a user ID."""
214
+ return cls(
215
+ user_id=user_id,
216
+ is_authenticated=True,
217
+ **kwargs,
218
+ )
219
+
220
+ def to_dict(self) -> dict:
221
+ """Serialize to dictionary."""
222
+ return {
223
+ "user_id": self.user_id,
224
+ "is_authenticated": self.is_authenticated,
225
+ "username": self.username,
226
+ "email": self.email,
227
+ "metadata": self.metadata,
228
+ }
229
+
230
+ @classmethod
231
+ def from_dict(cls, data: dict) -> "UserContext":
232
+ """Deserialize from dictionary."""
233
+ return cls(
234
+ user_id=data.get("user_id"),
235
+ is_authenticated=data.get("is_authenticated", False),
236
+ username=data.get("username"),
237
+ email=data.get("email"),
238
+ metadata=data.get("metadata", {}),
239
+ )
240
+
241
+ def __str__(self) -> str:
242
+ if self.is_authenticated:
243
+ return f"User({self.username or self.user_id})"
244
+ return "AnonymousUser"
245
+
246
+
247
+ # Default instances for convenience
248
+ DEFAULT_PRIVACY_CONFIG = PrivacyConfig()
249
+ ANONYMOUS_USER = UserContext.anonymous()
250
+
@@ -75,8 +75,10 @@ class ToolCallingAgent(AgentRuntime):
75
75
  Maximum number of tool-calling iterations.
76
76
 
77
77
  Override to change the default limit.
78
+ Default uses the value from config (default: 50).
78
79
  """
79
- return 15
80
+ from agent_runtime_core.config import get_config
81
+ return get_config().max_iterations
80
82
 
81
83
  @property
82
84
  def model(self) -> Optional[str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-runtime-core
3
- Version: 0.8.0
3
+ Version: 0.9.1
4
4
  Summary: Framework-agnostic Python library for executing AI agents with consistent patterns
5
5
  Project-URL: Homepage, https://github.com/makemore/agent-runtime-core
6
6
  Project-URL: Repository, https://github.com/makemore/agent-runtime-core
@@ -92,6 +92,7 @@ A lightweight, framework-agnostic Python library for building AI agent systems.
92
92
 
93
93
  | Version | Date | Changes |
94
94
  |---------|------|---------|
95
+ | **0.9.0** | 2026-01-28 | **Multi-Agent & Debug** - Shared memory with privacy controls, journey mode, structured handback protocol, stuck/loop detection, fallback routing, cost/context tracking in debug mode |
95
96
  | **0.8.0** | 2026-01-28 | **File Ingestion** - Pluggable file processors (PDF, images, DOCX, XLSX, CSV), OCR providers (Tesseract, Google Vision, AWS Textract, Azure), AI vision (OpenAI, Anthropic, Gemini), file read/write tools |
96
97
  | **0.7.1** | 2026-01-24 | RAG module, vector stores (sqlite-vec, Vertex AI), memory system, multi-agent support, agentic loop, JSON runtime |
97
98
  | **0.6.0** | 2025-01-23 | Enhanced registry with factory functions and class registration |
@@ -1,16 +1,17 @@
1
- agent_runtime_core/__init__.py,sha256=Vn-32GMh-6S5k6e4fiejAbNxjnbsoskf-Um1Ni2dgog,7117
2
- agent_runtime_core/agentic_loop.py,sha256=DJ3RXaQLFlHMf-icQjpTJkAvdfjkPBSGN1S_iy3mf64,9635
3
- agent_runtime_core/config.py,sha256=WVfcIluFvf2zC_NKk2WuJhhPIGQNcuxmZV9TCg4t13o,7297
1
+ agent_runtime_core/__init__.py,sha256=80m5og5XW2cGvFlU2dQ4aj8RZ_Z0gQdswstmkhxVleM,8656
2
+ agent_runtime_core/agentic_loop.py,sha256=nphrM0uvf41n9e9s4elxlObel02uuXsd-lrSny_3Cpc,22050
3
+ agent_runtime_core/config.py,sha256=7v3NPuE6LQcNLb0MpgpnelEW13ZinXflaCOwYTKdcWQ,7587
4
4
  agent_runtime_core/config_schema.py,sha256=1t2ZF5Rk2oRbeYpRATMdFgbvgTPtedIQO6xej4cELh0,10576
5
- agent_runtime_core/contexts.py,sha256=41UVkSqRJ3E9yIxfCQ-BQ7-wetUfSnDNGdr5-dQOWiY,11349
6
- agent_runtime_core/interfaces.py,sha256=QvRFPRc2Fwqv_sv-3nExCoaiqwBf_HsQo9yzCYE_Hm0,15498
5
+ agent_runtime_core/contexts.py,sha256=ws4St30698DR6E-ce9ou0wJwFxUE3S_pPXNcXrlDB-Q,14474
6
+ agent_runtime_core/interfaces.py,sha256=rjA8KsbyyKpkVmJvjYQbmIcdoDjt8l3z1FsYFXZkN1A,16263
7
7
  agent_runtime_core/json_runtime.py,sha256=b1BnGAQMORB4YULsKcCR0hEaCvln3Bz2dP228yq5BIQ,17358
8
- agent_runtime_core/multi_agent.py,sha256=UleIFocGW0GZFeoa_bPfYGLZZH-NYiEsiG2BBTGdKyA,18409
8
+ agent_runtime_core/multi_agent.py,sha256=k8OlPY2AQ5G0eXl53QgcBglUFK7i2f4bahhLy1Nt2Fs,68536
9
+ agent_runtime_core/privacy.py,sha256=47b_5FrUBhNrONaziLlVvUOxtmzaMSYGkrVN6krFDjw,8983
9
10
  agent_runtime_core/registry.py,sha256=QmazCAcHTsPt236Z_xEBJjdppm6jUuufE-gfvcGMUCk,3959
10
11
  agent_runtime_core/runner.py,sha256=ydzyGJHCyz1wjs-sN5dx4RlJsYK0U-Or12BL_Fg8-aQ,19595
11
12
  agent_runtime_core/steps.py,sha256=XpVFK7P-ZOpr7NwaP7XFygduIpjrKld-OIig7dHNMKE,11994
12
13
  agent_runtime_core/testing.py,sha256=ordECGprBappLBMWxlETvuf2AoIPNomJFeSedXaY30E,11131
13
- agent_runtime_core/tool_calling_agent.py,sha256=kyPTwHlYGaqUo0HJ7ycYCCQMFHD_AmPZMsyjxaKpJVc,5967
14
+ agent_runtime_core/tool_calling_agent.py,sha256=CCtGXSh2iLHksY1PodMVIxCMYN5OntfYvhO7vXpus7Q,6107
14
15
  agent_runtime_core/tools.py,sha256=SSbiViOJe7raSijwV_TSHI60F5ReHy43Vd_QrAkKgAk,5620
15
16
  agent_runtime_core/events/__init__.py,sha256=Gg7cMQHWfLTQ4Xik09KSg7cWbQDmW_MuF5_jl-yZkHU,1575
16
17
  agent_runtime_core/events/base.py,sha256=NfHYyoczxr40Er5emROi_aY_07m5hDrKsn31pdWY2DY,1950
@@ -24,16 +25,16 @@ agent_runtime_core/files/processors.py,sha256=KudeacTDxaVyUtCjBpIg1OuByi4_71WP9R
24
25
  agent_runtime_core/files/tools.py,sha256=Dky2CxFLUL8GICIwU1kbNV-IwnszWr1WXhJ3FItGRd4,10856
25
26
  agent_runtime_core/files/vision.py,sha256=nM8xKx-yEblwPFr5tM9JRrFkitTPLDkLU1fSDHLvuW8,10119
26
27
  agent_runtime_core/llm/__init__.py,sha256=7-tA1FmPkhY1l-lHhzd84MQf2bjs26bcgb8oAlglc58,4605
27
- agent_runtime_core/llm/anthropic.py,sha256=AX2QJoQf-4uLDCxWFs71XfD11IMN6iI3gMPA25F3KrM,12239
28
+ agent_runtime_core/llm/anthropic.py,sha256=icxQa4BtNg8rOV4B187YKSgutscfT12NXNwaay4rSqA,18474
28
29
  agent_runtime_core/llm/litellm_client.py,sha256=c-O-lE08cT3ne0xSOvSDezPL6hCiA69p3HnB451Ipe4,5193
29
- agent_runtime_core/llm/models_config.py,sha256=i275wtsWeR-LHdFrObPI19PtCIGvMDKTEKpue5TuYIk,5342
30
- agent_runtime_core/llm/openai.py,sha256=qBZkkndDgYQ6LG-9bHS2za5KJTGSgL-c_7h0bD3_5lg,6862
30
+ agent_runtime_core/llm/models_config.py,sha256=_jOi60N9cA3PvVOFvCj1rHSlFN5ue8oI9zO_k1d_J2Y,6816
31
+ agent_runtime_core/llm/openai.py,sha256=Ib4FjpcIq3GPTgC0rqvn9zXBdOEfKlMxkTBAFdE__as,8843
31
32
  agent_runtime_core/memory/__init__.py,sha256=7dgoXMr3IIjKsKKbxVgQBrrhZHqmJRIx64mcbF8jgUM,2178
32
33
  agent_runtime_core/memory/manager.py,sha256=ba8ZKb1aF9Pc-zZB4O_22b6zb6ELpvo_LhpSs959L5U,18474
33
34
  agent_runtime_core/memory/mixin.py,sha256=Afq7rhW1SmZgii6b3gUbM3peDzMwfMxQ0DstHzGfuDM,9683
34
- agent_runtime_core/persistence/__init__.py,sha256=HdkGW5hnLjBRE0QcUWVjL2xsIkMyKPpqJKpamPbFh0s,2822
35
- agent_runtime_core/persistence/base.py,sha256=k0wuzTCffPJ609dj9hIhnaqnNI1Qr3pCzJ-6E1YkSRU,21616
36
- agent_runtime_core/persistence/file.py,sha256=uZxl3W405jeX1H6f0Xj_pZOQFTpZOYbpIdJ98rZabBI,28712
35
+ agent_runtime_core/persistence/__init__.py,sha256=TeGcQSfNGGBAc_aEWmSkxh6U-rG_Gbelyk2CAke8Lwg,3008
36
+ agent_runtime_core/persistence/base.py,sha256=zyKQDTKMX9rHucota1RI6zWQzmiOd_R6qHCaLZfyvXk,32015
37
+ agent_runtime_core/persistence/file.py,sha256=QfhRdPI4bEDJJaKogG-kYdD0HkWpNEOE2-3oEtMlUZQ,36005
37
38
  agent_runtime_core/persistence/manager.py,sha256=UL_eFsFM28nXM6O9PTHdzKX9Qxh9v2gBGd1m9Bs0vog,14309
38
39
  agent_runtime_core/queue/__init__.py,sha256=m8gapXACPGApLj0RIDpVe5cQYuvKq1QsY2_mXzZcULQ,1527
39
40
  agent_runtime_core/queue/base.py,sha256=QW1eWbwBX_tmVD8yJobFJtlxLd_RtUWHTuXGessuxy8,3959
@@ -57,7 +58,7 @@ agent_runtime_core/vectorstore/base.py,sha256=y1ZZCbAMkFkbHwOqzaK0JUBAVjbnNwwdSn
57
58
  agent_runtime_core/vectorstore/embeddings.py,sha256=WTTiId9Q6I7cxHuiInYHEV8EWS2HyRYRW1YDPALGUVY,7749
58
59
  agent_runtime_core/vectorstore/sqlite_vec.py,sha256=B4KPYdSkm-af-uqltqMga1uXslC19Uaeuy1sXfKOjyo,10552
59
60
  agent_runtime_core/vectorstore/vertex.py,sha256=a1Ps_gMYqTlWUkNALpgMVEX6r6Zw_8gN5pZ59-vH7Ww,9695
60
- agent_runtime_core-0.8.0.dist-info/METADATA,sha256=nC_KSql_QyKBPfaGxyakWQhTR_z15gj3X068l7viqqY,32431
61
- agent_runtime_core-0.8.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
62
- agent_runtime_core-0.8.0.dist-info/licenses/LICENSE,sha256=fDlWep3_mUrj8KHV_jk275tHVEW7_9sJRhkNuGCZ_TA,1068
63
- agent_runtime_core-0.8.0.dist-info/RECORD,,
61
+ agent_runtime_core-0.9.1.dist-info/METADATA,sha256=xG7r5bvo-7DxmsFv22N8DkNvt0mVfT4PnFiBGVzgvoA,32643
62
+ agent_runtime_core-0.9.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
63
+ agent_runtime_core-0.9.1.dist-info/licenses/LICENSE,sha256=eWG1BdmVdl1LpUaXNfUwEHIGm8qFT5UzSB08LhYyLTo,3850
64
+ agent_runtime_core-0.9.1.dist-info/RECORD,,
@@ -0,0 +1,83 @@
1
+ Business Source License 1.1
2
+
3
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
4
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
5
+
6
+ Parameters
7
+
8
+ Licensor: Chris Barry
9
+ Licensed Work: agent-runtime-core
10
+ The Licensed Work is (c) 2025 Chris Barry
11
+ Additional Use Grant: You may use the Licensed Work for non-production purposes,
12
+ including development, testing, and evaluation. Production
13
+ use requires a commercial license from the Licensor.
14
+ Change Date: 2029-01-24
15
+ Change License: MIT
16
+
17
+ Terms
18
+
19
+ The Licensor hereby grants you the right to copy, modify, create derivative
20
+ works, redistribute, and make non-production use of the Licensed Work. The
21
+ Licensor may make an Additional Use Grant, above, permitting limited production
22
+ use.
23
+
24
+ Effective on the Change Date, or the fourth anniversary of the first publicly
25
+ available distribution of a specific version of the Licensed Work under this
26
+ License, whichever comes first, the Licensor hereby grants you rights under
27
+ the terms of the Change License, and the rights granted in the paragraph above
28
+ terminate.
29
+
30
+ If your use of the Licensed Work does not comply with the requirements
31
+ currently in effect as described in this License, you must purchase a
32
+ commercial license from the Licensor, its affiliated entities, or authorized
33
+ resellers, or you must refrain from using the Licensed Work.
34
+
35
+ All copies of the original and modified Licensed Work, and derivative works
36
+ of the Licensed Work, are subject to this License. This License applies
37
+ separately for each version of the Licensed Work and the Change Date may vary
38
+ for each version of the Licensed Work released by Licensor.
39
+
40
+ You must conspicuously display this License on each original or modified copy
41
+ of the Licensed Work. If you receive the Licensed Work in original or
42
+ modified form from a third party, the terms and conditions set forth in this
43
+ License apply to your use of that work.
44
+
45
+ Any use of the Licensed Work in violation of this License will automatically
46
+ terminate your rights under this License for the current and all other
47
+ versions of the Licensed Work.
48
+
49
+ This License does not grant you any right in any trademark or logo of
50
+ Licensor or its affiliates (provided that you may use a trademark or logo of
51
+ Licensor as expressly required by this License).
52
+
53
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
54
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
55
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
56
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
57
+ TITLE.
58
+
59
+ MariaDB hereby grants you permission to use this License's text to license
60
+ your works, and to refer to it using the trademark "Business Source License",
61
+ as long as you comply with the Covenants of Licensor below.
62
+
63
+ Covenants of Licensor
64
+
65
+ In consideration of the right to use this License's text and the "Business
66
+ Source License" name and trademark, Licensor covenants to MariaDB, and to all
67
+ other recipients of the licensed work to be provided by Licensor:
68
+
69
+ 1. To specify as the Change License the GPL Version 2.0 or any later version,
70
+ or a license that is compatible with GPL Version 2.0 or a later version,
71
+ where "compatible" means that software provided under the Change License can
72
+ be included in a program with software provided under GPL Version 2.0 or a
73
+ later version. Licensor may specify additional Change Licenses without
74
+ limitation.
75
+
76
+ 2. To either: (a) specify an additional grant of rights to use that does not
77
+ impose any additional restriction on the right granted in this License, as
78
+ the Additional Use Grant; or (b) insert the text "None".
79
+
80
+ 3. To specify a Change Date.
81
+
82
+ 4. Not to modify this License in any other way.
83
+
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Chris Barry
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.