dirigent-plugin 0.20.0__tar.gz → 0.22.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.
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/PKG-INFO +2 -2
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/pyproject.toml +2 -2
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/pyproject.toml.orig +2 -2
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/blocks.py +58 -8
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/LICENSE +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/README.md +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/__init__.py +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/markers.py +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/messages.py +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/py.typed +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/runners.py +0 -0
- {dirigent_plugin-0.20.0 → dirigent_plugin-0.22.0}/src/dirigent_plugin/transforms.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dirigent-plugin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: The dirigent plugin contract: block specs, protocols, and markers.
|
|
5
5
|
License-Expression: LicenseRef-Proprietary
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
8
8
|
Classifier: Programming Language :: Python :: 3.13
|
|
9
|
-
Requires-Dist: dirigent-common==0.
|
|
9
|
+
Requires-Dist: dirigent-common==0.22.0
|
|
10
10
|
Requires-Dist: httpx2>=2.12.0
|
|
11
11
|
Requires-Dist: pluginkit>=0.5.0
|
|
12
12
|
Requires-Dist: pydantic>=2.13.5
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dirigent-plugin"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.22.0"
|
|
4
4
|
description = "The dirigent plugin contract: block specs, protocols, and markers."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -11,7 +11,7 @@ classifiers = [
|
|
|
11
11
|
"Programming Language :: Python :: 3.13",
|
|
12
12
|
]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"dirigent-common==0.
|
|
14
|
+
"dirigent-common==0.22.0",
|
|
15
15
|
"httpx2>=2.12.0",
|
|
16
16
|
"pluginkit>=0.5.0",
|
|
17
17
|
"pydantic>=2.13.5",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dirigent-plugin"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.22.0"
|
|
4
4
|
description = "The dirigent plugin contract: block specs, protocols, and markers."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -11,7 +11,7 @@ classifiers = [
|
|
|
11
11
|
"Programming Language :: Python :: 3.13",
|
|
12
12
|
]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"dirigent-common==0.
|
|
14
|
+
"dirigent-common==0.22.0",
|
|
15
15
|
"httpx2>=2.12.0",
|
|
16
16
|
"pluginkit>=0.5.0",
|
|
17
17
|
"pydantic>=2.13.5",
|
|
@@ -16,7 +16,16 @@ from pydantic import BaseModel, ConfigDict, Field, GetJsonSchemaHandler, JsonVal
|
|
|
16
16
|
from pydantic.json_schema import JsonSchemaValue, SkipJsonSchema
|
|
17
17
|
from pydantic_core import CoreSchema
|
|
18
18
|
|
|
19
|
-
from dirigent_common import
|
|
19
|
+
from dirigent_common import (
|
|
20
|
+
API_VERSION,
|
|
21
|
+
SHELL_MEDIA_TYPE,
|
|
22
|
+
BlockModel,
|
|
23
|
+
Catalogue,
|
|
24
|
+
HealthReport,
|
|
25
|
+
Issue,
|
|
26
|
+
JsonMap,
|
|
27
|
+
Message,
|
|
28
|
+
)
|
|
20
29
|
from dirigent_plugin.messages import (
|
|
21
30
|
DUPLICATE_ID,
|
|
22
31
|
INVALID_MARK,
|
|
@@ -280,8 +289,9 @@ class NotYet(BaseModel):
|
|
|
280
289
|
worker that dies before that commit leaves the older cursor for the next poke to read
|
|
281
290
|
from again. So a poke must tolerate reading the same ground twice.
|
|
282
291
|
|
|
283
|
-
The cursor's life is the waiting attempt. A poke that succeeds ends the step, and
|
|
284
|
-
|
|
292
|
+
The cursor's life is the waiting attempt. A poke that succeeds ends the step, and only
|
|
293
|
+
:meth:`Sensor.resume_cursor` carries a cursor past it: a watch hands what that returns to
|
|
294
|
+
the first poke of the run it arms next.
|
|
285
295
|
"""
|
|
286
296
|
|
|
287
297
|
|
|
@@ -363,7 +373,13 @@ class ContainerResult(BaseModel):
|
|
|
363
373
|
|
|
364
374
|
|
|
365
375
|
class AlertMessage(BaseModel):
|
|
366
|
-
"""What an alert rule hands a notifier: the event, a rendered summary, and links back.
|
|
376
|
+
"""What an alert rule hands a notifier: the event, a rendered summary, and links back.
|
|
377
|
+
|
|
378
|
+
The subject and the body are the rule author's own template rendered over the run, so they
|
|
379
|
+
are that author's words in that author's language and carry no code. What dirigent itself
|
|
380
|
+
said is ``error_code`` and ``error_params``: the refusal the run ended with, which a
|
|
381
|
+
notifier with a catalogue can render in the language of wherever it delivers.
|
|
382
|
+
"""
|
|
367
383
|
|
|
368
384
|
event: str = Field(min_length=1)
|
|
369
385
|
subject: str = Field(min_length=1)
|
|
@@ -371,6 +387,10 @@ class AlertMessage(BaseModel):
|
|
|
371
387
|
run_id: RunId | None = None
|
|
372
388
|
pipeline: str | None = None
|
|
373
389
|
url: str | None = None
|
|
390
|
+
error_code: str | None = None
|
|
391
|
+
"""The dotted code of the refusal the alerted run ended with, when it ended with one."""
|
|
392
|
+
error_params: dict[str, JsonValue] = Field(default_factory=dict)
|
|
393
|
+
"""The specifics that refusal rendered, for a re-render in another language."""
|
|
374
394
|
context: dict[str, JsonValue] = Field(default_factory=dict)
|
|
375
395
|
|
|
376
396
|
|
|
@@ -492,6 +512,10 @@ class RunSnapshot(BaseModel):
|
|
|
492
512
|
total_steps: int = Field(default=0, ge=0)
|
|
493
513
|
finished_steps: int = Field(default=0, ge=0)
|
|
494
514
|
error: str | None = None
|
|
515
|
+
error_code: str | None = None
|
|
516
|
+
"""The dotted code of the refusal this run ended with, when it ended with one."""
|
|
517
|
+
error_params: JsonMap = Field(default_factory=dict)
|
|
518
|
+
"""The specifics that refusal rendered, for a re-render in another language."""
|
|
495
519
|
|
|
496
520
|
@property
|
|
497
521
|
def progress(self) -> float | None:
|
|
@@ -523,8 +547,12 @@ class Runs(Protocol):
|
|
|
523
547
|
"""Describe a run this instance holds, or return None when it holds no such run."""
|
|
524
548
|
...
|
|
525
549
|
|
|
526
|
-
async def cancel(self, run_id: RunId,
|
|
527
|
-
"""Cancel a run; False means it had already settled and there was nothing to stop.
|
|
550
|
+
async def cancel(self, run_id: RunId, reason: Message, /, **params: Any) -> bool:
|
|
551
|
+
"""Cancel a run; False means it had already settled and there was nothing to stop.
|
|
552
|
+
|
|
553
|
+
The reason is a catalogued message, so the cancelled run carries a code and whoever
|
|
554
|
+
reads it renders their own sentence rather than this block's English.
|
|
555
|
+
"""
|
|
528
556
|
...
|
|
529
557
|
|
|
530
558
|
|
|
@@ -551,7 +579,9 @@ class StepContext(Protocol):
|
|
|
551
579
|
cursor: JsonMap | None
|
|
552
580
|
"""The cursor the last committed :class:`NotYet` returned, and None on the first poke.
|
|
553
581
|
|
|
554
|
-
|
|
582
|
+
The first poke of a run a watch armed is handed where the watch's last success left off
|
|
583
|
+
instead, which is what :meth:`Sensor.resume_cursor` returned. Only a sensor's poke reads
|
|
584
|
+
it; every other call sees None.
|
|
555
585
|
"""
|
|
556
586
|
|
|
557
587
|
def connection[C: BaseModel](self, ref: ConnectionRef, model: type[C]) -> C:
|
|
@@ -682,6 +712,16 @@ class Sensor[ConfigT: BaseModel, OutputT: BaseModel](ABC):
|
|
|
682
712
|
"""Observe the world once, read-only and briefly; NotYet is not a failure."""
|
|
683
713
|
...
|
|
684
714
|
|
|
715
|
+
def resume_cursor(self, output: OutputT) -> JsonMap | None:
|
|
716
|
+
"""Say where a poke that succeeded left off, read from the output it succeeded with.
|
|
717
|
+
|
|
718
|
+
A watch stores what this returns and hands it to the first poke of the next run it
|
|
719
|
+
arms as ``ctx.cursor``. None, the default, starts every run fresh. It is stored in the
|
|
720
|
+
transaction that settles the step, so it is only as far along as the last success that
|
|
721
|
+
committed, and the next poke may read that ground again.
|
|
722
|
+
"""
|
|
723
|
+
return None
|
|
724
|
+
|
|
685
725
|
def check_config(self, config: BaseModel) -> list[Issue]:
|
|
686
726
|
"""List the extra refusals this block makes at apply, beyond what its schema says.
|
|
687
727
|
|
|
@@ -824,7 +864,7 @@ type AnySensor = Sensor[Any, Any]
|
|
|
824
864
|
|
|
825
865
|
|
|
826
866
|
class Contribution(BaseModel):
|
|
827
|
-
"""Everything one plugin adds, across all
|
|
867
|
+
"""Everything one plugin adds, across all seven surfaces, gathered by the host at startup."""
|
|
828
868
|
|
|
829
869
|
model_config = ConfigDict(arbitrary_types_allowed=True, frozen=True)
|
|
830
870
|
|
|
@@ -839,6 +879,14 @@ class Contribution(BaseModel):
|
|
|
839
879
|
``format: <name>`` then asserts wherever the contributing pack is installed, and stays a
|
|
840
880
|
passing annotation on an instance without it."""
|
|
841
881
|
|
|
882
|
+
labels: list[Catalogue] = Field(default_factory=list[Catalogue])
|
|
883
|
+
"""The message catalogues this plugin refuses out of, so a surface can render its codes.
|
|
884
|
+
|
|
885
|
+
A pack's refusal reaches a browser under the pack's own code, and the browser holds no table
|
|
886
|
+
for it. Contributing the catalogue is what puts one there: the host serves every code and its
|
|
887
|
+
template, and a renderer that knows the code says its own sentence rather than repeating the
|
|
888
|
+
English this process happened to mint."""
|
|
889
|
+
|
|
842
890
|
@field_validator("api_version")
|
|
843
891
|
@classmethod
|
|
844
892
|
def _check_api_version(cls, value: int) -> int:
|
|
@@ -855,6 +903,7 @@ class Contribution(BaseModel):
|
|
|
855
903
|
_require_unique("notifier id", [notifier.id for notifier in self.notifiers])
|
|
856
904
|
_require_unique("connection kind id", [connection.id for connection in self.connection_kinds])
|
|
857
905
|
_require_unique("format", list(self.formats))
|
|
906
|
+
_require_unique("label prefix", [catalogue.prefix for catalogue in self.labels])
|
|
858
907
|
return self
|
|
859
908
|
|
|
860
909
|
@model_validator(mode="after")
|
|
@@ -888,6 +937,7 @@ def merge_contributions(contributions: list[Contribution]) -> Contribution:
|
|
|
888
937
|
"storage_backends": [],
|
|
889
938
|
"notifiers": [],
|
|
890
939
|
"connection_kinds": [],
|
|
940
|
+
"labels": [],
|
|
891
941
|
}
|
|
892
942
|
for contribution in contributions:
|
|
893
943
|
for surface, collected in merged.items():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|