agent-chat-plugin 0.7.0__tar.gz → 0.7.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.
- {agent_chat_plugin-0.7.0/agent_chat_plugin.egg-info → agent_chat_plugin-0.7.2}/PKG-INFO +1 -1
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat/lease_store.py +35 -21
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat/path_locks.py +22 -6
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat/state_store.py +9 -1
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat/task_store.py +9 -3
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2/agent_chat_plugin.egg-info}/PKG-INFO +1 -1
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/chat.py +1 -1
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/pyproject.toml +1 -1
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/LICENSE +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/README.md +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat/_advisory_lock.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat/task_model.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/SOURCES.txt +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/dependency_links.txt +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/entry_points.txt +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/top_level.txt +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/setup.cfg +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_capabilities.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_chat.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_context_budget.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_hooks.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_leases.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_path_locks.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_plugin_manifest.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_state.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_state_json_output.py +0 -0
- {agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/tests/test_tasks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-chat-plugin
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Peer AI agents coordinate through markdown messages in shared channel folders — no orchestrator, autonomous zero-token waiting, cross-platform.
|
|
5
5
|
Author: n24q02m
|
|
6
6
|
License: Apache-2.0
|
|
@@ -237,18 +237,19 @@ class LeaseStore:
|
|
|
237
237
|
def _assert_exact_claim_path(self, path: Path, filename: str) -> None:
|
|
238
238
|
self._assert_exact_layout(path, self.claims_dir, kind="claim")
|
|
239
239
|
try:
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
240
|
+
with os.scandir(self.claims_dir) as it:
|
|
241
|
+
for entry in it:
|
|
242
|
+
if (
|
|
243
|
+
os.name == "nt"
|
|
244
|
+
and entry.name.casefold() == filename.casefold()
|
|
245
|
+
and entry.name != filename
|
|
246
|
+
):
|
|
247
|
+
raise LeaseError(
|
|
248
|
+
"LEASE_TRANSACTION_INVALID",
|
|
249
|
+
f"claim filename case alias is not canonical: {filename!r}",
|
|
250
|
+
file=filename,
|
|
251
|
+
actual_file=entry.name,
|
|
252
|
+
)
|
|
252
253
|
except OSError as error:
|
|
253
254
|
raise LeaseError(
|
|
254
255
|
"LEASE_TRANSACTION_INVALID",
|
|
@@ -350,9 +351,15 @@ class LeaseStore:
|
|
|
350
351
|
f"claim storage is not a directory: {self.claims_dir}",
|
|
351
352
|
)
|
|
352
353
|
matches: list[tuple[Path, LeaseRecord]] = []
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
354
|
+
found_paths = []
|
|
355
|
+
try:
|
|
356
|
+
with os.scandir(self.claims_dir) as it:
|
|
357
|
+
for entry in it:
|
|
358
|
+
if entry.name.endswith(".json") and not entry.name.startswith((".", "_")):
|
|
359
|
+
found_paths.append(Path(entry.path))
|
|
360
|
+
except OSError:
|
|
361
|
+
pass
|
|
362
|
+
for path in sorted(found_paths, key=lambda item: item.name):
|
|
356
363
|
self._assert_inside_channel(path)
|
|
357
364
|
record = self._read_claim(path)
|
|
358
365
|
if record.channel == self.channel.name and record.task_id == task_id:
|
|
@@ -390,9 +397,15 @@ class LeaseStore:
|
|
|
390
397
|
f"claim storage is not a directory: {self.claims_dir}",
|
|
391
398
|
)
|
|
392
399
|
records = []
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
400
|
+
found_paths = []
|
|
401
|
+
try:
|
|
402
|
+
with os.scandir(self.claims_dir) as it:
|
|
403
|
+
for entry in it:
|
|
404
|
+
if entry.name.endswith(".json") and not entry.name.startswith((".", "_")):
|
|
405
|
+
found_paths.append(Path(entry.path))
|
|
406
|
+
except OSError:
|
|
407
|
+
pass
|
|
408
|
+
for path in sorted(found_paths, key=lambda item: item.name):
|
|
396
409
|
self._assert_inside_channel(path)
|
|
397
410
|
records.append(self._read_claim(path))
|
|
398
411
|
return records
|
|
@@ -840,11 +853,12 @@ class LeaseStore:
|
|
|
840
853
|
marker = f'"transaction_id": "{transaction_id}"'
|
|
841
854
|
for path in chat.message_files(self.channel):
|
|
842
855
|
try:
|
|
843
|
-
|
|
856
|
+
with path.open(encoding="utf-8") as f:
|
|
857
|
+
for line in f:
|
|
858
|
+
if marker in line:
|
|
859
|
+
return True
|
|
844
860
|
except (OSError, UnicodeError):
|
|
845
861
|
continue
|
|
846
|
-
if marker in body:
|
|
847
|
-
return True
|
|
848
862
|
return False
|
|
849
863
|
|
|
850
864
|
|
|
@@ -679,9 +679,15 @@ class PathLockStore:
|
|
|
679
679
|
f"lock storage is not a directory: {self.locks_dir}",
|
|
680
680
|
)
|
|
681
681
|
records: list[PathLockRecord] = []
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
682
|
+
found_paths = []
|
|
683
|
+
try:
|
|
684
|
+
with os.scandir(self.locks_dir) as it:
|
|
685
|
+
for entry in it:
|
|
686
|
+
if entry.name.endswith(".json") and not entry.name.startswith((".", "_")):
|
|
687
|
+
found_paths.append(Path(entry.path))
|
|
688
|
+
except OSError:
|
|
689
|
+
pass
|
|
690
|
+
for path in sorted(found_paths, key=lambda item: item.name):
|
|
685
691
|
records.append(self._read_record(path))
|
|
686
692
|
return records
|
|
687
693
|
|
|
@@ -1231,8 +1237,10 @@ class PathLockStore:
|
|
|
1231
1237
|
return False
|
|
1232
1238
|
for path in message_paths:
|
|
1233
1239
|
try:
|
|
1234
|
-
|
|
1235
|
-
|
|
1240
|
+
with path.open(encoding="utf-8") as f:
|
|
1241
|
+
for line in f:
|
|
1242
|
+
if marker in line:
|
|
1243
|
+
return True
|
|
1236
1244
|
except (OSError, UnicodeError):
|
|
1237
1245
|
continue
|
|
1238
1246
|
return False
|
|
@@ -1542,7 +1550,15 @@ class PathLockStore:
|
|
|
1542
1550
|
"PATH_LOCK_NOT_FOUND", f"lock record does not exist: {target}"
|
|
1543
1551
|
)
|
|
1544
1552
|
matches: list[tuple[Path, PathLockRecord]] = []
|
|
1545
|
-
|
|
1553
|
+
found_paths = []
|
|
1554
|
+
try:
|
|
1555
|
+
with os.scandir(self.locks_dir) as it:
|
|
1556
|
+
for entry in it:
|
|
1557
|
+
if entry.name.endswith(".json"):
|
|
1558
|
+
found_paths.append(Path(entry.path))
|
|
1559
|
+
except OSError:
|
|
1560
|
+
pass
|
|
1561
|
+
for path in found_paths:
|
|
1546
1562
|
record = self._read_record(path)
|
|
1547
1563
|
if any(item.normalized_path == requested.normalized_path for item in record.paths):
|
|
1548
1564
|
matches.append((path, record))
|
|
@@ -515,7 +515,15 @@ class StateStore:
|
|
|
515
515
|
# records that cannot satisfy the authoritative task contract.
|
|
516
516
|
tasks_dir = self.channel / "tasks"
|
|
517
517
|
if tasks_dir.exists() and tasks_dir.is_dir():
|
|
518
|
-
|
|
518
|
+
found_paths = []
|
|
519
|
+
try:
|
|
520
|
+
with os.scandir(tasks_dir) as it:
|
|
521
|
+
for entry in it:
|
|
522
|
+
if entry.name.endswith(".json"):
|
|
523
|
+
found_paths.append(Path(entry.path))
|
|
524
|
+
except OSError:
|
|
525
|
+
pass
|
|
526
|
+
for path in sorted(found_paths, key=lambda item: item.name):
|
|
519
527
|
try:
|
|
520
528
|
resolved = path.resolve(strict=False)
|
|
521
529
|
resolved.relative_to(tasks_dir.resolve(strict=False))
|
|
@@ -218,9 +218,15 @@ class TaskStore:
|
|
|
218
218
|
f"task storage is not a directory: {self.tasks_dir}",
|
|
219
219
|
)
|
|
220
220
|
records = []
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
221
|
+
found_paths = []
|
|
222
|
+
try:
|
|
223
|
+
with os.scandir(self.tasks_dir) as it:
|
|
224
|
+
for entry in it:
|
|
225
|
+
if entry.name.endswith(".json") and not entry.name.startswith((".", "_")):
|
|
226
|
+
found_paths.append(Path(entry.path))
|
|
227
|
+
except OSError:
|
|
228
|
+
pass
|
|
229
|
+
for path in sorted(found_paths, key=lambda item: item.name):
|
|
224
230
|
self._assert_inside_channel(path)
|
|
225
231
|
records.append(self._read_path(path))
|
|
226
232
|
return records
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-chat-plugin
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Peer AI agents coordinate through markdown messages in shared channel folders — no orchestrator, autonomous zero-token waiting, cross-platform.
|
|
5
5
|
Author: n24q02m
|
|
6
6
|
License: Apache-2.0
|
|
@@ -1597,7 +1597,7 @@ def main(argv=None):
|
|
|
1597
1597
|
except OSError as error:
|
|
1598
1598
|
if "args" in locals() and getattr(args, "cmd", None) == "task":
|
|
1599
1599
|
die(f"TASK_IO_ERROR: {error}", code=2)
|
|
1600
|
-
|
|
1600
|
+
die(f"I/O error: {error}", code=1)
|
|
1601
1601
|
except Exception as error:
|
|
1602
1602
|
if _is_task_error(error):
|
|
1603
1603
|
die(str(error), code=2)
|
|
@@ -10,7 +10,7 @@ requires-python = ">=3.8"
|
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
11
11
|
authors = [{ name = "n24q02m" }]
|
|
12
12
|
keywords = ["multi-agent", "coordination", "markdown", "blackboard", "claude-code", "agent-skills", "peer-to-peer"]
|
|
13
|
-
version = "0.7.
|
|
13
|
+
version = "0.7.2" # managed by python-semantic-release; do not hand-edit
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Programming Language :: Python :: 3",
|
|
16
16
|
"License :: OSI Approved :: Apache Software License",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{agent_chat_plugin-0.7.0 → agent_chat_plugin-0.7.2}/agent_chat_plugin.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|