whiletrue 0.1.0__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.
- whiletrue/__init__.py +0 -0
- whiletrue/__main__.py +3 -0
- whiletrue/abort.py +79 -0
- whiletrue/basics/__init__.py +99 -0
- whiletrue/basics/agent.py +249 -0
- whiletrue/basics/comments.py +113 -0
- whiletrue/basics/diff_size.py +80 -0
- whiletrue/basics/exec_.py +84 -0
- whiletrue/basics/history.py +117 -0
- whiletrue/basics/human.py +201 -0
- whiletrue/basics/json_source.py +35 -0
- whiletrue/basics/markdown_source.py +55 -0
- whiletrue/basics/process.py +99 -0
- whiletrue/basics/sessions.py +62 -0
- whiletrue/basics/set_.py +29 -0
- whiletrue/basics/shell.py +98 -0
- whiletrue/basics/wake.py +27 -0
- whiletrue/claude_code/__init__.py +58 -0
- whiletrue/claude_code/endpoint.py +143 -0
- whiletrue/claude_code/headless.py +181 -0
- whiletrue/claude_code/interactive.py +344 -0
- whiletrue/claude_code/learnings.py +32 -0
- whiletrue/claude_code/panes.py +164 -0
- whiletrue/claude_code/plugin/.claude-plugin/plugin.json +5 -0
- whiletrue/claude_code/plugin/hook.py +44 -0
- whiletrue/claude_code/plugin/hooks/hooks.json +81 -0
- whiletrue/claude_code/plugin/mcp_server.py +98 -0
- whiletrue/claude_code/session.py +345 -0
- whiletrue/claude_code/transcript.py +123 -0
- whiletrue/cli/__init__.py +15 -0
- whiletrue/cli/__main__.py +3 -0
- whiletrue/cli/app.py +550 -0
- whiletrue/cli/common.py +36 -0
- whiletrue/cli/gates.py +156 -0
- whiletrue/cli/ops.py +339 -0
- whiletrue/cli/panel.py +198 -0
- whiletrue/cli/registry.py +143 -0
- whiletrue/cli/templates.py +24 -0
- whiletrue/codex/__init__.py +14 -0
- whiletrue/codex/runner.py +243 -0
- whiletrue/control/__init__.py +38 -0
- whiletrue/control/chain.py +61 -0
- whiletrue/control/loop.py +139 -0
- whiletrue/control/map_.py +101 -0
- whiletrue/control/parallel.py +32 -0
- whiletrue/control/retry.py +100 -0
- whiletrue/control/sequence.py +40 -0
- whiletrue/control/switch.py +67 -0
- whiletrue/core/__init__.py +260 -0
- whiletrue/core/caps.py +139 -0
- whiletrue/core/comments.py +80 -0
- whiletrue/core/composite.py +140 -0
- whiletrue/core/config.py +461 -0
- whiletrue/core/context.py +177 -0
- whiletrue/core/duration.py +19 -0
- whiletrue/core/events.py +94 -0
- whiletrue/core/expr.py +85 -0
- whiletrue/core/history.py +83 -0
- whiletrue/core/lock.py +86 -0
- whiletrue/core/memory_store.py +352 -0
- whiletrue/core/module.py +146 -0
- whiletrue/core/outcomes.py +82 -0
- whiletrue/core/registry.py +129 -0
- whiletrue/core/replay.py +58 -0
- whiletrue/core/runner.py +98 -0
- whiletrue/core/runtime.py +538 -0
- whiletrue/core/source.py +45 -0
- whiletrue/core/store.py +207 -0
- whiletrue/core/template.py +60 -0
- whiletrue/core/validate.py +142 -0
- whiletrue/core/wake.py +117 -0
- whiletrue/core/workspace.py +55 -0
- whiletrue/git/__init__.py +31 -0
- whiletrue/git/modules.py +128 -0
- whiletrue/git/workspaces.py +77 -0
- whiletrue/github/__init__.py +30 -0
- whiletrue/github/client.py +269 -0
- whiletrue/github/filebacked.py +87 -0
- whiletrue/github/memory.py +96 -0
- whiletrue/github/plugin.py +343 -0
- whiletrue/github/specs.py +39 -0
- whiletrue/opencode/__init__.py +25 -0
- whiletrue/opencode/runner.py +186 -0
- whiletrue/py.typed +0 -0
- whiletrue/recipes/issue-loop.yaml +59 -0
- whiletrue/recipes/ralph.yaml +14 -0
- whiletrue/recipes/review-pass.yaml +27 -0
- whiletrue/recipes/review-respond.yaml +22 -0
- whiletrue/store_sqlite/__init__.py +6 -0
- whiletrue/store_sqlite/migrations.py +132 -0
- whiletrue/store_sqlite/sqlite_store.py +537 -0
- whiletrue/tmux/__init__.py +11 -0
- whiletrue/tmux/controller.py +197 -0
- whiletrue-0.1.0.dist-info/METADATA +48 -0
- whiletrue-0.1.0.dist-info/RECORD +98 -0
- whiletrue-0.1.0.dist-info/WHEEL +4 -0
- whiletrue-0.1.0.dist-info/entry_points.txt +2 -0
- whiletrue-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import Any, cast
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from whiletrue.control.chain import run_chain
|
|
9
|
+
from whiletrue.core import (
|
|
10
|
+
CompositeContext,
|
|
11
|
+
ConfigIssue,
|
|
12
|
+
Emit,
|
|
13
|
+
PipelineNode,
|
|
14
|
+
Strategy,
|
|
15
|
+
ValidateContext,
|
|
16
|
+
define_strategy,
|
|
17
|
+
parse_expr,
|
|
18
|
+
)
|
|
19
|
+
from whiletrue.core.expr import ExprError
|
|
20
|
+
from whiletrue.core.module import PortValues
|
|
21
|
+
|
|
22
|
+
#: Variables a `map`/`switch` expression may use.
|
|
23
|
+
EXPR_VARIABLES = frozenset({"run", "item", "iter", "input"})
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MapConfig(BaseModel):
|
|
27
|
+
#: CEL expression yielding a list. Each element is `iter.value` for one pass over the children.
|
|
28
|
+
over: str = Field(min_length=1)
|
|
29
|
+
#: How many elements run at once (each pass gets its own `iter`). Results keep element order.
|
|
30
|
+
parallel: int = Field(default=1, ge=1)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def check_expr(name: str, source: str) -> list[ConfigIssue]:
|
|
34
|
+
try:
|
|
35
|
+
problems = parse_expr(source).check(EXPR_VARIABLES)
|
|
36
|
+
except ExprError as error:
|
|
37
|
+
problems = [str(error)]
|
|
38
|
+
return [ConfigIssue("error", f"`{name}`: {p}") for p in problems]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _validate(config: MapConfig, _vctx: ValidateContext) -> list[ConfigIssue]:
|
|
42
|
+
return check_expr("map.over", config.over)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def _run(
|
|
46
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[MapConfig]
|
|
47
|
+
) -> Emit:
|
|
48
|
+
scope = {**ctx.scope.snapshot(), "input": input.get("in")}
|
|
49
|
+
values = parse_expr(ctx.config.over).eval(scope)
|
|
50
|
+
if not isinstance(values, list):
|
|
51
|
+
return Emit("fail", {"error": f"`map.over` must be a list, got {type(values).__name__}"})
|
|
52
|
+
elements = cast(list[Any], values)
|
|
53
|
+
if ctx.config.parallel > 1:
|
|
54
|
+
return await _run_parallel(children, input, ctx, elements)
|
|
55
|
+
results: list[Any] = []
|
|
56
|
+
for index, value in enumerate(elements, start=1):
|
|
57
|
+
if ctx.signal.aborted:
|
|
58
|
+
return Emit("fail", {"error": "cancelled"})
|
|
59
|
+
ctx.scope.set("iter", {"index": index, "value": value, "previous": ""})
|
|
60
|
+
emit = await run_chain(children, input, ctx)
|
|
61
|
+
if emit.port != "ok":
|
|
62
|
+
return emit
|
|
63
|
+
results.append(emit.value)
|
|
64
|
+
return Emit("ok", results)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def _run_parallel(
|
|
68
|
+
children: list[PipelineNode],
|
|
69
|
+
input: PortValues,
|
|
70
|
+
ctx: CompositeContext[MapConfig],
|
|
71
|
+
elements: list[Any],
|
|
72
|
+
) -> Emit:
|
|
73
|
+
slots = asyncio.Semaphore(ctx.config.parallel)
|
|
74
|
+
stop = asyncio.Event()
|
|
75
|
+
|
|
76
|
+
async def one(index: int, value: Any) -> Emit | None:
|
|
77
|
+
async with slots:
|
|
78
|
+
if stop.is_set() or ctx.signal.aborted:
|
|
79
|
+
return None
|
|
80
|
+
scope = ctx.scope.child()
|
|
81
|
+
scope.set("iter", {"index": index, "value": value, "previous": ""})
|
|
82
|
+
emit = await run_chain(children, input, ctx, scope)
|
|
83
|
+
if emit.port != "ok":
|
|
84
|
+
stop.set()
|
|
85
|
+
return emit
|
|
86
|
+
|
|
87
|
+
emits = await asyncio.gather(*(one(i, v) for i, v in enumerate(elements, start=1)))
|
|
88
|
+
for emit in emits:
|
|
89
|
+
if emit is not None and emit.port != "ok":
|
|
90
|
+
return emit
|
|
91
|
+
if any(e is None for e in emits):
|
|
92
|
+
return Emit("fail", {"error": "cancelled"})
|
|
93
|
+
return Emit("ok", [e.value for e in emits if e is not None])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
#: Runs the children once per element of `over` (one after another, or `parallel` at once) and
|
|
97
|
+
#: returns the list of results.
|
|
98
|
+
#: The first element that doesn't succeed stops the map and its outcome is returned.
|
|
99
|
+
map_strategy: Strategy[Any] = define_strategy(
|
|
100
|
+
Strategy(id="map", config=MapConfig, validate=_validate, run=_run)
|
|
101
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from whiletrue.core import (
|
|
7
|
+
CompositeContext,
|
|
8
|
+
Emit,
|
|
9
|
+
EmptyConfig,
|
|
10
|
+
PipelineNode,
|
|
11
|
+
Strategy,
|
|
12
|
+
define_strategy,
|
|
13
|
+
resolve_outcome,
|
|
14
|
+
)
|
|
15
|
+
from whiletrue.core.module import PortValues
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def _run(
|
|
19
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[EmptyConfig]
|
|
20
|
+
) -> Emit:
|
|
21
|
+
emits = await asyncio.gather(*(ctx.run(child, input) for child in children))
|
|
22
|
+
for emit in emits:
|
|
23
|
+
if resolve_outcome(emit.port, {}, ctx.policy).action != "continue":
|
|
24
|
+
return emit
|
|
25
|
+
return Emit("ok", [emit.value for emit in emits])
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#: Runs every child at the same time on the same input and returns the list of their results in
|
|
29
|
+
#: order. If any child doesn't succeed, the first such outcome (in child order) is returned.
|
|
30
|
+
parallel_strategy: Strategy[Any] = define_strategy(
|
|
31
|
+
Strategy(id="parallel", config=EmptyConfig, run=_run)
|
|
32
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import Any, Literal
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, PositiveFloat, PositiveInt
|
|
7
|
+
|
|
8
|
+
from whiletrue.control.chain import run_chain
|
|
9
|
+
from whiletrue.control.loop import describe
|
|
10
|
+
from whiletrue.core import (
|
|
11
|
+
CompositeContext,
|
|
12
|
+
ConfigIssue,
|
|
13
|
+
Emit,
|
|
14
|
+
PipelineNode,
|
|
15
|
+
Strategy,
|
|
16
|
+
ValidateContext,
|
|
17
|
+
define_strategy,
|
|
18
|
+
parse_duration,
|
|
19
|
+
)
|
|
20
|
+
from whiletrue.core.module import PortValues
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class RetryConfig(BaseModel):
|
|
24
|
+
max: PositiveInt = 3
|
|
25
|
+
#: Delay before the second attempt, e.g. "2s". Grows by `factor` each further attempt.
|
|
26
|
+
backoff: str | int | float | None = None
|
|
27
|
+
factor: PositiveFloat = 1.0
|
|
28
|
+
#: Expose the previous failure as `{{iter.previous}}` to the next attempt.
|
|
29
|
+
feedback: bool = True
|
|
30
|
+
#: What happens when every attempt failed. Default: park the item for a human.
|
|
31
|
+
on_exhausted: Literal["needs_human", "fail"] = "needs_human"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _validate(config: RetryConfig, _vctx: ValidateContext) -> list[ConfigIssue]:
|
|
35
|
+
if config.backoff is None:
|
|
36
|
+
return []
|
|
37
|
+
try:
|
|
38
|
+
parse_duration(config.backoff)
|
|
39
|
+
except ValueError as error:
|
|
40
|
+
return [ConfigIssue("error", f"`retry.backoff`: {error}")]
|
|
41
|
+
return []
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def _sleep(ctx: CompositeContext[Any], ms: float) -> None:
|
|
45
|
+
if ms <= 0:
|
|
46
|
+
return
|
|
47
|
+
waiter = asyncio.ensure_future(ctx.signal.wait())
|
|
48
|
+
try:
|
|
49
|
+
await asyncio.wait({waiter}, timeout=ms / 1000)
|
|
50
|
+
finally:
|
|
51
|
+
waiter.cancel()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def _run(
|
|
55
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[RetryConfig]
|
|
56
|
+
) -> Emit:
|
|
57
|
+
cfg = ctx.config
|
|
58
|
+
delay = parse_duration(cfg.backoff) if cfg.backoff is not None else 0
|
|
59
|
+
last = Emit("ok")
|
|
60
|
+
for attempt in range(1, cfg.max + 1):
|
|
61
|
+
if ctx.signal.aborted:
|
|
62
|
+
return Emit("fail", {"error": "cancelled"})
|
|
63
|
+
previous = describe(last.value) if cfg.feedback and attempt > 1 else ""
|
|
64
|
+
ctx.scope.set("iter", {"index": attempt, "previous": previous, "value": None})
|
|
65
|
+
last = await run_chain(children, input, ctx)
|
|
66
|
+
if last.port != "fail":
|
|
67
|
+
return last
|
|
68
|
+
ctx.log("warn", f"retry attempt {attempt}/{cfg.max} failed", None)
|
|
69
|
+
if attempt < cfg.max:
|
|
70
|
+
await _sleep(ctx, delay * cfg.factor ** (attempt - 1))
|
|
71
|
+
error = {"error": f"retry gave up after {cfg.max} attempts", "last": last.value}
|
|
72
|
+
return Emit(cfg.on_exhausted, error)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#: Re-runs its children when they `fail`, up to `max` attempts, with optional backoff. Other
|
|
76
|
+
#: outcomes pass straight through. When attempts run out, the item is parked as `needs_human`
|
|
77
|
+
#: (or `fail` with `on_exhausted: fail`).
|
|
78
|
+
retry_strategy: Strategy[Any] = define_strategy(
|
|
79
|
+
Strategy(id="retry", config=RetryConfig, validate=_validate, run=_run)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class TryConfig(BaseModel):
|
|
84
|
+
#: Outcome to fire instead of `fail`: `skip` carries on with the previous value, `ok` yields
|
|
85
|
+
#: the error object as the value.
|
|
86
|
+
emit: Literal["skip", "ok"] = "skip"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
async def _try(
|
|
90
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[TryConfig]
|
|
91
|
+
) -> Emit:
|
|
92
|
+
result = await run_chain(children, input, ctx)
|
|
93
|
+
if result.port != "fail" or ctx.signal.aborted:
|
|
94
|
+
return result
|
|
95
|
+
ctx.log("warn", "try swallowed a failure", {"error": describe(result.value)})
|
|
96
|
+
return Emit("ok", result.value) if ctx.config.emit == "ok" else Emit("skip")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
#: Runs its children and turns a `fail` into `skip` (or `ok`) so optional steps never stop the item.
|
|
100
|
+
try_strategy: Strategy[Any] = define_strategy(Strategy(id="try", config=TryConfig, run=_try))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from whiletrue.control.chain import run_chain
|
|
6
|
+
from whiletrue.core import (
|
|
7
|
+
CompositeContext,
|
|
8
|
+
Emit,
|
|
9
|
+
EmptyConfig,
|
|
10
|
+
PipelineNode,
|
|
11
|
+
Strategy,
|
|
12
|
+
define_strategy,
|
|
13
|
+
)
|
|
14
|
+
from whiletrue.core.module import PortValues
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def _run(
|
|
18
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[EmptyConfig]
|
|
19
|
+
) -> Emit:
|
|
20
|
+
return await run_chain(children, input, ctx)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#: Runs children one after another; each `out` feeds the next `in`.
|
|
24
|
+
sequence_strategy: Strategy[Any] = define_strategy(
|
|
25
|
+
Strategy(id="sequence", chain=True, config=EmptyConfig, run=_run)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def _tap(
|
|
30
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[EmptyConfig]
|
|
31
|
+
) -> Emit:
|
|
32
|
+
emit = await run_chain(children, input, ctx)
|
|
33
|
+
# On success the original input flows on, so a side branch (a fix) does not replace it.
|
|
34
|
+
return Emit("ok", input.get("in")) if emit.port == "ok" else emit
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
#: Runs children like `sequence`, then passes its own input through unchanged.
|
|
38
|
+
tap_strategy: Strategy[Any] = define_strategy(
|
|
39
|
+
Strategy(id="tap", chain=True, config=EmptyConfig, run=_tap)
|
|
40
|
+
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from whiletrue.control.map_ import check_expr
|
|
9
|
+
from whiletrue.core import (
|
|
10
|
+
CompositeContext,
|
|
11
|
+
ConfigIssue,
|
|
12
|
+
Emit,
|
|
13
|
+
PipelineNode,
|
|
14
|
+
Strategy,
|
|
15
|
+
ValidateContext,
|
|
16
|
+
define_strategy,
|
|
17
|
+
parse_expr,
|
|
18
|
+
)
|
|
19
|
+
from whiletrue.core.module import PortValues
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SwitchConfig(BaseModel):
|
|
23
|
+
#: CEL expression; its value (strings as-is, anything else as JSON) selects a case.
|
|
24
|
+
on: str = Field(min_length=1)
|
|
25
|
+
#: Case value -> id of a child step.
|
|
26
|
+
cases: dict[str, str] = Field(default_factory=lambda: {})
|
|
27
|
+
#: Child step id used when no case matches. Without it, no match fires `skip`.
|
|
28
|
+
default: str | None = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _validate(config: SwitchConfig, _vctx: ValidateContext) -> list[ConfigIssue]:
|
|
32
|
+
return check_expr("switch.on", config.on)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _validate_node(
|
|
36
|
+
config: SwitchConfig, node: PipelineNode, _vctx: ValidateContext
|
|
37
|
+
) -> list[ConfigIssue]:
|
|
38
|
+
ids = {c.id for c in node.children}
|
|
39
|
+
targets = [*config.cases.items(), *([("default", config.default)] if config.default else [])]
|
|
40
|
+
return [
|
|
41
|
+
ConfigIssue("error", f'`switch` case "{case}" targets unknown step "{target}"')
|
|
42
|
+
for case, target in targets
|
|
43
|
+
if target not in ids
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _key(value: Any) -> str:
|
|
48
|
+
return value if isinstance(value, str) else json.dumps(value, separators=(",", ":"))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def _run(
|
|
52
|
+
children: list[PipelineNode], input: PortValues, ctx: CompositeContext[SwitchConfig]
|
|
53
|
+
) -> Emit:
|
|
54
|
+
value = parse_expr(ctx.config.on).eval({**ctx.scope.snapshot(), "input": input.get("in")})
|
|
55
|
+
target = ctx.config.cases.get(_key(value), ctx.config.default)
|
|
56
|
+
child = next((c for c in children if c.id == target), None)
|
|
57
|
+
if child is None:
|
|
58
|
+
return Emit("skip")
|
|
59
|
+
return await ctx.run(child, input)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
#: Runs exactly one child, chosen by evaluating `on` and looking it up in `cases`.
|
|
63
|
+
switch_strategy: Strategy[Any] = define_strategy(
|
|
64
|
+
Strategy(
|
|
65
|
+
id="switch", config=SwitchConfig, validate=_validate, validate_node=_validate_node, run=_run
|
|
66
|
+
)
|
|
67
|
+
)
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""whiletrue core: module/port/cap model, config, validation, runtime. Imports no agent or VCS."""
|
|
2
|
+
|
|
3
|
+
from whiletrue.abort import AbortSignal
|
|
4
|
+
from whiletrue.core.caps import CapError, CapRegistry, CapValidation, create_builtin_caps
|
|
5
|
+
from whiletrue.core.comments import (
|
|
6
|
+
REPLY_PREFIX,
|
|
7
|
+
CommentsContext,
|
|
8
|
+
CommentsProvider,
|
|
9
|
+
IncomingComment,
|
|
10
|
+
sync_comments,
|
|
11
|
+
with_prefix,
|
|
12
|
+
)
|
|
13
|
+
from whiletrue.core.composite import expand_composites
|
|
14
|
+
from whiletrue.core.config import (
|
|
15
|
+
AgentDefinition,
|
|
16
|
+
CompositeDefinition,
|
|
17
|
+
ConfigError,
|
|
18
|
+
ParamSpec,
|
|
19
|
+
PipelineConfig,
|
|
20
|
+
PipelineNode,
|
|
21
|
+
SourceLoc,
|
|
22
|
+
load_agent_definition,
|
|
23
|
+
load_composite,
|
|
24
|
+
load_pipeline,
|
|
25
|
+
parse_agent_definition,
|
|
26
|
+
parse_composite,
|
|
27
|
+
parse_pipeline,
|
|
28
|
+
)
|
|
29
|
+
from whiletrue.core.context import (
|
|
30
|
+
CompositeContext,
|
|
31
|
+
Locks,
|
|
32
|
+
Resource,
|
|
33
|
+
Scope,
|
|
34
|
+
StepContext,
|
|
35
|
+
create_step_context,
|
|
36
|
+
)
|
|
37
|
+
from whiletrue.core.duration import parse_duration
|
|
38
|
+
from whiletrue.core.events import EventBus, WtEvent
|
|
39
|
+
from whiletrue.core.expr import Expr, ExprError, parse_expr
|
|
40
|
+
from whiletrue.core.history import (
|
|
41
|
+
CommentRecord,
|
|
42
|
+
Decision,
|
|
43
|
+
EffectRecord,
|
|
44
|
+
LearningRecord,
|
|
45
|
+
LearningStatus,
|
|
46
|
+
ParkRecord,
|
|
47
|
+
SteerRecord,
|
|
48
|
+
)
|
|
49
|
+
from whiletrue.core.lock import (
|
|
50
|
+
LOCK_FILE,
|
|
51
|
+
LockError,
|
|
52
|
+
check_lock,
|
|
53
|
+
collect_file_hashes,
|
|
54
|
+
read_lock,
|
|
55
|
+
sha256_file,
|
|
56
|
+
write_lock,
|
|
57
|
+
)
|
|
58
|
+
from whiletrue.core.memory_store import MemoryStore
|
|
59
|
+
from whiletrue.core.module import (
|
|
60
|
+
EFFECTS,
|
|
61
|
+
ActionModule,
|
|
62
|
+
ConfigIssue,
|
|
63
|
+
Effect,
|
|
64
|
+
Emit,
|
|
65
|
+
EmptyConfig,
|
|
66
|
+
ModuleDefinitionError,
|
|
67
|
+
Ports,
|
|
68
|
+
PortSpec,
|
|
69
|
+
Strategy,
|
|
70
|
+
ValidateContext,
|
|
71
|
+
define_action,
|
|
72
|
+
define_strategy,
|
|
73
|
+
is_effect,
|
|
74
|
+
)
|
|
75
|
+
from whiletrue.core.outcomes import (
|
|
76
|
+
OUTCOME_PORTS,
|
|
77
|
+
InvalidTransition,
|
|
78
|
+
ItemState,
|
|
79
|
+
OnFail,
|
|
80
|
+
OutcomePolicy,
|
|
81
|
+
Resolution,
|
|
82
|
+
can_transition,
|
|
83
|
+
is_outcome_port,
|
|
84
|
+
item_state_for,
|
|
85
|
+
resolve_outcome,
|
|
86
|
+
transition,
|
|
87
|
+
)
|
|
88
|
+
from whiletrue.core.registry import Plugin, PluginApi, Registry, RegistryError, SimplePlugin
|
|
89
|
+
from whiletrue.core.replay import Recording, ReplayData, ReplayError, load_recording
|
|
90
|
+
from whiletrue.core.runner import (
|
|
91
|
+
AgentLimits,
|
|
92
|
+
AgentRequest,
|
|
93
|
+
AgentResult,
|
|
94
|
+
RunContext,
|
|
95
|
+
Runner,
|
|
96
|
+
RunnerCapabilities,
|
|
97
|
+
)
|
|
98
|
+
from whiletrue.core.runtime import (
|
|
99
|
+
ItemOutcome,
|
|
100
|
+
RunItem,
|
|
101
|
+
RunResult,
|
|
102
|
+
find_dependency_cycles,
|
|
103
|
+
hash_pipeline,
|
|
104
|
+
run_pipeline,
|
|
105
|
+
)
|
|
106
|
+
from whiletrue.core.source import SourceError, SourceProvider, fetch_items, source_spec
|
|
107
|
+
from whiletrue.core.store import (
|
|
108
|
+
ItemRecord,
|
|
109
|
+
RunRecord,
|
|
110
|
+
StateStore,
|
|
111
|
+
StepRecord,
|
|
112
|
+
)
|
|
113
|
+
from whiletrue.core.template import TemplateError, render_deep, render_template
|
|
114
|
+
from whiletrue.core.validate import Diagnostic, format_diagnostic, has_errors, validate_pipeline
|
|
115
|
+
from whiletrue.core.wake import (
|
|
116
|
+
WakeChecker,
|
|
117
|
+
WakeCondition,
|
|
118
|
+
WakeContext,
|
|
119
|
+
WakeResult,
|
|
120
|
+
WakeSpec,
|
|
121
|
+
evaluate_wake,
|
|
122
|
+
parse_wake,
|
|
123
|
+
wake_to_dict,
|
|
124
|
+
)
|
|
125
|
+
from whiletrue.core.workspace import (
|
|
126
|
+
Workspace,
|
|
127
|
+
WorkspaceError,
|
|
128
|
+
WorkspaceProvider,
|
|
129
|
+
resolve_workspace,
|
|
130
|
+
workspace_spec,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
__all__ = [
|
|
134
|
+
"EFFECTS",
|
|
135
|
+
"LOCK_FILE",
|
|
136
|
+
"OUTCOME_PORTS",
|
|
137
|
+
"REPLY_PREFIX",
|
|
138
|
+
"AbortSignal",
|
|
139
|
+
"ActionModule",
|
|
140
|
+
"AgentDefinition",
|
|
141
|
+
"AgentLimits",
|
|
142
|
+
"AgentRequest",
|
|
143
|
+
"AgentResult",
|
|
144
|
+
"CapError",
|
|
145
|
+
"CapRegistry",
|
|
146
|
+
"CapValidation",
|
|
147
|
+
"CommentRecord",
|
|
148
|
+
"CommentsContext",
|
|
149
|
+
"CommentsProvider",
|
|
150
|
+
"CompositeContext",
|
|
151
|
+
"CompositeDefinition",
|
|
152
|
+
"ConfigError",
|
|
153
|
+
"ConfigIssue",
|
|
154
|
+
"Decision",
|
|
155
|
+
"Diagnostic",
|
|
156
|
+
"Effect",
|
|
157
|
+
"EffectRecord",
|
|
158
|
+
"Emit",
|
|
159
|
+
"EmptyConfig",
|
|
160
|
+
"EventBus",
|
|
161
|
+
"Expr",
|
|
162
|
+
"ExprError",
|
|
163
|
+
"IncomingComment",
|
|
164
|
+
"InvalidTransition",
|
|
165
|
+
"ItemOutcome",
|
|
166
|
+
"ItemRecord",
|
|
167
|
+
"ItemState",
|
|
168
|
+
"LearningRecord",
|
|
169
|
+
"LearningStatus",
|
|
170
|
+
"LockError",
|
|
171
|
+
"Locks",
|
|
172
|
+
"MemoryStore",
|
|
173
|
+
"ModuleDefinitionError",
|
|
174
|
+
"OnFail",
|
|
175
|
+
"OutcomePolicy",
|
|
176
|
+
"ParamSpec",
|
|
177
|
+
"ParkRecord",
|
|
178
|
+
"PipelineConfig",
|
|
179
|
+
"PipelineNode",
|
|
180
|
+
"Plugin",
|
|
181
|
+
"PluginApi",
|
|
182
|
+
"PortSpec",
|
|
183
|
+
"Ports",
|
|
184
|
+
"Recording",
|
|
185
|
+
"Registry",
|
|
186
|
+
"RegistryError",
|
|
187
|
+
"ReplayData",
|
|
188
|
+
"ReplayError",
|
|
189
|
+
"Resolution",
|
|
190
|
+
"Resource",
|
|
191
|
+
"RunContext",
|
|
192
|
+
"RunItem",
|
|
193
|
+
"RunRecord",
|
|
194
|
+
"RunResult",
|
|
195
|
+
"Runner",
|
|
196
|
+
"RunnerCapabilities",
|
|
197
|
+
"Scope",
|
|
198
|
+
"SimplePlugin",
|
|
199
|
+
"SourceError",
|
|
200
|
+
"SourceLoc",
|
|
201
|
+
"SourceProvider",
|
|
202
|
+
"StateStore",
|
|
203
|
+
"SteerRecord",
|
|
204
|
+
"StepContext",
|
|
205
|
+
"StepRecord",
|
|
206
|
+
"Strategy",
|
|
207
|
+
"TemplateError",
|
|
208
|
+
"ValidateContext",
|
|
209
|
+
"WakeChecker",
|
|
210
|
+
"WakeCondition",
|
|
211
|
+
"WakeContext",
|
|
212
|
+
"WakeResult",
|
|
213
|
+
"WakeSpec",
|
|
214
|
+
"Workspace",
|
|
215
|
+
"WorkspaceError",
|
|
216
|
+
"WorkspaceProvider",
|
|
217
|
+
"WtEvent",
|
|
218
|
+
"can_transition",
|
|
219
|
+
"check_lock",
|
|
220
|
+
"collect_file_hashes",
|
|
221
|
+
"create_builtin_caps",
|
|
222
|
+
"create_step_context",
|
|
223
|
+
"define_action",
|
|
224
|
+
"define_strategy",
|
|
225
|
+
"evaluate_wake",
|
|
226
|
+
"expand_composites",
|
|
227
|
+
"fetch_items",
|
|
228
|
+
"find_dependency_cycles",
|
|
229
|
+
"format_diagnostic",
|
|
230
|
+
"has_errors",
|
|
231
|
+
"hash_pipeline",
|
|
232
|
+
"is_effect",
|
|
233
|
+
"is_outcome_port",
|
|
234
|
+
"item_state_for",
|
|
235
|
+
"load_agent_definition",
|
|
236
|
+
"load_composite",
|
|
237
|
+
"load_pipeline",
|
|
238
|
+
"load_recording",
|
|
239
|
+
"parse_agent_definition",
|
|
240
|
+
"parse_composite",
|
|
241
|
+
"parse_duration",
|
|
242
|
+
"parse_expr",
|
|
243
|
+
"parse_pipeline",
|
|
244
|
+
"parse_wake",
|
|
245
|
+
"read_lock",
|
|
246
|
+
"render_deep",
|
|
247
|
+
"render_template",
|
|
248
|
+
"resolve_outcome",
|
|
249
|
+
"resolve_workspace",
|
|
250
|
+
"run_pipeline",
|
|
251
|
+
"sha256_file",
|
|
252
|
+
"source_spec",
|
|
253
|
+
"sync_comments",
|
|
254
|
+
"transition",
|
|
255
|
+
"validate_pipeline",
|
|
256
|
+
"wake_to_dict",
|
|
257
|
+
"with_prefix",
|
|
258
|
+
"workspace_spec",
|
|
259
|
+
"write_lock",
|
|
260
|
+
]
|