muse-code-sdk 1.3.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.
@@ -0,0 +1,141 @@
1
+ """The session-state half of the SS4 client fold (spec 638 FR-638-007
2
+ carrying spec 14990 FR-007, INV-005).
3
+
4
+ State events are NOT items: they carry replace-wholesale session facts,
5
+ cursor-ordered, latest-wins (tdd SS4.6). An explicit ``None`` is a fact — it
6
+ clears the family — never "unchanged" (the ``session/goalChanged`` and
7
+ ``session/branchChanged`` rules). ``session/tokenUsage`` is the one
8
+ accumulate-only family; its running totals arrive server-computed in
9
+ ``cumulative``, so the client stores rather than sums (tdd SS4.6.5).
10
+
11
+ The family KEY is the notification method name — protocol vocabulary treated
12
+ as an opaque string, so a family added additively (tdd SS1.5.4) folds without
13
+ a code change.
14
+
15
+ Absent versus cleared, the Python spelling: ``get`` answers ``None`` for
16
+ both, and ``has`` distinguishes — ``has(family)`` is ``False`` when no fact
17
+ has ever landed and ``True`` when a fact (including an explicit clear)
18
+ holds. Absent is never fabricated (tdd SS4.9.1). (The TS store spells the
19
+ same three states as ``undefined`` / ``null`` / value.)
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from dataclasses import dataclass
25
+ from typing import Iterable
26
+
27
+ StateValue = object | None
28
+ """A stored family value. ``None`` is a real value: the family was cleared."""
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class StateApplyOutcome:
33
+ """What one state event changed.
34
+
35
+ Attributes:
36
+ family: The family it targeted.
37
+ previous: The value it replaced (``None`` when absent or cleared;
38
+ ``had_previous`` distinguishes).
39
+ had_previous: Whether the family held any fact before this event.
40
+ current: The value now stored.
41
+ applied: ``False`` when the incoming value was refused as an
42
+ exact-cursor replay.
43
+ """
44
+
45
+ family: str
46
+ previous: StateValue
47
+ had_previous: bool
48
+ current: StateValue
49
+ applied: bool
50
+
51
+
52
+ class SessionStateStore:
53
+ """Last-write-wins per family, in arrival order.
54
+
55
+ Cursors are opaque strings and MUST NOT be parsed or ordered (tdd SS4.1),
56
+ so ordering here is by arrival: the server emits view events in cursor
57
+ order on every connection, and a page's events are ascending. The one
58
+ cursor use is EXACT-EQUALITY replay de-duplication, and it remembers only
59
+ the family's LATEST cursor — it refuses only a back-to-back replay of the
60
+ family's most recent event. The SS4.8 splice caller must skip
61
+ already-applied page events itself, which it does by construction: the
62
+ splice pages forward from ``after`` and discards paged events at cursors
63
+ >= ``next`` as duplicates of the live buffer. No relational comparison
64
+ exists: string order diverges from cursor order at every digit rollover
65
+ ("v:s:10" < "v:s:9" as strings), which would drop genuinely newer events.
66
+ """
67
+
68
+ def __init__(self) -> None:
69
+ """Create an empty store."""
70
+ self._values: dict[str, StateValue] = {}
71
+ self._cursors: dict[str, str] = {}
72
+
73
+ def apply(
74
+ self, family: str, value: StateValue, cursor: str | None = None
75
+ ) -> StateApplyOutcome:
76
+ """Apply a state event.
77
+
78
+ Args:
79
+ family: The notification method name (opaque vocabulary).
80
+ value: The event's params object, or ``None`` for a clear.
81
+ cursor: The event's ``viewCursor``; when omitted (a snapshot
82
+ seed, which carries one cursor for the whole state) the value
83
+ is taken unconditionally.
84
+
85
+ Returns:
86
+ What changed, and whether the event applied.
87
+ """
88
+ had_previous = family in self._values
89
+ previous = self._values.get(family)
90
+ if cursor is not None:
91
+ seen = self._cursors.get(family)
92
+ # An equal cursor is a replay of the same event (idempotent):
93
+ # refuse. That is the ONLY cursor comparison — cursors are opaque
94
+ # (SS4.1) and any relational order mis-sorts at a digit rollover;
95
+ # arrival order carries the LWW truth.
96
+ if seen is not None and cursor == seen:
97
+ return StateApplyOutcome(
98
+ family=family,
99
+ previous=previous,
100
+ had_previous=had_previous,
101
+ current=previous,
102
+ applied=False,
103
+ )
104
+ self._cursors[family] = cursor
105
+ self._values[family] = value
106
+ return StateApplyOutcome(
107
+ family=family,
108
+ previous=previous,
109
+ had_previous=had_previous,
110
+ current=value,
111
+ applied=True,
112
+ )
113
+
114
+ def get(self, family: str) -> StateValue:
115
+ """Read a family: the held value, or ``None`` when absent or cleared.
116
+
117
+ Pair with :meth:`has` to distinguish never-landed from cleared
118
+ (module docstring, "Absent versus cleared").
119
+ """
120
+ return self._values.get(family)
121
+
122
+ def has(self, family: str) -> bool:
123
+ """Whether the family holds any fact (an explicit clear counts)."""
124
+ return family in self._values
125
+
126
+ def families(self) -> list[str]:
127
+ """Every family that holds a value, in insertion order."""
128
+ return list(self._values)
129
+
130
+ def seed(
131
+ self,
132
+ entries: Iterable[tuple[str, StateValue]],
133
+ cursor: str | None = None,
134
+ ) -> None:
135
+ """Seed from a snapshot's state block: authoritative, replaces wholesale."""
136
+ self._values.clear()
137
+ self._cursors.clear()
138
+ for family, value in entries:
139
+ self._values[family] = value
140
+ if cursor is not None:
141
+ self._cursors[family] = cursor
@@ -0,0 +1,53 @@
1
+ """The SS4.13 ``PendingCommand`` fold (client-local; spec 638 FR-638-008)."""
2
+
3
+ from muse_code.pending.pending_command_set import (
4
+ COMMAND_REJECTED_CODE,
5
+ COMMAND_REJECTED_KIND,
6
+ AbandonedRetirement,
7
+ CommandErrorResponse,
8
+ Held,
9
+ MaterializedRetirement,
10
+ PendingCommandAck,
11
+ PendingCommandEntry,
12
+ PendingCommandSet,
13
+ PendingDisposition,
14
+ PendingJoinPlan,
15
+ PendingRetirement,
16
+ ReclaimedRetirement,
17
+ RejectedRetirement,
18
+ ReplayAck,
19
+ ReplayAnswer,
20
+ ReplayError,
21
+ RetryAbandonedByClientRetirement,
22
+ SnapshotJoinFacts,
23
+ TerminalUnknownRetirement,
24
+ TurnRef,
25
+ UserMessageRef,
26
+ is_settlement,
27
+ )
28
+
29
+ __all__ = [
30
+ "COMMAND_REJECTED_CODE",
31
+ "COMMAND_REJECTED_KIND",
32
+ "AbandonedRetirement",
33
+ "CommandErrorResponse",
34
+ "Held",
35
+ "MaterializedRetirement",
36
+ "PendingCommandAck",
37
+ "PendingCommandEntry",
38
+ "PendingCommandSet",
39
+ "PendingDisposition",
40
+ "PendingJoinPlan",
41
+ "PendingRetirement",
42
+ "ReclaimedRetirement",
43
+ "RejectedRetirement",
44
+ "ReplayAck",
45
+ "ReplayAnswer",
46
+ "ReplayError",
47
+ "RetryAbandonedByClientRetirement",
48
+ "SnapshotJoinFacts",
49
+ "TerminalUnknownRetirement",
50
+ "TurnRef",
51
+ "UserMessageRef",
52
+ "is_settlement",
53
+ ]