ww-agentic-workflows 1.0.0.dev3__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.
- ww/__init__.py +18 -0
- ww/_bundled_extensions/ww/git/extension.py +1728 -0
- ww/action_execution.py +887 -0
- ww/actions/__init__.py +94 -0
- ww/actions/command.py +444 -0
- ww/actions/contracts.py +699 -0
- ww/actions/extension.py +197 -0
- ww/actions/mcp.py +84 -0
- ww/actions/prompt.py +74 -0
- ww/actions/skill.py +62 -0
- ww/actions/slash_command.py +63 -0
- ww/agents.py +151 -0
- ww/amendments.py +54 -0
- ww/artifacts.py +93 -0
- ww/assessments.py +181 -0
- ww/assets/__init__.py +2 -0
- ww/assets/agent_instructions.md +49 -0
- ww/assets/docs/examples.md +879 -0
- ww/assets/docs/features.md +4639 -0
- ww/assets/docs/specification.md +1876 -0
- ww/assets/noww_skill.md +11 -0
- ww/assets/workflows/catchall.yaml +26 -0
- ww/assets/workflows/onboarding.yaml +586 -0
- ww/assets/workflows/scriptize.yaml +130 -0
- ww/assets/ww-automate_skill.md +23 -0
- ww/assets/ww-deduce-feedback_skill.md +38 -0
- ww/assets/ww-feedback-rules_skill.md +48 -0
- ww/assets/ww-learn-project_skill.md +22 -0
- ww/assets/ww-refresh_skill.md +26 -0
- ww/assets/ww-rule_skill.md +83 -0
- ww/assets/ww-rules-from-artifacts_skill.md +22 -0
- ww/assets/ww-scriptize_skill.md +33 -0
- ww/assets/ww-setup_skill.md +94 -0
- ww/assets/ww-solve_skill.md +23 -0
- ww/assets/ww-suggest_skill.md +32 -0
- ww/assets/ww-wizard_skill.md +105 -0
- ww/assets/ww_skill.md +59 -0
- ww/assignments.py +283 -0
- ww/bootstrap.py +405 -0
- ww/builtin_workflows.py +215 -0
- ww/changes.py +225 -0
- ww/child_coordination.py +482 -0
- ww/children.py +106 -0
- ww/claude_permissions.py +115 -0
- ww/cli/__init__.py +7 -0
- ww/cli/__main__.py +6 -0
- ww/cli/audit.py +129 -0
- ww/cli/catalogs.py +131 -0
- ww/cli/discover.py +607 -0
- ww/cli/initialization.py +898 -0
- ww/cli/lookup.py +287 -0
- ww/cli/main.py +1768 -0
- ww/cli/parser.py +1200 -0
- ww/cli/prompts.py +217 -0
- ww/cli/updates.py +117 -0
- ww/completion_artifacts.py +156 -0
- ww/completion_inputs.py +39 -0
- ww/config/__init__.py +582 -0
- ww/config/actions.py +591 -0
- ww/config/composition.py +571 -0
- ww/config/rules.py +511 -0
- ww/config/steps.py +1220 -0
- ww/config/values.py +223 -0
- ww/config_files.py +191 -0
- ww/config_writes.py +264 -0
- ww/contracts.py +155 -0
- ww/control.py +41 -0
- ww/defaults.py +130 -0
- ww/design_docs.py +32 -0
- ww/discovery.py +104 -0
- ww/documents.py +217 -0
- ww/errors.py +18 -0
- ww/executable.py +43 -0
- ww/execution_models/__init__.py +64 -0
- ww/execution_models/construction.py +148 -0
- ww/execution_models/decoding.py +38 -0
- ww/execution_models/plan_codec.py +565 -0
- ww/execution_models/records.py +1206 -0
- ww/execution_models/runs.py +266 -0
- ww/extensions/__init__.py +40 -0
- ww/extensions/api.py +559 -0
- ww/extensions/registry.py +864 -0
- ww/extensions/store.py +78 -0
- ww/feedback.py +342 -0
- ww/handler_repairs.py +57 -0
- ww/hooks/__init__.py +40 -0
- ww/hooks/agents.py +380 -0
- ww/hooks/install.py +168 -0
- ww/hooks/notices.py +206 -0
- ww/hooks/records.py +209 -0
- ww/hooks/runtime.py +266 -0
- ww/hooks/transcripts.py +183 -0
- ww/inspect.py +896 -0
- ww/instructions/__init__.py +17 -0
- ww/instructions/builder.py +1682 -0
- ww/instructions/commands.py +335 -0
- ww/instructions/handoff.py +149 -0
- ww/instructions/models.py +686 -0
- ww/instructions/policy.py +219 -0
- ww/instructions/text.py +168 -0
- ww/interactions.py +187 -0
- ww/interpolation.py +37 -0
- ww/item_passes.py +167 -0
- ww/items.py +99 -0
- ww/locking.py +207 -0
- ww/metadata_publication.py +230 -0
- ww/onboarding.py +229 -0
- ww/open_work.py +236 -0
- ww/operations.py +193 -0
- ww/operator_ui/__init__.py +16 -0
- ww/operator_ui/page.html +351 -0
- ww/operator_ui/server.py +215 -0
- ww/operator_ui/session.py +389 -0
- ww/operator_ui/sheet.py +104 -0
- ww/operator_ui/view.py +109 -0
- ww/output.py +339 -0
- ww/output_adapters/__init__.py +12 -0
- ww/output_adapters/base.py +25 -0
- ww/output_adapters/json_adapter.py +37 -0
- ww/output_adapters/markdown.py +2293 -0
- ww/output_adapters/rule_pages.py +337 -0
- ww/output_adapters/terminal.py +21 -0
- ww/package_updates.py +167 -0
- ww/plan/__init__.py +38 -0
- ww/plan/actions.py +207 -0
- ww/plan/compiler.py +1492 -0
- ww/plan/constructs.py +456 -0
- ww/plan/models.py +665 -0
- ww/project_config.py +752 -0
- ww/recovery.py +401 -0
- ww/replanning.py +367 -0
- ww/results.py +77 -0
- ww/rule_checks.py +230 -0
- ww/rule_conversion.py +331 -0
- ww/rule_disputes.py +148 -0
- ww/rule_store.py +456 -0
- ww/rule_verification.py +714 -0
- ww/rule_views.py +447 -0
- ww/rule_writes.py +920 -0
- ww/run_coordination.py +158 -0
- ww/runtimes.py +105 -0
- ww/service.py +4405 -0
- ww/setup_apply.py +428 -0
- ww/step_values.py +20 -0
- ww/storage.py +447 -0
- ww/storage_adapters/__init__.py +36 -0
- ww/storage_adapters/base.py +540 -0
- ww/storage_adapters/filesystem.py +370 -0
- ww/storage_adapters/memory.py +195 -0
- ww/storage_adapters/project_metadata.py +69 -0
- ww/storage_adapters/task_document.py +484 -0
- ww/task_ids.py +114 -0
- ww/task_references.py +124 -0
- ww/transitions.py +1619 -0
- ww/updates.py +399 -0
- ww/upgrade.py +95 -0
- ww/validation.py +168 -0
- ww/variables.py +275 -0
- ww/workflow_config.py +854 -0
- ww/workflow_update.py +239 -0
- ww/workflow_validation.py +1260 -0
- ww/workspace.py +50 -0
- ww_agentic_workflows-1.0.0.dev3.dist-info/METADATA +690 -0
- ww_agentic_workflows-1.0.0.dev3.dist-info/RECORD +167 -0
- ww_agentic_workflows-1.0.0.dev3.dist-info/WHEEL +4 -0
- ww_agentic_workflows-1.0.0.dev3.dist-info/entry_points.txt +2 -0
- ww_agentic_workflows-1.0.0.dev3.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
"""Run aggregates, plan snapshots, and the invariants that tie them together."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import hashlib
|
|
7
|
+
import json
|
|
8
|
+
from dataclasses import dataclass, replace
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from ww.actions import PlannedAction, actions
|
|
12
|
+
from ww.children import ChildTask
|
|
13
|
+
from ww.contracts import BOOTSTRAP_REQUEST_PREFIX, RunStatus, run_is_open
|
|
14
|
+
from ww.errors import StateError
|
|
15
|
+
from ww.items import WorkItem
|
|
16
|
+
from ww.plan import PlanItem, WorkflowPlan
|
|
17
|
+
from ww.validation import (
|
|
18
|
+
expect_optional_string,
|
|
19
|
+
expect_positive_int,
|
|
20
|
+
expect_string,
|
|
21
|
+
is_strict_int,
|
|
22
|
+
require_keys,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
from .decoding import _from_path
|
|
26
|
+
from .plan_codec import _plan_from_dict
|
|
27
|
+
from .records import ExecutionState
|
|
28
|
+
|
|
29
|
+
# Schema 2 records explicit ``items`` pass identity on plan items.
|
|
30
|
+
PLAN_SCHEMA_VERSION = 2
|
|
31
|
+
# Recorded on every snapshot; informational until a reader needs to branch on it.
|
|
32
|
+
PLAN_COMPILER_VERSION = "plan-v10"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class WorkflowRunSummary:
|
|
37
|
+
"""Task-level projection of one independently persisted workflow run."""
|
|
38
|
+
|
|
39
|
+
run_id: str
|
|
40
|
+
workflow: str
|
|
41
|
+
status: RunStatus
|
|
42
|
+
summary: str | None = None
|
|
43
|
+
|
|
44
|
+
def to_dict(self) -> dict[str, str | None]:
|
|
45
|
+
return self.__dict__.copy()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class TaskRunAggregate:
|
|
50
|
+
"""Authoritative, atomically published state for one workflow run.
|
|
51
|
+
|
|
52
|
+
``plan`` and ``state`` are the source of truth. Items and children are
|
|
53
|
+
included in the same record because they participate in transitions (and
|
|
54
|
+
are therefore not safe as independently committed side files).
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
run_id: str
|
|
58
|
+
workflow: str
|
|
59
|
+
snapshot: PlanSnapshot
|
|
60
|
+
state: ExecutionState
|
|
61
|
+
items: tuple[WorkItem, ...] = ()
|
|
62
|
+
children: tuple[ChildTask, ...] = ()
|
|
63
|
+
bootstrap_request_id: str | None = None
|
|
64
|
+
|
|
65
|
+
def to_dict(self) -> dict[str, Any]:
|
|
66
|
+
return {
|
|
67
|
+
"run_id": self.run_id,
|
|
68
|
+
"workflow": self.workflow,
|
|
69
|
+
"snapshot": self.snapshot.to_dict(),
|
|
70
|
+
"state": self.state.to_dict(),
|
|
71
|
+
"items": [item.to_dict() for item in self.items],
|
|
72
|
+
"children": [child.to_dict() for child in self.children],
|
|
73
|
+
"bootstrap_request_id": self.bootstrap_request_id,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_dict(cls, data: Any) -> TaskRunAggregate:
|
|
78
|
+
"""Decode one run without coercing malformed persisted values."""
|
|
79
|
+
if not isinstance(data, dict):
|
|
80
|
+
raise ValueError("run must be a mapping")
|
|
81
|
+
require_keys(data, {"run_id", "workflow", "snapshot", "state"}, "run")
|
|
82
|
+
run_id = expect_string(data["run_id"], "run.run_id")
|
|
83
|
+
raw_items = data.get("items", [])
|
|
84
|
+
raw_children = data.get("children", [])
|
|
85
|
+
if not isinstance(raw_items, list):
|
|
86
|
+
raise ValueError("run.items must be a list")
|
|
87
|
+
if not isinstance(raw_children, list):
|
|
88
|
+
raise ValueError("run.children must be a list")
|
|
89
|
+
snapshot = _from_path(PlanSnapshot.from_dict, data["snapshot"], "run.snapshot")
|
|
90
|
+
state = _from_path(ExecutionState.from_dict, data["state"], "run.state")
|
|
91
|
+
if state.plan_digest is not None:
|
|
92
|
+
# The digest is derived from the plan stored beside it, and how a
|
|
93
|
+
# plan serializes depends on the ww version that wrote it: a
|
|
94
|
+
# field it knew and this one does not, or a default only one of
|
|
95
|
+
# them fills in. Re-derive it from this version's reading of the
|
|
96
|
+
# same plan, so state another version wrote keeps loading.
|
|
97
|
+
state = replace(state, plan_digest=snapshot.plan_digest)
|
|
98
|
+
return cls(
|
|
99
|
+
run_id=run_id,
|
|
100
|
+
workflow=expect_string(data["workflow"], "run.workflow"),
|
|
101
|
+
snapshot=snapshot,
|
|
102
|
+
state=state,
|
|
103
|
+
items=tuple(
|
|
104
|
+
_from_path(WorkItem.from_dict, item, f"run.items[{index}]")
|
|
105
|
+
for index, item in enumerate(raw_items)
|
|
106
|
+
),
|
|
107
|
+
children=tuple(
|
|
108
|
+
_from_path(ChildTask.from_dict, child, f"run.children[{index}]")
|
|
109
|
+
for index, child in enumerate(raw_children)
|
|
110
|
+
),
|
|
111
|
+
bootstrap_request_id=expect_optional_string(
|
|
112
|
+
data.get("bootstrap_request_id"), "run.bootstrap_request_id"
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@dataclass(frozen=True)
|
|
118
|
+
class PlanSnapshot:
|
|
119
|
+
"""A task-local plan revision plus its immutable compiled template."""
|
|
120
|
+
|
|
121
|
+
schema_version: int
|
|
122
|
+
compiler_version: str
|
|
123
|
+
configuration_digest: str
|
|
124
|
+
compiled_at: str
|
|
125
|
+
plan: WorkflowPlan
|
|
126
|
+
plan_revision: int = 1
|
|
127
|
+
template_plan: WorkflowPlan | None = None
|
|
128
|
+
# The step a bootstrap request already performed, which the plan omits;
|
|
129
|
+
# kept so a replan compiles the workflow the way the run started.
|
|
130
|
+
bootstrap_step: str | None = None
|
|
131
|
+
|
|
132
|
+
def __post_init__(self) -> None:
|
|
133
|
+
if self.template_plan is None:
|
|
134
|
+
object.__setattr__(self, "template_plan", self.plan)
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def plan_digest(self) -> str:
|
|
138
|
+
canonical = json.dumps(
|
|
139
|
+
self.plan.to_dict(), sort_keys=True, separators=(",", ":")
|
|
140
|
+
)
|
|
141
|
+
return hashlib.sha256(canonical.encode()).hexdigest()
|
|
142
|
+
|
|
143
|
+
def to_dict(self) -> dict[str, Any]:
|
|
144
|
+
template = self.template_plan if self.template_plan is not None else self.plan
|
|
145
|
+
return {
|
|
146
|
+
"schema_version": self.schema_version,
|
|
147
|
+
"compiler_version": self.compiler_version,
|
|
148
|
+
"configuration_digest": self.configuration_digest,
|
|
149
|
+
"compiled_at": self.compiled_at,
|
|
150
|
+
"plan": self.plan.to_dict(),
|
|
151
|
+
"plan_revision": self.plan_revision,
|
|
152
|
+
"template_plan": template.to_dict(),
|
|
153
|
+
**(
|
|
154
|
+
{"bootstrap_step": self.bootstrap_step}
|
|
155
|
+
if self.bootstrap_step is not None
|
|
156
|
+
else {}
|
|
157
|
+
),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def from_dict(cls, data: Any) -> PlanSnapshot:
|
|
162
|
+
if not isinstance(data, dict):
|
|
163
|
+
raise ValueError("plan snapshot must be a mapping")
|
|
164
|
+
required = {
|
|
165
|
+
"schema_version",
|
|
166
|
+
"compiler_version",
|
|
167
|
+
"configuration_digest",
|
|
168
|
+
"compiled_at",
|
|
169
|
+
"plan",
|
|
170
|
+
}
|
|
171
|
+
require_keys(data, required, "plan snapshot")
|
|
172
|
+
schema_version = data["schema_version"]
|
|
173
|
+
if not is_strict_int(schema_version) or schema_version != PLAN_SCHEMA_VERSION:
|
|
174
|
+
raise ValueError(f"unsupported plan snapshot schema: {schema_version!r}")
|
|
175
|
+
template = (
|
|
176
|
+
_plan_from_dict(data["template_plan"]) if "template_plan" in data else None
|
|
177
|
+
)
|
|
178
|
+
plan = _plan_from_dict(data["plan"])
|
|
179
|
+
return cls(
|
|
180
|
+
schema_version=schema_version,
|
|
181
|
+
compiler_version=expect_string(
|
|
182
|
+
data["compiler_version"], "compiler_version"
|
|
183
|
+
),
|
|
184
|
+
configuration_digest=expect_string(
|
|
185
|
+
data["configuration_digest"], "configuration_digest"
|
|
186
|
+
),
|
|
187
|
+
compiled_at=expect_string(data["compiled_at"], "compiled_at"),
|
|
188
|
+
plan=plan,
|
|
189
|
+
plan_revision=expect_positive_int(
|
|
190
|
+
data.get("plan_revision", 1), "plan snapshot.plan_revision"
|
|
191
|
+
),
|
|
192
|
+
template_plan=template if template is not None else plan,
|
|
193
|
+
bootstrap_step=expect_optional_string(
|
|
194
|
+
data.get("bootstrap_step"), "plan snapshot.bootstrap_step"
|
|
195
|
+
),
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def validate_task_runs(task_id: str, runs: tuple[TaskRunAggregate, ...]) -> None:
|
|
200
|
+
"""Reject an aggregate whose runs, plans, and records disagree.
|
|
201
|
+
|
|
202
|
+
Every storage adapter calls this on read and before commit, so the
|
|
203
|
+
invariants live with the model rather than being copied per backend.
|
|
204
|
+
"""
|
|
205
|
+
run_ids = [run.run_id for run in runs]
|
|
206
|
+
if len(run_ids) != len(set(run_ids)):
|
|
207
|
+
raise StateError(f"task {task_id!r} aggregate has duplicate run IDs")
|
|
208
|
+
if sum(run_is_open(run.state.status) for run in runs) > 1:
|
|
209
|
+
raise StateError(f"task {task_id!r} aggregate has multiple active runs")
|
|
210
|
+
for run in runs:
|
|
211
|
+
_validate_run(task_id, run)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _validate_run(task_id: str, run: TaskRunAggregate) -> None:
|
|
215
|
+
state, plan = run.state, run.snapshot.plan
|
|
216
|
+
if state.task_id != task_id or state.run_id != run.run_id:
|
|
217
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched run identity")
|
|
218
|
+
if plan.task_id != task_id:
|
|
219
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched plan task ID")
|
|
220
|
+
binding = run.bootstrap_request_id
|
|
221
|
+
if binding is not None and not binding.startswith(BOOTSTRAP_REQUEST_PREFIX):
|
|
222
|
+
raise StateError(f"task {task_id!r} aggregate has invalid bootstrap binding")
|
|
223
|
+
if state.workflow != run.workflow or plan.workflow != run.workflow:
|
|
224
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched workflow identity")
|
|
225
|
+
if (
|
|
226
|
+
state.agent != plan.agent
|
|
227
|
+
or state.snapshot_digest != run.snapshot.configuration_digest
|
|
228
|
+
):
|
|
229
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched plan identity")
|
|
230
|
+
if state.plan_revision != run.snapshot.plan_revision:
|
|
231
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched plan revision")
|
|
232
|
+
if state.plan_digest is not None and state.plan_digest != run.snapshot.plan_digest:
|
|
233
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched plan digest")
|
|
234
|
+
if len(state.item_executions) != len(plan.items):
|
|
235
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched plan/state")
|
|
236
|
+
if not 0 <= state.cursor <= len(plan.items):
|
|
237
|
+
raise StateError(f"task {task_id!r} aggregate has invalid cursor")
|
|
238
|
+
item_ids = [item.id for item in plan.items]
|
|
239
|
+
if len(item_ids) != len(set(item_ids)) or any(
|
|
240
|
+
item.position != position for position, item in enumerate(plan.items, 1)
|
|
241
|
+
):
|
|
242
|
+
raise StateError(f"task {task_id!r} aggregate has invalid plan identity")
|
|
243
|
+
for item, record in zip(plan.items, state.item_executions, strict=True):
|
|
244
|
+
if item.id != record.plan_item_id or item.position != record.position:
|
|
245
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched item identity")
|
|
246
|
+
expected = _expected_command_count(item)
|
|
247
|
+
if expected is not None and expected != len(record.commands):
|
|
248
|
+
raise StateError(f"task {task_id!r} aggregate has mismatched commands")
|
|
249
|
+
if any(
|
|
250
|
+
command.index != index for index, command in enumerate(record.commands, 1)
|
|
251
|
+
):
|
|
252
|
+
raise StateError(f"task {task_id!r} aggregate has invalid command index")
|
|
253
|
+
if state.active_item_id is not None and (
|
|
254
|
+
state.cursor >= len(plan.items)
|
|
255
|
+
or plan.items[state.cursor].id != state.active_item_id
|
|
256
|
+
):
|
|
257
|
+
raise StateError(f"task {task_id!r} aggregate has an invalid active item")
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _expected_command_count(item: PlanItem) -> int | None:
|
|
261
|
+
"""Return how many command records the item's action declares, if known."""
|
|
262
|
+
if not isinstance(item.operation, PlannedAction) or not actions.contains(item.kind):
|
|
263
|
+
return None
|
|
264
|
+
implementation = actions.get(item.kind)
|
|
265
|
+
traits = implementation.traits(item.payload_as(implementation.planned_type))
|
|
266
|
+
return len(traits.command_segments or ())
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
"""Pluggable extensions: handlers, modes, and commands from other vendors."""
|
|
3
|
+
|
|
4
|
+
from ww.extensions.api import (
|
|
5
|
+
EXTENSION_API_VERSION,
|
|
6
|
+
Extension,
|
|
7
|
+
ExtensionCheckResult,
|
|
8
|
+
ExtensionCommand,
|
|
9
|
+
ExtensionContext,
|
|
10
|
+
ExtensionHandler,
|
|
11
|
+
ExtensionNamespace,
|
|
12
|
+
ExtensionResult,
|
|
13
|
+
ExtensionVariable,
|
|
14
|
+
RuleGroupContribution,
|
|
15
|
+
)
|
|
16
|
+
from ww.extensions.registry import (
|
|
17
|
+
ExtensionReference,
|
|
18
|
+
ExtensionRegistry,
|
|
19
|
+
is_extension_reference,
|
|
20
|
+
parse_reference,
|
|
21
|
+
)
|
|
22
|
+
from ww.extensions.store import ExtensionStore
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"EXTENSION_API_VERSION",
|
|
26
|
+
"Extension",
|
|
27
|
+
"ExtensionCommand",
|
|
28
|
+
"ExtensionContext",
|
|
29
|
+
"ExtensionCheckResult",
|
|
30
|
+
"ExtensionHandler",
|
|
31
|
+
"ExtensionNamespace",
|
|
32
|
+
"ExtensionReference",
|
|
33
|
+
"ExtensionRegistry",
|
|
34
|
+
"ExtensionResult",
|
|
35
|
+
"ExtensionVariable",
|
|
36
|
+
"ExtensionStore",
|
|
37
|
+
"RuleGroupContribution",
|
|
38
|
+
"is_extension_reference",
|
|
39
|
+
"parse_reference",
|
|
40
|
+
]
|