dirigent-plugin 0.21.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.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-plugin
3
- Version: 0.21.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.21.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.21.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.21.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.21.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.21.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 API_VERSION, SHELL_MEDIA_TYPE, BlockModel, HealthReport, Issue, JsonMap, Message
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,
@@ -364,7 +373,13 @@ class ContainerResult(BaseModel):
364
373
 
365
374
 
366
375
  class AlertMessage(BaseModel):
367
- """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
+ """
368
383
 
369
384
  event: str = Field(min_length=1)
370
385
  subject: str = Field(min_length=1)
@@ -372,6 +387,10 @@ class AlertMessage(BaseModel):
372
387
  run_id: RunId | None = None
373
388
  pipeline: str | None = None
374
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."""
375
394
  context: dict[str, JsonValue] = Field(default_factory=dict)
376
395
 
377
396
 
@@ -493,6 +512,10 @@ class RunSnapshot(BaseModel):
493
512
  total_steps: int = Field(default=0, ge=0)
494
513
  finished_steps: int = Field(default=0, ge=0)
495
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."""
496
519
 
497
520
  @property
498
521
  def progress(self) -> float | None:
@@ -524,8 +547,12 @@ class Runs(Protocol):
524
547
  """Describe a run this instance holds, or return None when it holds no such run."""
525
548
  ...
526
549
 
527
- async def cancel(self, run_id: RunId, *, reason: str) -> bool:
528
- """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
+ """
529
556
  ...
530
557
 
531
558
 
@@ -837,7 +864,7 @@ type AnySensor = Sensor[Any, Any]
837
864
 
838
865
 
839
866
  class Contribution(BaseModel):
840
- """Everything one plugin adds, across all six surfaces, gathered by the host at startup."""
867
+ """Everything one plugin adds, across all seven surfaces, gathered by the host at startup."""
841
868
 
842
869
  model_config = ConfigDict(arbitrary_types_allowed=True, frozen=True)
843
870
 
@@ -852,6 +879,14 @@ class Contribution(BaseModel):
852
879
  ``format: <name>`` then asserts wherever the contributing pack is installed, and stays a
853
880
  passing annotation on an instance without it."""
854
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
+
855
890
  @field_validator("api_version")
856
891
  @classmethod
857
892
  def _check_api_version(cls, value: int) -> int:
@@ -868,6 +903,7 @@ class Contribution(BaseModel):
868
903
  _require_unique("notifier id", [notifier.id for notifier in self.notifiers])
869
904
  _require_unique("connection kind id", [connection.id for connection in self.connection_kinds])
870
905
  _require_unique("format", list(self.formats))
906
+ _require_unique("label prefix", [catalogue.prefix for catalogue in self.labels])
871
907
  return self
872
908
 
873
909
  @model_validator(mode="after")
@@ -901,6 +937,7 @@ def merge_contributions(contributions: list[Contribution]) -> Contribution:
901
937
  "storage_backends": [],
902
938
  "notifiers": [],
903
939
  "connection_kinds": [],
940
+ "labels": [],
904
941
  }
905
942
  for contribution in contributions:
906
943
  for surface, collected in merged.items():