Skip to content

Loading search…

中文

Tick and entries

Observe, judge the rules and deliver one worker command per control period.

The tick exists while an execution or a rule on time needs it, and not otherwise: nothing is driven by time unless a unit asks for it. Single-resource executions take turns and receive the receipts for their own commands. With channels, executions advance concurrently, merging their inputs with what units hold before local admission. Delayed actions retain their admission and attribution until delivery. The worker shield judges every delivered command.

def driving(profile) -> tuple

How an environment says it can be driven: (the most commands a second it takes, None: as fast as it answers; the time one step of it lasts, None: its time is the wall’s). From the profile’s max_hz and step_seconds; a profile that still names a clock is read as what that mode meant: steps (or none), each step lasts 1 / control_hz; wall, at most control_hz commands a second; events, neither.

def delay_ticks(reaction_delay_ms, hz) -> int

The control periods a decision waits before it is sent: reaction_delay_ms rounded up to whole periods of hz.

class Preempted(Exception)
__init__(by=None, priority=0)

Raised in an execution’s steps where they wait for a step’s reply: the unit by, of priority, takes the embodiment.

class Tick
__init__(session)

The tick of one kernel session (see the module docstring): run(steps) runs an execution on it, judge() has the rules judged, stop() ends it. ticks counts the steps it sent. bound: the most commands a second the environment takes (its periods are paced then), step_seconds: the time one step of it lasts (driving()).

def judge()

Have the rules judged: one was set, what they read changed, or a rule’s program ended. Nothing where no rule is judged (no rule, no tick).

def stop(timeout=5.0)

Stop ticking; a program entry still running ends with an error.

def on_thread() -> bool

Whether the caller runs on the tick (a controller, a guard).

def run(steps)

Run the execution on the tick and return its trace, or raise its error. steps: its generator, or a function that makes it. Without channels the embodiment is held by priority: the execution of the unit of highest priority advances (the oldest among equals), and it ends a lower unit’s execution where that is: with PREEMPTED and what it had done, and the model is told at once (_preempt). The unit that took the embodiment holds it until it ends: what lower units start meanwhile waits, and goes on then. A unit that said restart=True has its execution started again then instead (its trace counts the restarts). Where the environment pauses (its profile says “pauses”), the lower execution does not end: the environment holds what it was doing, and it goes on from there when the higher unit has ended (_pause, _resume).

def hold(unit) -> None

unit said with what priority it holds the embodiment (at_priority): it holds it with that from now until it ends, between its executions too.

def known(names) -> list

names (a name or a list) as channel names of the embodiment (ValueError for one it does not declare).

def conflicts(entry, names, *, claiming=False) -> dict

{channel: id of the entry that has it} for the channels of names that entry cannot use now: another entry drives or holds it, or claimed it (a claim of an entry above entry leaves it to the entries below).

def claim(entry, names) -> dict

entry claims the channels names until it releases them or ends: {channel: holder id} of those it cannot have (then it claims none), else {}.

def release(entry, names=None) -> None

entry lets go of the channels names (None: all it has): its claims, and the keys and buttons it holds down on them, which go up at the next period.

def let_go(entries) -> None

The keys and buttons entries hold down go up at the next period; their claims stay (a guard stopped what they do, runtime/execution/session.py).

def board() -> dict

Who has each channel now: {channel: {“entry”, “how”: claimed, driving or holding}}, None where nobody does (it is at its default).

class Refused(Exception)
__init__(reason: dict)

A command the session cannot take apart into its channels’ periods (an input of no channel, a command it does not know): its reason, as a shield’s.

Units of a kernel session, and bounded ClosedLoop executions.

A session has one model (the root entry) and the units it started: every program the model writes, every function a program spawns, every sub-agent. A unit has its own output, events and pictures (its box) and its own result. What a unit starts belongs to the model, not to the unit: it outlives the program that started it and ends with the model. An event goes through the handlers; one nobody answers reaches the model, and so does every unit’s end.

def current_entry()

The entry executing on this thread, or None outside every unit.

class Box
__init__()

What one unit gathered for the model: its output (a writer the kernel gives it, whose recent(chars) is what was printed last), the pictures it showed and looked at, and the events of its executions.

class Cancelled(BaseException)

Raised in an entry’s code when the entry was cancelled; a BaseException so that the broad excepts of a program do not keep it running.

class Entry
__init__(tree, identifier, name, kind, parent, claims=(), agent=None)

One unit of a session (see the module docstring): its id, name, kind (“root” for the model, “program” for code, “agent” for a sub-agent), the model it belongs to (parent), its claims, its status (running, done, failed, cancelled) and, once ended, what its function returned (result) or why it failed (error). cell is the number of the model’s program it is (None for spawned code), rule the name of the rule whose program it is (the rules that program sets live with it), priority what it holds the embodiment with and restart whether an execution of it that a higher unit ended is started again (runtime/tick.py; default: it ends with PREEMPTED), box what it gathered, outcome how its code ended ({“status”: ok, error, escalated, episode_ended, finished or cancelled, …}), raised the exception of an error.

def running() -> bool

Whether it has not ended yet.

def rank() -> float

What it holds the environment with now: its priority, or the one the code it runs in the environment asks for, whichever is higher.

def lineage() -> list

This entry and the entries above it, up to the root.

def state() -> dict

The entry as a program and the model see it.

def wait(timeout=None)

Wait until this entry has ended, at most timeout seconds (None: as long as it takes). Returns what its function returned (a sub-agent: its report); raises its failure (an Escalation with an ENTRY_FAILED event), which this wait then handles; returns None when it was cancelled or is still running at the timeout (status says which).

def output(chars=2000) -> str

What this unit has printed so far: the last chars characters (at most 30000), while it runs or after it ended. Reading takes nothing away: its result still has the whole output when it ends. “” for a unit that printed nothing (a sub-agent prints nothing here: its report is its result).

def send(message)

Send this entry a message, which its code reads with receive() (a sub-agent: the answer to its question, or more to do).

def cancel(timeout=5.0)

Stop this unit: the execution it runs ends at its next step, a wait or receive it is in raises, and code that does not reach the harness is interrupted where it is after a moment. What it started goes on (it is the model’s). Returns its state.

def receive(timeout=None)

The oldest message sent to this entry, waiting at most timeout seconds for one (None: as long as it takes); None when none came.

class Tree
__init__(session)

The units of one kernel session (see the module docstring). on_end(entry, handled) is called once for every unit that ended (the kernel tells the model, runtime/execution/kernel.py); new_output(entry) gives a new unit the writer of its output.

def current() -> Entry

The entry the calling code belongs to (the root outside every other).

def acting(entry)

Code inside belongs to entry (the tick steps an entry’s execution, a handler of an entry runs).

def get(identifier) -> Entry

The entry identifier (the root when there is none).

def under(entry) -> list

entry and every entry below it (those it started, those they started, …).

def check(entry=None) -> None

Raise in the code of entry (default: the caller’s) what it must stop for: its cancellation, or the user’s pause.

def interruption(entry, take=True)

What entry’s code must stop for now (see check), or None: every unit of the model stops while the user has paused it (runtime/execution/control.py).

def spawn(fn, name=None, claims=None, *, cell=None, rule=None, priority=None, restart=False, quiet=False, until=None) -> Entry

Run fn() as a new unit of the model (see the module docstring); cell: it is the model’s program of that number; rule: it is the program of that rule; priority: its own (default: that of the unit that starts it); restart True: an execution of it that a unit of higher priority ends is started again when that unit is over (default: it ends there with PREEMPTED).

def until(condition) -> None

The unit this code runs in is for condition: a function of the view that holds when its work is done. It is judged when the unit ends, and the end says whether it held.

def at_priority(priority) -> '_Priority'

with at_priority(priority): the unit this code runs in holds the embodiment with priority for the block, between its executions too (runtime/tick.py hold), and with what it held it before from the block’s end on. A unit of higher priority still takes it (a reflex whose place is priority or above); one of lower priority waits, and is judged again when the block ends. Its own ends stay: it is cancelled, its calls reach their time, a reflex that ends what runs holds, the episode ends.

def claim(names) -> bool

The caller’s entry claims the channels names (see the module docstring): True; False when one is another entry’s and a handler took the CHANNEL_CONFLICT event, which otherwise escalates.

def release(names=None) -> None

The caller’s entry lets go of the channels names (None: all it has): its claims, and the keys and buttons it holds down on them.

def channels() -> dict

Who has each channel now ({channel: {“entry”, “how”}}, None: nobody); {} when the embodiment declares none.

def adopt_agent(agent, task) -> Entry

The unit of a sub-agent the model’s code started (delegate).

def agent_runs(agent) -> bool

Whether a unit of sub-agent agent has not ended.

def agent_ended(agent, report, *, cancelled=False) -> None

A turn of a sub-agent ended (the conversation tells the kernel, runtime/execution/kernel.py): so does its entry, failed unless the turn ended with an answer.

def record_event(trace, entry=None)
def raise_event(entry, trace, *, notice=False) -> None

Deliver an independent event without waiting for its handlers on the tick.

def handle(entry, trace) -> bool

Offer trace’s event to the tree of reflexes (runtime/reactive/tree.py answer): a node that answers its kind, and whose turn it is, starts its program as a unit, and the event is answered.

def running() -> list

The units that have not ended, oldest first (the model aside).

def close(timeout=2.0) -> None

The session closes: the model ends, and every unit with it.

class Result(dict)

What a closed loop did: {“ok”, “reason”, “tries”, “seconds”, “detail”}; true when ok.

class Stop(Exception)

Raised in a step: the loop ends here with this reason (no more tries).

class ClosedLoop
__init__(*args, **kwargs)

Confirm, do, check, retry, give the reason: one bounded execution, in any action scenario; a skill the model writes is one, and so is every execution of the session’s skills (runtime/execution/session.py Execution). A subclass fills in confirm() (before each try: True, or the reason not to act), do(), check() (after it: True, or why not) and recover(reason) (between tries); a step may raise Stop(reason). Called with the skill’s parameters (on self), it runs at most tries times and max_seconds long and returns a Result; an exception of catches in a step is its reason (the episode’s end, finish() and PASS_ON always end the program). A step may fill in detail. Each try’s end is report()ed: a skill_step record, news for the model while the program runs.

def confirm()
def do()
def check()
def recover(reason)
def report(number: int, what: str, ok: bool, seconds: float, reason) -> None
def run() -> Result