@llblab/pi-kit 0.26.0 → 0.27.1
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/BACKLOG.md +4 -2
- package/CHANGELOG.md +9 -0
- package/README.md +6 -6
- package/node_modules/@llblab/pi-claude-usage/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +4 -0
- package/node_modules/@llblab/pi-claude-usage/README.md +3 -1
- package/node_modules/@llblab/pi-claude-usage/lib/status.ts +3 -8
- package/node_modules/@llblab/pi-claude-usage/lib/telegram.ts +15 -1
- package/node_modules/@llblab/pi-claude-usage/package.json +1 -1
- package/node_modules/@llblab/pi-codex-usage/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +4 -0
- package/node_modules/@llblab/pi-codex-usage/README.md +2 -2
- package/node_modules/@llblab/pi-codex-usage/lib/status.ts +3 -11
- package/node_modules/@llblab/pi-codex-usage/lib/telegram.ts +15 -0
- package/node_modules/@llblab/pi-codex-usage/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +12 -5
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +9 -0
- package/node_modules/@llblab/pi-state-flow/README.md +116 -34
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +24 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +80 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +17 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +40 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +149 -298
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +29 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +58 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/operation.d.ts +37 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/operation.js +59 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.d.ts +31 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.js +117 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +7 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +28 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +6 -1
- package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +14 -6
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/README.md +19 -9
- package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +4 -4
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +644 -91
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +116 -37
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +118 -21
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +68 -8
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +88 -14
- package/node_modules/@llblab/pi-state-flow/docs/performance.md +83 -66
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +391 -62
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +317 -62
- package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +85 -1
- package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +47 -0
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +161 -295
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +63 -0
- package/node_modules/@llblab/pi-state-flow/lib/operation.ts +75 -0
- package/node_modules/@llblab/pi-state-flow/lib/ownership.ts +120 -0
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +7 -8
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +1 -2
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +29 -0
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +5 -1
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +14 -6
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +2 -2
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -0
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +10 -0
- package/node_modules/@llblab/pi-telegram/README.md +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +4 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +16 -12
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +7 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +12 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +137 -83
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +26 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.d.ts +57 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +109 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/model.js +2 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/status.d.ts +3 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/status.js +31 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +4 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +17 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +2 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +48 -12
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +6 -5
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +2 -0
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +2 -2
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +4 -0
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +17 -10
- package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +8 -2
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +135 -97
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +25 -0
- package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +140 -4
- package/node_modules/@llblab/pi-telegram/lib/model.ts +2 -4
- package/node_modules/@llblab/pi-telegram/lib/status.ts +30 -1
- package/node_modules/@llblab/pi-telegram/lib/sync.ts +4 -4
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +21 -3
- package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +46 -13
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +5 -5
|
@@ -6,8 +6,11 @@ import {
|
|
|
6
6
|
type ArtifactInvalidationRequest,
|
|
7
7
|
type ArtifactSourceFingerprint,
|
|
8
8
|
type ArtifactSourceIdentity,
|
|
9
|
+
ORDINARY_ARTIFACT_COMPILER,
|
|
10
|
+
type ArtifactProvenanceRegistry,
|
|
9
11
|
} from "./artifact.ts";
|
|
10
|
-
import { isObject } from "./json.ts";
|
|
12
|
+
import { isObject, type JsonObject } from "./json.ts";
|
|
13
|
+
import type { AtomicScopePatches, ScopedSemanticStates, ScopedStates, StateScope } from "./state.ts";
|
|
11
14
|
|
|
12
15
|
/** Why the caller is considering source-body acquisition. */
|
|
13
16
|
export type ArtifactAcquisitionIntent =
|
|
@@ -154,3 +157,84 @@ export function decideArtifactAcquisition(
|
|
|
154
157
|
return { kind: "read-source", reason: "maintenance" };
|
|
155
158
|
}
|
|
156
159
|
}
|
|
160
|
+
|
|
161
|
+
export const SOURCE_CHANGED_HINT = "Source changed since this artifact was compiled. Read and recompile it before relying on it.";
|
|
162
|
+
|
|
163
|
+
const SCOPES = ["global", "cwd", "session"] as const;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* One selected branch's ordinary-artifact acquisition plan: runtime-observed
|
|
167
|
+
* invalidations, their model hints and the read tracker correlated to them.
|
|
168
|
+
* The tracker's candidates always equal the current invalidation plan.
|
|
169
|
+
*/
|
|
170
|
+
export class ArtifactAcquisitionState {
|
|
171
|
+
readonly reads = new ArtifactReadTracker();
|
|
172
|
+
#invalidations: ArtifactInvalidationRequest[] = [];
|
|
173
|
+
#hints: Record<string, string> = {};
|
|
174
|
+
|
|
175
|
+
get invalidations(): readonly ArtifactInvalidationRequest[] { return this.#invalidations; }
|
|
176
|
+
get hints(): Record<string, string> { return this.#hints; }
|
|
177
|
+
|
|
178
|
+
/** Drop the invalidation plan; hints remain until the next refresh. */
|
|
179
|
+
clearInvalidations(): void { this.#setInvalidations([]); }
|
|
180
|
+
|
|
181
|
+
/** Forget plan and hints when no memory view is selected. */
|
|
182
|
+
reset(): void {
|
|
183
|
+
this.#hints = {};
|
|
184
|
+
this.#setInvalidations([]);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Re-observe exact registered sources for the selected scope artifacts. */
|
|
188
|
+
refresh(states: ScopedStates, provenance: (scope: StateScope) => ArtifactProvenanceRegistry): void {
|
|
189
|
+
const paths = new Set<string>();
|
|
190
|
+
for (const scope of SCOPES) for (const path of Object.keys(states[scope].artifacts)) paths.add(path);
|
|
191
|
+
const observations = new Map(inspectRegisteredArtifactPaths(paths).map((observation) => [observation.path, observation]));
|
|
192
|
+
const hints: Record<string, string> = {};
|
|
193
|
+
const invalidations = new Map<string, ArtifactInvalidationRequest>();
|
|
194
|
+
for (const scope of SCOPES) {
|
|
195
|
+
const registry = provenance(scope);
|
|
196
|
+
for (const [path, metadata] of Object.entries(states[scope].artifacts)) {
|
|
197
|
+
// A narrower owner replaces broader evidence for the same path.
|
|
198
|
+
delete hints[path];
|
|
199
|
+
invalidations.delete(path);
|
|
200
|
+
if (metadata.kind === "skill") continue;
|
|
201
|
+
const observed = observations.get(path);
|
|
202
|
+
if (observed?.kind !== "present") continue;
|
|
203
|
+
const need = classifyArtifactCompilationNeed({ path, scope, sourceFingerprint: observed.fingerprint }, metadata, ORDINARY_ARTIFACT_COMPILER, false, registry[path]);
|
|
204
|
+
if (need.kind !== "requires-compilation") continue;
|
|
205
|
+
if (need.reason === "source-changed") hints[path] = SOURCE_CHANGED_HINT;
|
|
206
|
+
invalidations.set(path, { path, scope, reason: need.reason });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
this.#hints = hints;
|
|
210
|
+
this.#setInvalidations([...invalidations.values()].sort((left, right) => left.path.localeCompare(right.path)));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Accepted compilations leave the plan; correlated read evidence is single-use. */
|
|
214
|
+
acceptAcquired(paths: ReadonlySet<string> = new Set(this.reads.successful.keys())): void {
|
|
215
|
+
this.#setInvalidations(this.#invalidations.filter(({ path }) => !paths.has(path)));
|
|
216
|
+
this.reads.clear();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#setInvalidations(invalidations: ArtifactInvalidationRequest[]): void {
|
|
220
|
+
this.#invalidations = invalidations;
|
|
221
|
+
this.reads.setCandidates(invalidations);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Deletion patches for registered artifacts whose exact source is observed missing, in every owning scope. */
|
|
226
|
+
export function missingArtifactRemovals(states: ScopedSemanticStates): AtomicScopePatches {
|
|
227
|
+
const owners = new Map<string, StateScope[]>();
|
|
228
|
+
for (const scope of SCOPES) for (const path of Object.keys(states[scope].artifacts ?? {})) {
|
|
229
|
+
owners.set(path, [...owners.get(path) ?? [], scope]);
|
|
230
|
+
}
|
|
231
|
+
const removals: AtomicScopePatches = {};
|
|
232
|
+
for (const observation of inspectRegisteredArtifactPaths(owners.keys())) {
|
|
233
|
+
if (observation.kind !== "missing") continue;
|
|
234
|
+
for (const scope of owners.get(observation.path) ?? []) {
|
|
235
|
+
const artifacts = (removals[scope]?.artifacts ?? {}) as JsonObject;
|
|
236
|
+
removals[scope] = { ...(removals[scope] ?? {}), artifacts: { ...artifacts, [observation.path]: null } };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return removals;
|
|
240
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
2
3
|
import { estimateTokens, type CompactionResult } from "@earendil-works/pi-coding-agent";
|
|
3
4
|
|
|
@@ -97,3 +98,49 @@ export function stateFlowCompactionResult(
|
|
|
97
98
|
details: structuredClone(plan.details),
|
|
98
99
|
};
|
|
99
100
|
}
|
|
101
|
+
|
|
102
|
+
const STATE_FLOW_COMPACTION_MARKER_PREFIX = "state-flow-boundary:";
|
|
103
|
+
|
|
104
|
+
type CompactionEvent = Parameters<typeof stateFlowCompactionResult>[2];
|
|
105
|
+
|
|
106
|
+
/** Completed-history compaction request state owned by one extension instance. */
|
|
107
|
+
export class StateFlowCompactionRequests {
|
|
108
|
+
#plan: StateFlowCompactionPlan | undefined;
|
|
109
|
+
#marker: string | undefined;
|
|
110
|
+
#inFlight = false;
|
|
111
|
+
#stopped = false;
|
|
112
|
+
readonly #prefix = `${STATE_FLOW_COMPACTION_MARKER_PREFIX}${randomUUID()}:`;
|
|
113
|
+
|
|
114
|
+
get inFlight(): boolean { return this.#inFlight; }
|
|
115
|
+
get stopped(): boolean { return this.#stopped; }
|
|
116
|
+
|
|
117
|
+
/** Permanently refuse owned requests (shutdown). */
|
|
118
|
+
stop(): void { this.#stopped = true; }
|
|
119
|
+
|
|
120
|
+
/** Drop the run-local plan; a stale callback can no longer clear a newer one. */
|
|
121
|
+
clear(): void {
|
|
122
|
+
this.#plan = undefined;
|
|
123
|
+
this.#inFlight = false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Install a plan and return its unique per-request marker. */
|
|
127
|
+
begin(plan: StateFlowCompactionPlan): string {
|
|
128
|
+
this.#plan = plan;
|
|
129
|
+
const marker = this.#marker = `${this.#prefix}${randomUUID()}`;
|
|
130
|
+
this.#inFlight = true;
|
|
131
|
+
return marker;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Native completion clears only its own request. */
|
|
135
|
+
finish(marker: string): void {
|
|
136
|
+
if (this.#marker === marker) this.clear();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Answer session_before_compact: foreign requests pass, stale or unpermitted owned ones cancel. */
|
|
140
|
+
resolve(event: CompactionEvent, permitted: boolean): ReturnType<typeof stateFlowCompactionResult> {
|
|
141
|
+
if (event.reason !== "manual" || !event.customInstructions?.startsWith(STATE_FLOW_COMPACTION_MARKER_PREFIX)) return undefined;
|
|
142
|
+
const marker = this.#marker;
|
|
143
|
+
if (!permitted || this.#stopped || !this.#plan || !marker || event.customInstructions !== marker) return { cancel: true };
|
|
144
|
+
return stateFlowCompactionResult(this.#plan, marker, event);
|
|
145
|
+
}
|
|
146
|
+
}
|