@llblab/pi-kit 0.24.1 → 0.26.0
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.
- package/AGENTS.md +1 -1
- package/BACKLOG.md +5 -1
- package/CHANGELOG.md +12 -0
- package/README.md +11 -8
- package/node_modules/@llblab/pi-actors/AGENTS.md +2 -0
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +4 -1
- package/node_modules/@llblab/pi-actors/LICENSE +21 -0
- package/node_modules/@llblab/pi-actors/README.md +1 -1
- package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +1 -1
- package/node_modules/@llblab/pi-actors/package.json +4 -3
- package/node_modules/@llblab/pi-claude-usage/AGENTS.md +23 -0
- package/node_modules/@llblab/pi-claude-usage/BACKLOG.md +4 -0
- package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +21 -0
- package/node_modules/@llblab/pi-claude-usage/LICENSE +22 -0
- package/node_modules/@llblab/pi-claude-usage/README.md +155 -0
- package/node_modules/@llblab/pi-claude-usage/banner.jpg +0 -0
- package/node_modules/@llblab/pi-claude-usage/index.ts +8 -0
- package/node_modules/@llblab/pi-claude-usage/lib/extension.ts +30 -0
- package/node_modules/@llblab/pi-claude-usage/lib/fast.ts +24 -0
- package/node_modules/@llblab/pi-claude-usage/lib/query.ts +146 -0
- package/node_modules/@llblab/pi-claude-usage/lib/status-format.ts +297 -0
- package/node_modules/@llblab/pi-claude-usage/lib/status.ts +366 -0
- package/node_modules/@llblab/pi-claude-usage/lib/telegram.ts +44 -0
- package/node_modules/@llblab/pi-claude-usage/lib/usage-store.ts +221 -0
- package/node_modules/@llblab/pi-claude-usage/lib/usage.ts +128 -0
- package/node_modules/@llblab/pi-claude-usage/package.json +64 -0
- package/node_modules/@llblab/pi-clean-room/AGENTS.md +1 -0
- package/node_modules/@llblab/pi-clean-room/CHANGELOG.md +5 -0
- package/node_modules/@llblab/pi-clean-room/LICENSE +21 -0
- package/node_modules/@llblab/pi-clean-room/README.md +1 -1
- package/node_modules/@llblab/pi-clean-room/package.json +3 -2
- package/node_modules/@llblab/pi-codex-usage/AGENTS.md +9 -6
- package/node_modules/@llblab/pi-codex-usage/BACKLOG.md +2 -1
- package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +17 -0
- package/node_modules/@llblab/pi-codex-usage/README.md +75 -17
- package/node_modules/@llblab/pi-codex-usage/index.ts +8 -1602
- package/node_modules/@llblab/pi-codex-usage/lib/extension.ts +25 -0
- package/node_modules/@llblab/pi-codex-usage/lib/fast.ts +23 -0
- package/node_modules/@llblab/pi-codex-usage/lib/query.ts +368 -0
- package/node_modules/@llblab/pi-codex-usage/lib/status-format.ts +347 -0
- package/node_modules/@llblab/pi-codex-usage/lib/status.ts +435 -0
- package/node_modules/@llblab/pi-codex-usage/lib/telegram.ts +45 -0
- package/node_modules/@llblab/pi-codex-usage/lib/usage-store.ts +229 -0
- package/node_modules/@llblab/pi-codex-usage/lib/usage.ts +425 -0
- package/node_modules/@llblab/pi-codex-usage/package.json +11 -6
- package/node_modules/@llblab/pi-command-fast/AGENTS.md +7 -0
- package/node_modules/@llblab/pi-command-fast/BACKLOG.md +9 -0
- package/node_modules/@llblab/pi-command-fast/CHANGELOG.md +7 -0
- package/node_modules/@llblab/pi-command-fast/LICENSE +21 -0
- package/node_modules/@llblab/pi-command-fast/README.md +42 -0
- package/node_modules/@llblab/pi-command-fast/dist/command.d.ts +8 -0
- package/node_modules/@llblab/pi-command-fast/dist/command.js +52 -0
- package/node_modules/@llblab/pi-command-fast/dist/index.d.ts +3 -0
- package/node_modules/@llblab/pi-command-fast/dist/index.js +3 -0
- package/node_modules/@llblab/pi-command-fast/dist/models-json.d.ts +10 -0
- package/node_modules/@llblab/pi-command-fast/dist/models-json.js +81 -0
- package/node_modules/@llblab/pi-command-fast/package.json +49 -0
- package/node_modules/@llblab/pi-grow-loop/AGENTS.md +1 -0
- package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +4 -1
- package/node_modules/@llblab/pi-grow-loop/LICENSE +21 -0
- package/node_modules/@llblab/pi-grow-loop/README.md +1 -1
- package/node_modules/@llblab/pi-grow-loop/package.json +3 -2
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +43 -56
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +17 -3
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +25 -0
- package/node_modules/@llblab/pi-state-flow/LICENSE +21 -0
- package/node_modules/@llblab/pi-state-flow/README.md +18 -15
- package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/index.js +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +7 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +16 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +9 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +5 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +7 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +3 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +3 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +503 -235
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +16 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +11 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +6 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +4 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +1 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +4 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +13 -13
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +7 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +9 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +3 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +17 -12
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +13 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +62 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +23 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +52 -20
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +22 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +30 -10
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +5 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +19 -28
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +17 -15
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +52 -52
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +8 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +34 -18
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +13 -19
- package/node_modules/@llblab/pi-state-flow/dist/package.json +12 -11
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -1
- package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +72 -0
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +44 -36
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +14 -6
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +7 -5
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +6 -6
- package/node_modules/@llblab/pi-state-flow/docs/performance.md +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +13 -12
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +37 -33
- package/node_modules/@llblab/pi-state-flow/index.ts +3 -2
- package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +20 -10
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +15 -14
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +8 -6
- package/node_modules/@llblab/pi-state-flow/lib/episode.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +484 -232
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +14 -5
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -11
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +5 -1
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +16 -16
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +11 -11
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +19 -13
- package/node_modules/@llblab/pi-state-flow/lib/session.ts +57 -3
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +57 -22
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +46 -13
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +23 -32
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +66 -65
- package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +39 -19
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +19 -27
- package/node_modules/@llblab/pi-state-flow/package.json +12 -11
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +2 -2
- package/node_modules/jsonc-parser/CHANGELOG.md +76 -0
- package/node_modules/jsonc-parser/LICENSE.md +21 -0
- package/node_modules/jsonc-parser/README.md +364 -0
- package/node_modules/jsonc-parser/SECURITY.md +41 -0
- package/node_modules/jsonc-parser/lib/esm/impl/edit.js +185 -0
- package/node_modules/jsonc-parser/lib/esm/impl/format.js +261 -0
- package/node_modules/jsonc-parser/lib/esm/impl/parser.js +659 -0
- package/node_modules/jsonc-parser/lib/esm/impl/scanner.js +443 -0
- package/node_modules/jsonc-parser/lib/esm/impl/string-intern.js +29 -0
- package/node_modules/jsonc-parser/lib/esm/main.d.ts +351 -0
- package/node_modules/jsonc-parser/lib/esm/main.js +178 -0
- package/node_modules/jsonc-parser/lib/umd/impl/edit.js +201 -0
- package/node_modules/jsonc-parser/lib/umd/impl/format.js +275 -0
- package/node_modules/jsonc-parser/lib/umd/impl/parser.js +682 -0
- package/node_modules/jsonc-parser/lib/umd/impl/scanner.js +456 -0
- package/node_modules/jsonc-parser/lib/umd/impl/string-intern.js +42 -0
- package/node_modules/jsonc-parser/lib/umd/main.d.ts +351 -0
- package/node_modules/jsonc-parser/lib/umd/main.js +194 -0
- package/node_modules/jsonc-parser/package.json +37 -0
- package/package.json +10 -6
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 llblab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
**Incremental scoped context/memory compiler for Pi.**
|
|
6
6
|
|
|
7
|
-
State Flow maintains explicit state across requests and sessions. The agent incrementally compiles requirements, decisions, findings and source knowledge into durable memory rather than carrying every completed exchange into the next request.
|
|
7
|
+
When enabled, State Flow maintains explicit state across requests and sessions. The agent incrementally compiles requirements, decisions, findings and source knowledge into durable memory rather than carrying every completed exchange into the next request.
|
|
8
8
|
|
|
9
9
|
Drawing on the explicit-state approach of [SKILL.state](https://arxiv.org/html/2608.26263v2), State Flow combines durable state with Pi's native conversation context. In this hybrid, **state carries continuity between user runs; Pi's native context carries the working trajectory within a run.** The conversation is not reset after each model response or tool call. Pi retains ownership of execution, session navigation and the full inspectable trace.
|
|
10
10
|
|
|
11
11
|
## How it works
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
In Active mode, a user run starts with effective memory and a new request. The agent works through Pi's ordinary inference/tool loop, updates memory when useful information changes, and returns an ordinary answer. The next run receives the accepted state and compact recent transitions instead of the completed ordinary conversation history.
|
|
14
14
|
|
|
15
15
|
```text
|
|
16
16
|
Current state + Request
|
|
@@ -30,7 +30,7 @@ Native compaction remains available for long runs. State Flow may also request a
|
|
|
30
30
|
|
|
31
31
|
## Installation and activation
|
|
32
32
|
|
|
33
|
-
Requires **Pi 0.
|
|
33
|
+
Requires **Pi 1.0.0+** and **Node.js 22.19.0+**. See [SDK compatibility](docs/compatibility.md) for tested stacks and verification limits.
|
|
34
34
|
|
|
35
35
|
From NPM:
|
|
36
36
|
|
|
@@ -47,22 +47,23 @@ pi install git:github.com/llblab/pi-state-flow
|
|
|
47
47
|
Enable active State Flow on the current branch:
|
|
48
48
|
|
|
49
49
|
```text
|
|
50
|
-
/state-flow-
|
|
50
|
+
/state-flow-active
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Starting in an existing conversation retains its context for one complete bootstrap run so the agent can compile what matters.
|
|
54
54
|
|
|
55
|
-
- `/state-flow-
|
|
55
|
+
- `/state-flow-active`: Select the active, state-driven iteration workflow.
|
|
56
|
+
- `/state-flow-passive`: Select ordinary conversation with both memory tools and existing-memory projection.
|
|
57
|
+
- `/state-flow-off`: Remove both memory tools and all State Flow model context, without deleting memory.
|
|
56
58
|
- `/state-flow-status`: Inspect effective state, retained history and known recovery issues without scanning sources or changing state.
|
|
57
|
-
- `/state-flow-stop`: End active episode semantics without deleting memory, even when canonical persistence fails. Interrupted work and uncompiled conversation remain available across toggles and reload; a failed write stays fenced until explicit Start safely reactivates current memory.
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
New sessions default to **Off**; select Passive for ordinary conversation with memory tools, or Active for state-driven episodes. Passive projects state only after a validated memory view is available. Off removes State Flow's model-facing tools and context without deleting memory. Mode changes affect only this session; the global default applies only to new sessions. See [mode semantics](docs/usage.md#active-passive-and-configured-off), [configuration](docs/usage.md#configuration) and [status and controls](docs/usage.md#status-and-controls).
|
|
60
61
|
|
|
61
62
|
### Active, passive, off
|
|
62
63
|
|
|
63
64
|
- `Active`: Memory tools are available; the agent consolidates necessary final state changes before completing an iteration. Subsequent iterations use accepted state and new input rather than completed prior reasoning.
|
|
64
|
-
- `Passive`:
|
|
65
|
-
- `
|
|
65
|
+
- `Passive`: Both memory tools and existing-state projection remain available. Patching is on demand, and ordinary conversation context continues without State Flow's active iteration reset.
|
|
66
|
+
- `Off`: Neither memory tool nor State Flow context—including a frozen passive handoff—is exposed to the model. Startup/reload/tree attachment does not read or restore memory; selecting Off cancels pending memory waits and records only native policy/bookmarks. Explicit Passive/Active acquires memory later. Stored memory and Pi's native trace remain intact.
|
|
66
67
|
|
|
67
68
|
Modes select agent behavior, not a different disk persistence or fork-copy mechanism. Final consolidation does not require an empty ceremonial patch, and context projection does not delete native history. See [mode semantics and bootstrap terminology](docs/usage.md#active-passive-and-configured-off).
|
|
68
69
|
|
|
@@ -82,16 +83,18 @@ The agent receives the **effective view** of this composition, not three unrelat
|
|
|
82
83
|
|
|
83
84
|
### Semantic planes
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
Runtime views provide these documented planes:
|
|
86
87
|
|
|
87
88
|
- `intents`: Active commitments to future action.
|
|
88
89
|
- `contract`: Requirements, decisions, constraints and interface commitments.
|
|
89
90
|
- `working`: Observations, results, uncertainties and current continuation.
|
|
90
91
|
- `artifacts`: Source-addressed descriptions and compiled knowledge.
|
|
91
|
-
- `response`: The exact latest accepted answer, including an empty string, captured by the runtime only in Session. Global
|
|
92
|
+
- `response`: The exact latest accepted answer, including an empty string, captured by the runtime only in Session. Global/CWD receive no newly accepted answers; stored scopes may omit response entirely. Effective uses the highest-priority nonempty value.
|
|
92
93
|
- `lazy`: Supporting memory available through explicit reads, with its body omitted from baseline model context.
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
Stored checkpoints and patches may omit any documented plane, including `intents`, `lazy` or `response`. Current and historical views assemble only known fields actually present in the selected scopes, without filling absent fields. Empty `response` is treated as absent. Checkpoint and patch readers ignore unknown top-level fields; writers emit only known fields. Nested data within known planes is unrestricted. Reading or starting never rewrites data just to normalize it; missing fields are not a storage-format error.
|
|
96
|
+
|
|
97
|
+
These planes organize ordinary JSON rather than imposing a project-specific schema. The model updates the semantic planes except `response`, which is runtime-owned. Global and CWD revisions are shared by their canonical stores, Session has its own revision, and Effective has no scalar owner: its identity is the `g#c#s#` vector. One atomic patch advances each materially changed scope once. Memory remains fallible: storing an observation does not make it current or correct.
|
|
95
98
|
|
|
96
99
|
Registered Pi Skills may be compiled into source-addressed artifacts when durable guidance is useful. Pi's resource provenance determines ownership: user Skills map to global, project Skills to CWD and temporary Skills to session. A matching source hash needs no update; an uncompiled read remains ordinary volatile context and does not block unrelated patches.
|
|
97
100
|
|
|
@@ -134,11 +137,11 @@ The default store is `~/.pi/agent/state-flow/`, independent of registered source
|
|
|
134
137
|
|
|
135
138
|
**Persistence is optimistic across abrupt shutdown.** Short publication exclusion preserves independent shared fields between cooperating writers; the last accepted write wins on overlap. Per-file atomic replacement does not guarantee power-loss survival or crash-atomic recovery. That [accepted limitation](docs/filesystem-recovery.md#power-loss-durability) is not a release gate; no additional recovery journal or storage format is planned.
|
|
136
139
|
|
|
137
|
-
**Git backups are optional.** When the store is a configured Git repository, accepted active turns may create versioned backups of State Flow-owned files. A busy store explicitly defers backup when Pi provides no cancellable settlement wait (including SDK 0.87); a later accepted turn retries without changing memory or blocking native Abort. If the attached branch has an explicitly configured remote, State Flow then pushes the exact current backup commit there asynchronously and without force. Within one Pi process, only one push per repository can run at a time; overlapping attempts are skipped and a later accepted turn pushes the latest backup.
|
|
140
|
+
**Git backups are optional.** When the store is a configured Git repository, accepted active turns may create versioned backups of State Flow-owned files. A busy store explicitly defers backup when Pi provides no cancellable settlement wait (including SDK 0.87); a later accepted turn retries without changing memory or blocking native Abort. If the attached branch has an explicitly configured remote, State Flow then pushes the exact current backup commit there asynchronously and without force. Within one Pi process, only one push per repository can run at a time; overlapping attempts are skipped and a later accepted turn pushes the latest backup. Off cancels pending captures and its admitted push without rolling back accepted state or backup commits; canceled work emits no late memory warnings. Shutdown cancels owned pushes and waits for that repository's active push to close or time out. Commit failures warn locally; repeated push failures produce one concise warning until a successful push, with redacted Git detail kept in the local diagnostic log. Neither failure rejects or rolls back accepted memory. Backup needs a Git commit identity, but accepting and persisting state does not. Git history can be inspected separately, but it is not the authority for `read_state` or automatic restoration of expired semantic boundaries.
|
|
138
141
|
|
|
139
|
-
|
|
142
|
+
Memory-enabled resume and tree navigation restore the selected retained session boundary over current shared global/CWD memory; Off defers this acquisition. A new session gets its own session layer. Supported native forks copy selected session state into a new owner without changing the parent's private data. Expired, incomplete or contradictory boundaries never silently substitute newer private state during restoration. Explicit Start is a mode change, not historical restoration: it activates validated **current** memory of that same session, including private state, even after expired active/passive, interrupted or pre-runtime selections. Available aligned history and revisions survive; unavailable history is not recreated. Malformed storage, unsafe fork copying and concurrent writes remain fenced. See [fork support](docs/usage.md#fork-support-and-limits) and [storage recovery](docs/usage.md#storage-and-recovery).
|
|
140
143
|
|
|
141
|
-
SDK/launcher integrations can use [advisory continuation APIs](docs/architecture.md#session-continuation). Provenance inspection and candidate building are now asynchronous and accept host cancellation; they neither open native sessions nor install automatic resume. Run preparation and missing-artifact maintenance now wait cancelably before inference; embeddings can also use the [transaction APIs](docs/architecture.md#asynchronous-storage-transaction).
|
|
144
|
+
SDK/launcher integrations can use [advisory continuation APIs](docs/architecture.md#session-continuation). Provenance inspection and candidate building are now asynchronous and accept host cancellation; they neither open native sessions nor install automatic resume. Run preparation and missing-artifact maintenance now wait cancelably before inference; embeddings can also use the [transaction APIs](docs/architecture.md#asynchronous-storage-transaction). Selecting Passive switches local policy/context immediately and awaits runtime-only persistence. Off instead cancels owned memory waits and saves only native mode/continuation/fork bookkeeping, without validating or rewriting canonical storage. Explicit Off inspection may read current stored values through a disposable validated reader; it does not activate memory, install cache or change the selected historical/fork boundary. Missing private authority remains unavailable. Active waits for coherent capture/acceptance; another mode or selection can withdraw its wait. Passive retains independently owned restoration/fork work; Off cancels it and defers later acquisition. Failed Passive persistence preserves local policy and fences publication until accepted activation.
|
|
142
145
|
|
|
143
146
|
The canonical storage-format boundary introduced in 0.17 still applies: current versions accept only the canonical store contract and provide no in-place predecessor converter. Preserve existing data and check the [format boundary](docs/usage.md#moving-a-store-and-the-017-format-boundary) before changing versions or moving a store.
|
|
144
147
|
|
|
@@ -12,8 +12,8 @@ export { retainedMemoryScopes } from "./lib/memory.ts";
|
|
|
12
12
|
export { planKnowledgeRehydration, type RehydrationOptions, type RehydrationPhase, type RehydrationPlan, type RehydrationRead, type RehydrationRoute } from "./lib/rehydration.ts";
|
|
13
13
|
export { TemporalRuntime } from "./lib/runtime.ts";
|
|
14
14
|
export { hasCompiledSkillArtifact, hashSkillSource, SKILL_ARTIFACT_COMPILER, type SuccessfulSkillRead } from "./lib/skills.ts";
|
|
15
|
-
export { emptyState, isMaterializedState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts, type AtomicScopePatches, type MaterializedState, type ScopedPatch, type ScopedStates, type ScopePatch, type SemanticTransition, type StateDocument, type StatePatch, type StateScope, type TerminalTransition } from "./lib/state.ts";
|
|
15
|
+
export { emptyState, isMaterializedState, isSemanticState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts, type AtomicScopePatches, type MaterializedState, type ScopedPatch, type ScopedStates, type ScopedSemanticStates, type ScopePatch, type SemanticState, type SemanticTransition, type StateDocument, type StatePatch, type StateScope, type TerminalTransition } from "./lib/state.ts";
|
|
16
16
|
export { PublicationBusyError } from "./lib/storage.ts";
|
|
17
17
|
export { buildStateFlowSectionView, createStateFlowTelegramAdapter, formatStateFlowSectionLabel, loadStateFlowTelegramModules, STATE_FLOW_TELEGRAM_ID, type StateFlowTelegramAdapter, type StateFlowTelegramButton, type StateFlowTelegramCallbackContext, type StateFlowTelegramControlResult, type StateFlowTelegramInspection, type StateFlowTelegramInspectionPort, type StateFlowTelegramLoader, type StateFlowTelegramModules, type StateFlowTelegramPort, type StateFlowTelegramSectionContext, type StateFlowTelegramSectionModule, type StateFlowTelegramSnapshot, type StateFlowTelegramView } from "./lib/telegram.ts";
|
|
18
|
-
export { advanceTemporalState, readTemporalState, temporalScopeRevisions, type ScopeRevisions, type TemporalState } from "./lib/temporal.ts";
|
|
18
|
+
export { advanceTemporalState, readTemporalState, readTemporalView, temporalScopeRevisions, type ScopeRevisions, type TemporalState } from "./lib/temporal.ts";
|
|
19
19
|
export { parseStateReadPath, readStatePath, type StateReadQuery, type StateReadResult } from "./lib/query.ts";
|
|
@@ -11,8 +11,8 @@ export { retainedMemoryScopes } from "./lib/memory.js";
|
|
|
11
11
|
export { planKnowledgeRehydration } from "./lib/rehydration.js";
|
|
12
12
|
export { TemporalRuntime } from "./lib/runtime.js";
|
|
13
13
|
export { hasCompiledSkillArtifact, hashSkillSource, SKILL_ARTIFACT_COMPILER } from "./lib/skills.js";
|
|
14
|
-
export { emptyState, isMaterializedState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts } from "./lib/state.js";
|
|
14
|
+
export { emptyState, isMaterializedState, isSemanticState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts } from "./lib/state.js";
|
|
15
15
|
export { PublicationBusyError } from "./lib/storage.js";
|
|
16
16
|
export { buildStateFlowSectionView, createStateFlowTelegramAdapter, formatStateFlowSectionLabel, loadStateFlowTelegramModules, STATE_FLOW_TELEGRAM_ID } from "./lib/telegram.js";
|
|
17
|
-
export { advanceTemporalState, readTemporalState, temporalScopeRevisions } from "./lib/temporal.js";
|
|
17
|
+
export { advanceTemporalState, readTemporalState, readTemporalView, temporalScopeRevisions } from "./lib/temporal.js";
|
|
18
18
|
export { parseStateReadPath, readStatePath } from "./lib/query.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CompactionResult } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
export declare const STATE_FLOW_COMPACTION_SUMMARY = "State Flow accepted the completed work before this boundary. Current memory is restored from its retained semantic boundary and projected separately; use the retained native entries for subsequent work.";
|
|
3
3
|
/** A modest margin above Pi's default 20k retained suffix absorbs estimation drift. */
|
|
4
4
|
export declare const STATE_FLOW_COMPACTION_MIN_CONTEXT_TOKENS = 24000;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { estimateTokens } from "@earendil-works/pi-agent
|
|
1
|
+
import { estimateTokens } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
export const STATE_FLOW_COMPACTION_SUMMARY = "State Flow accepted the completed work before this boundary. Current memory is restored from its retained semantic boundary and projected separately; use the retained native entries for subsequent work.";
|
|
3
3
|
/** A modest margin above Pi's default 20k retained suffix absorbs estimation drift. */
|
|
4
4
|
export const STATE_FLOW_COMPACTION_MIN_CONTEXT_TOKENS = 24_000;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { type InactiveMode, type StateFlowMode } from "./snapshot.ts";
|
|
1
2
|
export interface StateFlowConfig {
|
|
2
3
|
/** Canonical State Flow repository. SDK callers may still override it explicitly. */
|
|
3
4
|
directory: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** Default mode for genuinely new sessions only; each session owns its selected mode. */
|
|
6
|
+
mode: StateFlowMode;
|
|
7
|
+
/** Non-active fallback for legacy `enabled:false` evidence and unavailable selections; never serialized. */
|
|
8
|
+
inactiveMode: InactiveMode;
|
|
7
9
|
/** Opt-in local capture of rejected patch attempts and unresolved terminal drafts. */
|
|
8
10
|
logging: boolean;
|
|
9
11
|
/** Show successful patch_state arguments in the interactive tool row. */
|
|
@@ -12,3 +14,5 @@ export interface StateFlowConfig {
|
|
|
12
14
|
}
|
|
13
15
|
/** Read the repository-global config once at extension load/reload. Missing config uses defaults; invalid config never falls back. */
|
|
14
16
|
export declare function loadStateFlowConfig(agentDir?: string, repositoryRoot?: string): StateFlowConfig;
|
|
17
|
+
/** Explicit modes never carry a separate passive policy: only Off stays off when inactive. */
|
|
18
|
+
export declare function inactiveModeFor(mode: StateFlowMode): InactiveMode;
|
|
@@ -5,15 +5,15 @@ import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
|
5
5
|
import { getDurableRepositoryRoot } from "./durable.js";
|
|
6
6
|
import { DEFAULT_HISTORY_LIMIT, MAX_HISTORY_LIMIT } from "./history.js";
|
|
7
7
|
import { isObject } from "./json.js";
|
|
8
|
+
import { isStateFlowMode } from "./snapshot.js";
|
|
8
9
|
/** Read the repository-global config once at extension load/reload. Missing config uses defaults; invalid config never falls back. */
|
|
9
10
|
export function loadStateFlowConfig(agentDir = getAgentDir(), repositoryRoot = getDurableRepositoryRoot(agentDir)) {
|
|
10
11
|
const directory = repositoryRoot;
|
|
11
12
|
const path = join(directory, "config.json");
|
|
12
13
|
const defaults = {
|
|
13
14
|
directory,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
passiveTools: true,
|
|
15
|
+
mode: "off",
|
|
16
|
+
inactiveMode: "off",
|
|
17
17
|
logging: false,
|
|
18
18
|
showSuccessfulPatches: true,
|
|
19
19
|
historyLimit: DEFAULT_HISTORY_LIMIT,
|
|
@@ -27,10 +27,13 @@ export function loadStateFlowConfig(agentDir = getAgentDir(), repositoryRoot = g
|
|
|
27
27
|
catch (error) {
|
|
28
28
|
throw new Error(`Cannot read State Flow configuration: ${path}`, { cause: error });
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
// autoStart/passiveBootstrap/passiveTools are read-only compatibility inputs; explicit mode is authoritative.
|
|
31
|
+
const allowed = new Set(["mode", "autoStart", "passiveBootstrap", "passiveTools", "logging", "showSuccessfulPatches", "historyLimit"]);
|
|
31
32
|
if (!isObject(value) || Object.keys(value).some((key) => !allowed.has(key))) {
|
|
32
33
|
throw new Error(`State Flow configuration contains unknown settings: ${path}`);
|
|
33
34
|
}
|
|
35
|
+
if (Object.hasOwn(value, "mode") && !isStateFlowMode(value.mode))
|
|
36
|
+
throw new Error(`State Flow mode must be "active", "passive" or "off": ${path}`);
|
|
34
37
|
if (Object.hasOwn(value, "autoStart") && typeof value.autoStart !== "boolean")
|
|
35
38
|
throw new Error(`State Flow autoStart must be a boolean: ${path}`);
|
|
36
39
|
if (Object.hasOwn(value, "passiveBootstrap") && typeof value.passiveBootstrap !== "boolean")
|
|
@@ -43,13 +46,19 @@ export function loadStateFlowConfig(agentDir = getAgentDir(), repositoryRoot = g
|
|
|
43
46
|
throw new Error(`State Flow showSuccessfulPatches must be a boolean: ${path}`);
|
|
44
47
|
if (Object.hasOwn(value, "historyLimit") && (!Number.isSafeInteger(value.historyLimit) || value.historyLimit < 0 || value.historyLimit > MAX_HISTORY_LIMIT))
|
|
45
48
|
throw new Error(`State Flow historyLimit must be an integer from 0 to ${MAX_HISTORY_LIMIT}: ${path}`);
|
|
49
|
+
const legacyInactive = value.passiveBootstrap !== false || value.passiveTools !== false ? "passive" : "off";
|
|
50
|
+
const hasLegacyMode = Object.hasOwn(value, "autoStart") || Object.hasOwn(value, "passiveBootstrap") || Object.hasOwn(value, "passiveTools");
|
|
51
|
+
const mode = isStateFlowMode(value.mode) ? value.mode : value.autoStart === true ? "active" : hasLegacyMode ? legacyInactive : "off";
|
|
46
52
|
return {
|
|
47
53
|
directory,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
passiveTools: value.passiveTools !== false,
|
|
54
|
+
mode,
|
|
55
|
+
inactiveMode: isStateFlowMode(value.mode) ? inactiveModeFor(value.mode) : hasLegacyMode ? legacyInactive : "off",
|
|
51
56
|
logging: value.logging === true,
|
|
52
57
|
showSuccessfulPatches: value.showSuccessfulPatches !== false,
|
|
53
58
|
historyLimit: typeof value.historyLimit === "number" ? value.historyLimit : DEFAULT_HISTORY_LIMIT,
|
|
54
59
|
};
|
|
55
60
|
}
|
|
61
|
+
/** Explicit modes never carry a separate passive policy: only Off stays off when inactive. */
|
|
62
|
+
export function inactiveModeFor(mode) {
|
|
63
|
+
return mode === "off" ? "off" : "passive";
|
|
64
|
+
}
|
|
@@ -4,12 +4,12 @@ import type { RecentTransitionWindow } from "./history.ts";
|
|
|
4
4
|
import { type JsonValue } from "./json.ts";
|
|
5
5
|
import type { Snapshot } from "./snapshot.ts";
|
|
6
6
|
import type { RehydrationPhase } from "./rehydration.ts";
|
|
7
|
-
import { type AtomicScopePatches, type
|
|
7
|
+
import { type AtomicScopePatches, type SemanticState } from "./state.ts";
|
|
8
8
|
/** Refresh only our section; Pi owns system frames, tools and forced-prompt precedence. */
|
|
9
9
|
export declare function projectSystemProtocol(messages: AgentMessage[], protocol: string | undefined): AgentMessage[];
|
|
10
10
|
type LazyValueKind = "array" | "boolean" | "null" | "number" | "object" | "string";
|
|
11
11
|
/** Fixed-budget navigation only: never place lazy bodies or partial key catalogs in baseline context. */
|
|
12
|
-
export declare function lazyNavigationHint(state:
|
|
12
|
+
export declare function lazyNavigationHint(state: SemanticState): {
|
|
13
13
|
available: boolean;
|
|
14
14
|
path: string;
|
|
15
15
|
keys?: Record<string, LazyValueKind>;
|
|
@@ -22,7 +22,7 @@ export type ModelStateUpdate = {
|
|
|
22
22
|
deleted: true;
|
|
23
23
|
});
|
|
24
24
|
/** Exact projected replacements, not authored merge patches; paths are unambiguous key/index segments. */
|
|
25
|
-
export declare function acceptedStateUpdates(before:
|
|
25
|
+
export declare function acceptedStateUpdates(before: SemanticState, after: SemanticState, patches: AtomicScopePatches): {
|
|
26
26
|
effective: ModelStateUpdate[];
|
|
27
27
|
lazy_navigation?: {
|
|
28
28
|
available: boolean;
|
|
@@ -31,14 +31,14 @@ export declare function acceptedStateUpdates(before: MaterializedState, after: M
|
|
|
31
31
|
} | undefined;
|
|
32
32
|
};
|
|
33
33
|
export interface ContextView {
|
|
34
|
-
state:
|
|
34
|
+
state: SemanticState;
|
|
35
35
|
lazy_navigation?: ReturnType<typeof lazyNavigationHint>;
|
|
36
36
|
artifact_invalidations: readonly ArtifactInvalidationNotice[];
|
|
37
37
|
knowledge_rehydration: {
|
|
38
38
|
phase: RehydrationPhase;
|
|
39
39
|
} | null;
|
|
40
40
|
}
|
|
41
|
-
export declare function contextView(state:
|
|
41
|
+
export declare function contextView(state: SemanticState, hints: ArtifactModelHints, invalidations: readonly ArtifactInvalidationNotice[], phase?: RehydrationPhase): ContextView;
|
|
42
42
|
/** Volatile model projection only. Native messages own trajectory; this cache owns no persistence or lifecycle. */
|
|
43
43
|
export declare class ContextProjection {
|
|
44
44
|
private identity;
|
|
@@ -48,7 +48,7 @@ export declare class ContextProjection {
|
|
|
48
48
|
private notices;
|
|
49
49
|
reset(): void;
|
|
50
50
|
/** Called only after successful publication and ancillary acceptance, immediately before returning the native result. */
|
|
51
|
-
acceptPatch(before:
|
|
51
|
+
acceptPatch(before: SemanticState, after: SemanticState, patches: AtomicScopePatches, hints: ArtifactModelHints): {
|
|
52
52
|
effective: ModelStateUpdate[];
|
|
53
53
|
lazy_navigation?: {
|
|
54
54
|
available: boolean;
|
|
@@ -65,13 +65,13 @@ export interface PassiveContinuation {
|
|
|
65
65
|
activeRunStartedAt?: number;
|
|
66
66
|
preserveContext?: true;
|
|
67
67
|
handoff: AgentMessage;
|
|
68
|
-
state:
|
|
68
|
+
state: SemanticState;
|
|
69
69
|
}
|
|
70
70
|
export declare function syntheticUser(text: string): AgentMessage;
|
|
71
|
-
export declare function createPassiveContinuation(state:
|
|
71
|
+
export declare function createPassiveContinuation(state: SemanticState, startedAt?: number, activeRunStartedAt?: number, preserveContext?: boolean): PassiveContinuation;
|
|
72
72
|
/** Keep the interrupted run through later results; an idle stop retains only later conversation. */
|
|
73
73
|
export declare function passiveContinuationMessages(messages: AgentMessage[], continuation: PassiveContinuation): AgentMessage[];
|
|
74
|
-
export declare function runtimeContextMessage(snapshot: Snapshot, state:
|
|
74
|
+
export declare function runtimeContextMessage(snapshot: Snapshot, state: SemanticState, recentTransitions?: RecentTransitionWindow, artifactInvalidations?: readonly ArtifactInvalidationNotice[], rehydrationPhase?: RehydrationPhase, artifactHints?: ArtifactModelHints): AgentMessage;
|
|
75
75
|
/** Render a view already projected by this domain without cloning the full semantic overlay twice. */
|
|
76
76
|
export declare function runtimeContextHead(snapshot: Snapshot, view: ContextView, recentTransitions?: RecentTransitionWindow): AgentMessage;
|
|
77
77
|
/** Captured identity survives text decoration; an uncertain boundary retains available context. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { projectArtifactForModel } from "./artifact.js";
|
|
3
3
|
import { applyPatch, isObject, presentationJson, sameJson } from "./json.js";
|
|
4
|
-
import { projectStateForModel } from "./state.js";
|
|
4
|
+
import { projectSemanticPatch, projectStateForModel } from "./state.js";
|
|
5
5
|
/** Refresh only our section; Pi owns system frames, tools and forced-prompt precedence. */
|
|
6
6
|
export function projectSystemProtocol(messages, protocol) {
|
|
7
7
|
let lastSystem = -1;
|
|
@@ -74,8 +74,8 @@ function projectedStateUpdates(previous, current, patches, beforeNavigation, nav
|
|
|
74
74
|
const diff = (left, right, path) => {
|
|
75
75
|
if (left === undefined && right === undefined || left !== undefined && right !== undefined && sameJson(left, right))
|
|
76
76
|
return;
|
|
77
|
-
if (isObject(
|
|
78
|
-
for (const key of new Set([...Object.keys(left), ...Object.keys(right)]))
|
|
77
|
+
if (isObject(right) && (isObject(left) || left === undefined && path.length === 1 && Object.keys(right).length > 0)) {
|
|
78
|
+
for (const key of new Set([...Object.keys(left ?? {}), ...Object.keys(right)]))
|
|
79
79
|
diff(child(left, key), child(right, key), [...path, key]);
|
|
80
80
|
}
|
|
81
81
|
else if (Array.isArray(left) && Array.isArray(right) && left.length === right.length) {
|
|
@@ -336,8 +336,9 @@ function projectRecentForModel(recent) {
|
|
|
336
336
|
const projected = structuredClone(recent);
|
|
337
337
|
for (const record of projected)
|
|
338
338
|
for (const transition of record.transitions) {
|
|
339
|
+
transition.patch = projectSemanticPatch(transition.patch);
|
|
339
340
|
delete transition.patch.lazy;
|
|
340
|
-
if (transition.patch.artifacts
|
|
341
|
+
if (!isObject(transition.patch.artifacts))
|
|
341
342
|
continue;
|
|
342
343
|
for (const [path, entry] of Object.entries(transition.patch.artifacts)) {
|
|
343
344
|
Object.defineProperty(transition.patch.artifacts, path, {
|
|
@@ -149,8 +149,8 @@ export async function inspectStateFlowContinuationProvenance(header, repositoryR
|
|
|
149
149
|
const runtime = parseSessionRuntime(files.get(paths.config), files.get(paths.runtime), selected.cwd, selected.id);
|
|
150
150
|
if (!runtime)
|
|
151
151
|
throw new Error("incomplete canonical session runtime");
|
|
152
|
-
if (
|
|
153
|
-
return { stateFlow: { enabled: false, restorable: true }, reason: "State Flow
|
|
152
|
+
if (runtime.config.mode !== "active")
|
|
153
|
+
return { stateFlow: { enabled: false, restorable: true }, reason: "State Flow is not active on selected runtime" };
|
|
154
154
|
const streams = ["global", "cwd", "session"].map((scope) => {
|
|
155
155
|
const owned = temporalScopePaths(selected.cwd, selected.id, scope, root, sessionKey);
|
|
156
156
|
return parseScopeStream(files.get(owned.checkpoint), files.get(owned.patches), scope, scope === "cwd" ? selected.cwd : undefined, files.get(owned.meta));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ArtifactProvenanceRegistry } from "./artifact.ts";
|
|
2
2
|
import { type ScopeStream, type TemporalState } from "./temporal.ts";
|
|
3
|
-
import type
|
|
3
|
+
import { type StateScope } from "./state.ts";
|
|
4
4
|
/** Canonical semantic sources plus runtime-owned temporal metadata. */
|
|
5
5
|
export interface ScopeStreamSources {
|
|
6
6
|
checkpoint: string;
|
|
@@ -6,6 +6,7 @@ import { parseArtifactProvenanceRegistry, serializeArtifactProvenanceRegistry, }
|
|
|
6
6
|
import { MAX_HISTORY_LIMIT } from "./history.js";
|
|
7
7
|
import { canonicalJson, isJsonValue, isObject } from "./json.js";
|
|
8
8
|
import { validateScopeStream, validateTemporalState } from "./temporal.js";
|
|
9
|
+
import { selectSemanticFields } from "./state.js";
|
|
9
10
|
const SESSION_KEY_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
10
11
|
const STATE_FILE = "state.json";
|
|
11
12
|
const CHECKPOINT_FILE = "checkpoint.json";
|
|
@@ -33,8 +34,8 @@ export function serializeScopeStream(stream, scope, cwdIdentity) {
|
|
|
33
34
|
if (scope !== "cwd" && cwdIdentity !== undefined)
|
|
34
35
|
throw new Error("Only State Flow CWD scope serialization accepts a CWD identity");
|
|
35
36
|
return {
|
|
36
|
-
checkpoint: `${canonicalJson(stream.checkpoint.state)}\n`,
|
|
37
|
-
patches: stream.patches.map((record) => `${canonicalJson(record.patch)}\n`).join(""),
|
|
37
|
+
checkpoint: `${canonicalJson(selectSemanticFields(stream.checkpoint.state))}\n`,
|
|
38
|
+
patches: stream.patches.map((record) => `${canonicalJson(selectSemanticFields(record.patch))}\n`).join(""),
|
|
38
39
|
temporal: {
|
|
39
40
|
revision: stream.revision,
|
|
40
41
|
checkpoint: structuredClone(stream.checkpoint.through),
|
|
@@ -96,8 +97,10 @@ export function classifyScopeStream(checkpointSource, patchesSource, scope, expe
|
|
|
96
97
|
// 0.17.4 and earlier did not persist scope revisions. Credit only their still-retained
|
|
97
98
|
// semantic tail; discarded ancestry cannot be reconstructed without inventing history.
|
|
98
99
|
revision: temporal.revision === undefined ? patches.length : temporal.revision,
|
|
99
|
-
checkpoint: { through: temporal.checkpoint, state: checkpoint },
|
|
100
|
-
patches: patches.map((patch, index) => ({
|
|
100
|
+
checkpoint: { through: temporal.checkpoint, state: isObject(checkpoint) ? selectSemanticFields(checkpoint) : checkpoint },
|
|
101
|
+
patches: patches.map((patch, index) => ({
|
|
102
|
+
transition: boundaries[index], patch: isObject(patch) ? selectSemanticFields(patch) : patch,
|
|
103
|
+
})),
|
|
101
104
|
};
|
|
102
105
|
validateScopeStream(stream, scope, MAX_HISTORY_LIMIT);
|
|
103
106
|
return { kind: "present", stream };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type Snapshot } from "./snapshot.ts";
|
|
1
|
+
import { type InactiveMode, type Snapshot } from "./snapshot.ts";
|
|
2
2
|
export declare function startEpisode(bootstrap: boolean): Snapshot;
|
|
3
3
|
/** Re-enable a branch checkpoint without discarding its runtime config or provenance. */
|
|
4
4
|
export declare function resumeEpisode(snapshot: Snapshot, bootstrap: boolean): Snapshot;
|
|
5
|
-
/**
|
|
6
|
-
export declare function
|
|
5
|
+
/** Select an inactive mode for only this branch; durable defaults and session history remain intact. */
|
|
6
|
+
export declare function deactivateEpisode(snapshot: Snapshot, mode: InactiveMode): Snapshot;
|
|
7
7
|
/** Apply one user-run boundary while preserving checkpoint-owned runtime state. */
|
|
8
8
|
export declare function prepareRun(snapshot: Snapshot, prompt: string): boolean;
|
|
9
9
|
/** Retain the full prompt only while its run remains recoverable and unfinished. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { emptySnapshot } from "./snapshot.js";
|
|
2
2
|
export function startEpisode(bootstrap) {
|
|
3
|
-
const snapshot = emptySnapshot(
|
|
3
|
+
const snapshot = emptySnapshot("active");
|
|
4
4
|
if (bootstrap)
|
|
5
5
|
snapshot.meta.bootstrap = true;
|
|
6
6
|
return snapshot;
|
|
@@ -8,15 +8,15 @@ export function startEpisode(bootstrap) {
|
|
|
8
8
|
/** Re-enable a branch checkpoint without discarding its runtime config or provenance. */
|
|
9
9
|
export function resumeEpisode(snapshot, bootstrap) {
|
|
10
10
|
const next = structuredClone(snapshot);
|
|
11
|
-
next.config.
|
|
11
|
+
next.config.mode = "active";
|
|
12
12
|
if (bootstrap)
|
|
13
13
|
next.meta.bootstrap = true;
|
|
14
14
|
return next;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
export function
|
|
16
|
+
/** Select an inactive mode for only this branch; durable defaults and session history remain intact. */
|
|
17
|
+
export function deactivateEpisode(snapshot, mode) {
|
|
18
18
|
const next = structuredClone(snapshot);
|
|
19
|
-
next.config.
|
|
19
|
+
next.config.mode = mode;
|
|
20
20
|
return next;
|
|
21
21
|
}
|
|
22
22
|
/** Apply one user-run boundary while preserving checkpoint-owned runtime state. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { formatPatchStateArguments } from "./protocol.ts";
|
|
3
|
+
import { type StateFlowMode } from "./snapshot.ts";
|
|
3
4
|
import { type ModelState, type StateScope } from "./state.ts";
|
|
4
5
|
import { type StateFlowTelegramLoader } from "./telegram.ts";
|
|
5
6
|
export interface StateFlowExtensionOptions {
|
|
@@ -11,11 +12,8 @@ export interface StateFlowExtensionOptions {
|
|
|
11
12
|
telegram?: {
|
|
12
13
|
load?: StateFlowTelegramLoader;
|
|
13
14
|
};
|
|
14
|
-
/** Test/SDK
|
|
15
|
-
|
|
16
|
-
bootstrap?: boolean;
|
|
17
|
-
tools?: boolean;
|
|
18
|
-
};
|
|
15
|
+
/** Test/SDK override of the default mode for new sessions; repository config remains the Pi default. */
|
|
16
|
+
mode?: StateFlowMode;
|
|
19
17
|
}
|
|
20
18
|
export { formatPatchStateArguments };
|
|
21
19
|
export declare const PATCH_STATE_TOOL_NAME = "patch_state";
|