@llblab/pi-kit 0.22.2 → 0.23.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/CHANGELOG.md +12 -0
- package/README.md +5 -5
- package/node_modules/@llblab/pi-actors/AGENTS.md +4 -1
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +10 -0
- package/node_modules/@llblab/pi-actors/README.md +2 -2
- package/node_modules/@llblab/pi-actors/dist/index.js +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.js +2 -1
- package/node_modules/@llblab/pi-actors/dist/lib/paths.d.ts +6 -0
- package/node_modules/@llblab/pi-actors/dist/lib/paths.js +19 -1
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.js +11 -7
- package/node_modules/@llblab/pi-actors/dist/scripts/build-dist.mjs +94 -30
- package/node_modules/@llblab/pi-actors/docs/actor-inspector.md +1 -1
- package/node_modules/@llblab/pi-actors/index.ts +6 -3
- package/node_modules/@llblab/pi-actors/lib/inspector-overlay.ts +2 -1
- package/node_modules/@llblab/pi-actors/lib/paths.ts +27 -1
- package/node_modules/@llblab/pi-actors/lib/trace-projection.ts +13 -6
- package/node_modules/@llblab/pi-actors/package.json +3 -8
- package/node_modules/@llblab/pi-actors/scripts/build-dist.mjs +94 -30
- package/node_modules/@llblab/pi-grow-loop/AGENTS.md +10 -6
- package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +7 -0
- package/node_modules/@llblab/pi-grow-loop/README.md +2 -0
- package/node_modules/@llblab/pi-grow-loop/dist/index.d.ts +33 -0
- package/node_modules/@llblab/pi-grow-loop/dist/index.js +286 -0
- package/node_modules/@llblab/pi-grow-loop/dist/pi-grow-loop/index.d.ts +1 -0
- package/node_modules/@llblab/pi-grow-loop/dist/pi-grow-loop/index.js +1 -0
- package/node_modules/@llblab/pi-grow-loop/dist/skills/grow-loop/SKILL.md +117 -0
- package/node_modules/@llblab/pi-grow-loop/dist/skills/while-true/SKILL.md +233 -0
- package/node_modules/@llblab/pi-grow-loop/index.ts +67 -12
- package/node_modules/@llblab/pi-grow-loop/package.json +9 -8
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +23 -17
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +5 -3
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +11 -0
- package/node_modules/@llblab/pi-state-flow/README.md +18 -6
- package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/index.js +1 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.js +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +3 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +7 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.d.ts +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +54 -40
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +20 -20
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +755 -325
- 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 +14 -17
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +4 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +65 -23
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +16 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +32 -15
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +28 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +276 -26
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +5 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +36 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +1 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +3 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +11 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +150 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +14 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +52 -18
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +8 -8
- 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 +3 -1
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +53 -7
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +84 -44
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +12 -2
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +6 -4
- package/node_modules/@llblab/pi-state-flow/docs/performance.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +28 -8
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +41 -14
- package/node_modules/@llblab/pi-state-flow/index.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +5 -5
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +8 -3
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +57 -40
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +20 -20
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +719 -316
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +16 -18
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +60 -24
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +34 -21
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +290 -25
- package/node_modules/@llblab/pi-state-flow/lib/session.ts +37 -2
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +4 -1
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +141 -22
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +60 -19
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +8 -8
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +3 -1
- package/node_modules/@llblab/pi-telegram/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +5 -0
- package/node_modules/@llblab/pi-telegram/README.md +2 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/skills.d.ts +7 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/skills.js +32 -7
- package/node_modules/@llblab/pi-telegram/dist/package.json +3 -8
- package/node_modules/@llblab/pi-telegram/lib/skills.ts +43 -7
- package/node_modules/@llblab/pi-telegram/package.json +3 -8
- package/node_modules/@llblab/pi-telegram/scripts/build-dist.mjs +103 -32
- package/package.json +7 -7
|
@@ -45,7 +45,7 @@ export function hasCwdMaterialization(cwd: string, repositoryRoot: string): bool
|
|
|
45
45
|
join(directory, CHECKPOINT_FILE), join(directory, PATCHES_FILE), join(directory, META_FILE),
|
|
46
46
|
], root);
|
|
47
47
|
if (checkpoint!.content !== undefined) return parseScopeStream(checkpoint!.content, patches!.content, "cwd", cwd, meta!.content) !== undefined;
|
|
48
|
-
if (patches!.content !== undefined) throw new Error(`State Flow tail has no provable checkpoint: ${directory}`);
|
|
48
|
+
if (patches!.content !== undefined) throw new Error(`State Flow tail has no provable checkpoint: ${JSON.stringify(directory)}`);
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -174,7 +174,7 @@ export function sessionRuntimePaths(cwd: string, sessionId: string, repositoryRo
|
|
|
174
174
|
export function loadScopeStream(cwd: string, sessionId: string, scope: StateScope, repositoryRoot: string, sessionKey = sessionId): ScopeStream | undefined {
|
|
175
175
|
const paths = temporalScopePaths(cwd, sessionId, scope, repositoryRoot, sessionKey);
|
|
176
176
|
if (readRegularBytes(join(paths.directory, STATE_FILE), repositoryRoot) !== undefined) {
|
|
177
|
-
throw new Error(`Unsupported State Flow storage format: ${paths.directory}`);
|
|
177
|
+
throw new Error(`Unsupported State Flow storage format: ${JSON.stringify(paths.directory)}`);
|
|
178
178
|
}
|
|
179
179
|
return parseScopeStream(readRegularFile(paths.checkpoint, repositoryRoot), readRegularFile(paths.patches, repositoryRoot), scope, scope === "cwd" ? cwd : undefined, readRegularFile(paths.meta, repositoryRoot));
|
|
180
180
|
}
|
|
@@ -205,7 +205,7 @@ export function temporalStateFileUpdates(
|
|
|
205
205
|
seen.add(scope);
|
|
206
206
|
const paths = temporalScopePaths(cwd, sessionId, scope, repositoryRoot, sessionKey);
|
|
207
207
|
if (readRegularBytes(join(paths.directory, STATE_FILE), repositoryRoot) !== undefined) {
|
|
208
|
-
throw new Error(`Unsupported State Flow storage format: ${paths.directory}`);
|
|
208
|
+
throw new Error(`Unsupported State Flow storage format: ${JSON.stringify(paths.directory)}`);
|
|
209
209
|
}
|
|
210
210
|
const sources = serializeScopeStream(view.scopes[scope], scope, scope === "cwd" ? cwd : undefined);
|
|
211
211
|
return [{ path: paths.checkpoint, content: sources.checkpoint }, { path: paths.patches, content: sources.patches }];
|
|
@@ -248,11 +248,11 @@ function parseMetadataDocument(source: string | undefined, label: string): Recor
|
|
|
248
248
|
|
|
249
249
|
/** Missing provenance is unavailable evidence, never corrupt state. Unknown metadata is preserved by writers. */
|
|
250
250
|
export function parseScopeProvenance(source: string | undefined, path: string): ArtifactProvenanceRegistry {
|
|
251
|
-
const value = parseMetadataDocument(source, `State Flow provenance file: ${path}`);
|
|
251
|
+
const value = parseMetadataDocument(source, `State Flow provenance file: ${JSON.stringify(path)}`);
|
|
252
252
|
if (Object.keys(value).length === 0) return {};
|
|
253
|
-
if (value.version !== 1 && value.version !== 2) throw new Error(`Invalid State Flow provenance document: ${path}`);
|
|
253
|
+
if (value.version !== 1 && value.version !== 2) throw new Error(`Invalid State Flow provenance document: ${JSON.stringify(path)}`);
|
|
254
254
|
if (!Object.hasOwn(value, "artifacts")) return {};
|
|
255
|
-
return parseArtifactProvenanceRegistry(value.artifacts, `State Flow provenance at ${path}`);
|
|
255
|
+
return parseArtifactProvenanceRegistry(value.artifacts, `State Flow provenance at ${JSON.stringify(path)}`);
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
export interface ScopePaths {
|
|
@@ -345,7 +345,7 @@ function missing(error: unknown): boolean {
|
|
|
345
345
|
function assertWithinRepository(path: string, repositoryRoot: string): void {
|
|
346
346
|
const child = relative(repositoryRoot, path);
|
|
347
347
|
if (child === "" || child === ".." || child.startsWith(`..${sep}`)) {
|
|
348
|
-
throw new Error(`Durable State Flow path escapes its repository: ${path}`);
|
|
348
|
+
throw new Error(`Durable State Flow path escapes its repository: ${JSON.stringify(path)}`);
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -367,7 +367,7 @@ function assertDirectoryChain(repositoryRoot: string, directory: string, create:
|
|
|
367
367
|
try {
|
|
368
368
|
const metadata = lstatSync(current);
|
|
369
369
|
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
370
|
-
throw new Error(`Durable State Flow directory is not a regular directory: ${current}`);
|
|
370
|
+
throw new Error(`Durable State Flow directory is not a regular directory: ${JSON.stringify(current)}`);
|
|
371
371
|
}
|
|
372
372
|
} catch (error) {
|
|
373
373
|
if (!missing(error)) throw error;
|
|
@@ -384,7 +384,7 @@ function readRegularBytes(path: string, repositoryRoot: string): Buffer | undefi
|
|
|
384
384
|
try {
|
|
385
385
|
descriptor = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
386
386
|
if (!fstatSync(descriptor).isFile()) {
|
|
387
|
-
throw new Error(`Durable State Flow path is not a regular file: ${path}`);
|
|
387
|
+
throw new Error(`Durable State Flow path is not a regular file: ${JSON.stringify(path)}`);
|
|
388
388
|
}
|
|
389
389
|
return readFileSync(descriptor);
|
|
390
390
|
} catch (error) {
|
|
@@ -392,7 +392,7 @@ function readRegularBytes(path: string, repositoryRoot: string): Buffer | undefi
|
|
|
392
392
|
if (error instanceof Error
|
|
393
393
|
&& "code" in error
|
|
394
394
|
&& (error as NodeJS.ErrnoException).code === "ELOOP") {
|
|
395
|
-
throw new Error(`Durable State Flow path is not a regular file: ${path}`);
|
|
395
|
+
throw new Error(`Durable State Flow path is not a regular file: ${JSON.stringify(path)}`);
|
|
396
396
|
}
|
|
397
397
|
throw error;
|
|
398
398
|
} finally {
|
|
@@ -416,7 +416,7 @@ function fileBase(path: string, repositoryRoot: string): DurableFileBase {
|
|
|
416
416
|
|
|
417
417
|
function assertCurrentBytes(path: string, root: string, expected: Uint8Array | undefined): void {
|
|
418
418
|
if (byteIdentity(readRegularBytes(path, root)) !== byteIdentity(expected)) {
|
|
419
|
-
throw new Error(`State Flow file conflict at ${path};
|
|
419
|
+
throw new Error(`State Flow file conflict at ${JSON.stringify(path)}; concurrent bytes preserved`);
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
|
|
@@ -424,7 +424,7 @@ function assertCurrentBytes(path: string, root: string, expected: Uint8Array | u
|
|
|
424
424
|
export function captureOwnedFileBases(paths: readonly string[], repositoryRoot: string): DurableFileBase[] {
|
|
425
425
|
const root = resolve(repositoryRoot);
|
|
426
426
|
return paths.map((path) => {
|
|
427
|
-
if (!isStateFlowOwnedPath(path, root)) throw new Error(`Cannot capture a non-State Flow path: ${path}`);
|
|
427
|
+
if (!isStateFlowOwnedPath(path, root)) throw new Error(`Cannot capture a non-State Flow path: ${JSON.stringify(path)}`);
|
|
428
428
|
return fileBase(resolve(path), root);
|
|
429
429
|
});
|
|
430
430
|
}
|
|
@@ -442,7 +442,7 @@ function prepareFile(path: string, repositoryRoot: string, content: string | und
|
|
|
442
442
|
assertDirectoryChain(repositoryRoot, dirname(path), true);
|
|
443
443
|
const original = readRegularBytes(path, repositoryRoot);
|
|
444
444
|
if (expected !== undefined && byteIdentity(original) !== expected.identity) {
|
|
445
|
-
throw new Error(`State Flow file conflict during preparation: ${path}`);
|
|
445
|
+
throw new Error(`State Flow file conflict during preparation: ${JSON.stringify(path)}`);
|
|
446
446
|
}
|
|
447
447
|
const temporary = join(dirname(path), `.${basename(path)}.${process.pid}.${randomUUID()}.tmp`);
|
|
448
448
|
const next = content === undefined ? undefined : Buffer.from(content);
|
|
@@ -502,7 +502,7 @@ export interface OwnedFileUpdate {
|
|
|
502
502
|
export function assertOwnedFileUpdates(updates: readonly OwnedFileUpdate[], repositoryRoot: string): void {
|
|
503
503
|
const root = resolve(repositoryRoot);
|
|
504
504
|
for (const update of updates) {
|
|
505
|
-
if (!isStateFlowOwnedPath(update.path, root)) throw new Error(`Cannot inspect a non-State Flow path: ${update.path}`);
|
|
505
|
+
if (!isStateFlowOwnedPath(update.path, root)) throw new Error(`Cannot inspect a non-State Flow path: ${JSON.stringify(update.path)}`);
|
|
506
506
|
assertCurrentBytes(update.path, root, update.content === undefined ? undefined : Buffer.from(update.content));
|
|
507
507
|
}
|
|
508
508
|
}
|
|
@@ -520,11 +520,11 @@ export function writeOwnedFileUpdates(
|
|
|
520
520
|
try {
|
|
521
521
|
for (const update of updates) {
|
|
522
522
|
const path = resolve(update.path);
|
|
523
|
-
if (!isStateFlowOwnedPath(path, root)) throw new Error(`Cannot update a non-State Flow path: ${path}`);
|
|
524
|
-
if (seen.has(path)) throw new Error(`Duplicate State Flow file update: ${path}`);
|
|
523
|
+
if (!isStateFlowOwnedPath(path, root)) throw new Error(`Cannot update a non-State Flow path: ${JSON.stringify(path)}`);
|
|
524
|
+
if (seen.has(path)) throw new Error(`Duplicate State Flow file update: ${JSON.stringify(path)}`);
|
|
525
525
|
seen.add(path);
|
|
526
526
|
const base = byPath.get(path);
|
|
527
|
-
if (base === undefined) throw new Error(`State Flow file update has no captured base: ${path}`);
|
|
527
|
+
if (base === undefined) throw new Error(`State Flow file update has no captured base: ${JSON.stringify(path)}`);
|
|
528
528
|
prepared.push(prepareFile(path, root, update.content, base));
|
|
529
529
|
}
|
|
530
530
|
} catch (error) {
|
|
@@ -546,19 +546,19 @@ export function restoreDurableFileBases(
|
|
|
546
546
|
for (const base of bases) {
|
|
547
547
|
assertWithinRepository(base.path, root);
|
|
548
548
|
if (!isStateFlowOwnedPath(base.path, root)) {
|
|
549
|
-
throw new Error(`Cannot restore a non-State Flow path: ${base.path}`);
|
|
549
|
+
throw new Error(`Cannot restore a non-State Flow path: ${JSON.stringify(base.path)}`);
|
|
550
550
|
}
|
|
551
551
|
}
|
|
552
552
|
for (const base of bases) {
|
|
553
553
|
const update = expected.get(resolve(base.path));
|
|
554
|
-
if (update === undefined) throw new Error(`Rollback has no published basis: ${base.path}`);
|
|
554
|
+
if (update === undefined) throw new Error(`Rollback has no published basis: ${JSON.stringify(base.path)}`);
|
|
555
555
|
assertCurrentBytes(base.path, root, update.content === undefined ? undefined : Buffer.from(update.content));
|
|
556
556
|
if (base.identity === "missing") {
|
|
557
557
|
rmSync(base.path, { force: true });
|
|
558
558
|
continue;
|
|
559
559
|
}
|
|
560
560
|
const original = base.bytes ?? (base.content === undefined ? undefined : Buffer.from(base.content));
|
|
561
|
-
if (original === undefined) throw new Error(`Durable State Flow base content is missing: ${base.path}`);
|
|
561
|
+
if (original === undefined) throw new Error(`Durable State Flow base content is missing: ${JSON.stringify(base.path)}`);
|
|
562
562
|
assertDirectoryChain(root, dirname(base.path), true);
|
|
563
563
|
const temporary = join(dirname(base.path), `.${basename(base.path)}.${process.pid}.${randomUUID()}.restore`);
|
|
564
564
|
try {
|