libpetri 1.5.1 → 1.8.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/dist/debug/index.d.ts +237 -15
- package/dist/debug/index.js +236 -45
- package/dist/debug/index.js.map +1 -1
- package/dist/doclet/index.d.ts +1 -1
- package/dist/{event-store-Y8q_wapJ.d.ts → event-store-BnyHh3TF.d.ts} +1 -1
- package/dist/export/index.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +28 -6
- package/dist/index.js.map +1 -1
- package/dist/{petri-net-C3Jy5HCt.d.ts → petri-net-D-GN9g_D.d.ts} +31 -4
- package/dist/verification/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/debug/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Writable } from 'node:stream';
|
|
2
|
-
import { a as PetriNet, b as Transition, T as Token } from '../petri-net-
|
|
3
|
-
import { E as EventStore, N as NetEvent } from '../event-store-
|
|
2
|
+
import { a as PetriNet, b as Transition, T as Token } from '../petri-net-D-GN9g_D.js';
|
|
3
|
+
import { E as EventStore, N as NetEvent } from '../event-store-BnyHh3TF.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Commands sent from debug UI client to server via WebSocket.
|
|
@@ -34,6 +34,8 @@ type DebugCommand = {
|
|
|
34
34
|
readonly type: 'listSessions';
|
|
35
35
|
readonly limit?: number;
|
|
36
36
|
readonly activeOnly?: boolean;
|
|
37
|
+
/** Optional tag filter (AND semantics). Empty or missing matches all. (libpetri 1.6.0+) */
|
|
38
|
+
readonly tagFilter?: Readonly<Record<string, string>>;
|
|
37
39
|
} | {
|
|
38
40
|
readonly type: 'seek';
|
|
39
41
|
readonly sessionId: string;
|
|
@@ -94,11 +96,29 @@ interface SessionSummary {
|
|
|
94
96
|
readonly startTime: string;
|
|
95
97
|
readonly active: boolean;
|
|
96
98
|
readonly eventCount: number;
|
|
99
|
+
/** User-defined session tags. Empty object if none. (libpetri 1.6.0+) */
|
|
100
|
+
readonly tags?: Readonly<Record<string, string>>;
|
|
101
|
+
/** ISO-8601 end time, present only for completed sessions. (libpetri 1.6.0+) */
|
|
102
|
+
readonly endTime?: string;
|
|
103
|
+
/** Session duration in milliseconds, present only for completed sessions. (libpetri 1.6.0+) */
|
|
104
|
+
readonly durationMs?: number;
|
|
97
105
|
}
|
|
98
106
|
interface TokenInfo {
|
|
99
107
|
readonly id: string | null;
|
|
100
108
|
readonly type: string;
|
|
109
|
+
/**
|
|
110
|
+
* `String(value)` form — stable display field that the bundled debug UI relies on.
|
|
111
|
+
* Always populated unless compact mode strips values.
|
|
112
|
+
*/
|
|
101
113
|
readonly value: string | null;
|
|
114
|
+
/**
|
|
115
|
+
* Structured JSON representation of the token value when the value is a plain
|
|
116
|
+
* JSON-friendly object / enum-like string / primitive. Populated alongside `value`
|
|
117
|
+
* (not instead of) so LLM-facing consumers can project typed fields without parsing
|
|
118
|
+
* the stringified form. Omitted from the wire when absent.
|
|
119
|
+
* (libpetri 1.8.0+)
|
|
120
|
+
*/
|
|
121
|
+
readonly structured?: unknown;
|
|
102
122
|
readonly timestamp: string | null;
|
|
103
123
|
}
|
|
104
124
|
interface NetEventInfo {
|
|
@@ -320,6 +340,15 @@ interface DebugSession {
|
|
|
320
340
|
readonly startTime: number;
|
|
321
341
|
readonly active: boolean;
|
|
322
342
|
readonly importedStructure: NetStructure | null;
|
|
343
|
+
/** Stamped on first `complete()`. Undefined while the session is active. (libpetri 1.6.0+) */
|
|
344
|
+
readonly endTime?: number;
|
|
345
|
+
/**
|
|
346
|
+
* Per-session tag storage, mutated in place by the registry. The reference is
|
|
347
|
+
* readonly but the underlying object is not — prefer
|
|
348
|
+
* {@link DebugSessionRegistry.tag}/{@link DebugSessionRegistry.tagsFor}
|
|
349
|
+
* over direct access.
|
|
350
|
+
*/
|
|
351
|
+
readonly tags: Record<string, string>;
|
|
323
352
|
}
|
|
324
353
|
/** Builds the net structure from a session's stored place and transition info. */
|
|
325
354
|
declare function buildNetStructure(session: DebugSession): NetStructure;
|
|
@@ -333,26 +362,54 @@ declare class DebugSessionRegistry {
|
|
|
333
362
|
/**
|
|
334
363
|
* Registers a new debug session for the given Petri net.
|
|
335
364
|
* Generates DOT diagram and extracts net structure.
|
|
365
|
+
*
|
|
366
|
+
* @param sessionId unique session id
|
|
367
|
+
* @param net the Petri net being executed
|
|
368
|
+
* @param tags optional user-defined tags (libpetri 1.6.0+) — e.g. `{channel: 'voice'}`
|
|
336
369
|
*/
|
|
337
|
-
register(sessionId: string, net: PetriNet): DebugSession;
|
|
370
|
+
register(sessionId: string, net: PetriNet, tags?: Readonly<Record<string, string>>): DebugSession;
|
|
338
371
|
/**
|
|
339
372
|
* Marks a session as completed (no longer active) and notifies completion listeners.
|
|
373
|
+
*
|
|
374
|
+
* <p>Stamps `endTime = Date.now()` on the first completion. Idempotent: subsequent
|
|
375
|
+
* calls preserve the existing endTime. (libpetri 1.6.0+)
|
|
340
376
|
*/
|
|
341
377
|
complete(sessionId: string): void;
|
|
342
|
-
/** Removes a session from the registry. */
|
|
378
|
+
/** Removes a session from the registry. Tags die with the session. */
|
|
343
379
|
remove(sessionId: string): DebugSession | undefined;
|
|
344
380
|
/** Returns a session by ID. */
|
|
345
381
|
getSession(sessionId: string): DebugSession | undefined;
|
|
382
|
+
/**
|
|
383
|
+
* Sets or overwrites a single tag on a session. (libpetri 1.6.0+)
|
|
384
|
+
*
|
|
385
|
+
* Tags accumulate until the session is removed. Setting a key that already
|
|
386
|
+
* exists replaces its value.
|
|
387
|
+
*
|
|
388
|
+
* If `sessionId` is not a currently-registered session the call is a no-op.
|
|
389
|
+
* A tag write that races with {@link remove} is harmless — the write lands on
|
|
390
|
+
* the now-orphaned session object and is garbage collected along with it.
|
|
391
|
+
*/
|
|
392
|
+
tag(sessionId: string, key: string, value: string): void;
|
|
393
|
+
/**
|
|
394
|
+
* Returns a snapshot of the tags attached to a session. Returns an empty
|
|
395
|
+
* object if the session has no tags or does not exist. (libpetri 1.6.0+)
|
|
396
|
+
*/
|
|
397
|
+
tagsFor(sessionId: string): Readonly<Record<string, string>>;
|
|
346
398
|
/** Lists sessions, ordered by start time (most recent first). */
|
|
347
|
-
listSessions(limit: number): readonly DebugSession[];
|
|
399
|
+
listSessions(limit: number, tagFilter?: Readonly<Record<string, string>>): readonly DebugSession[];
|
|
348
400
|
/** Lists only active sessions. */
|
|
349
|
-
listActiveSessions(limit: number): readonly DebugSession[];
|
|
401
|
+
listActiveSessions(limit: number, tagFilter?: Readonly<Record<string, string>>): readonly DebugSession[];
|
|
350
402
|
/** Total number of sessions. */
|
|
351
403
|
get size(): number;
|
|
352
404
|
/**
|
|
353
405
|
* Registers an imported (archived) session as an inactive, read-only session.
|
|
406
|
+
*
|
|
407
|
+
* @param endTime when the original session ended (libpetri 1.6.0+)
|
|
408
|
+
* @param tags user-defined tags attached to the imported session (libpetri 1.6.0+)
|
|
354
409
|
*/
|
|
355
|
-
registerImported(sessionId: string, netName: string, dotDiagram: string, structure: NetStructure, eventStore: DebugEventStore, startTime: number): DebugSession;
|
|
410
|
+
registerImported(sessionId: string, netName: string, dotDiagram: string, structure: NetStructure, eventStore: DebugEventStore, startTime: number, endTime?: number, tags?: Readonly<Record<string, string>>): DebugSession;
|
|
411
|
+
/** AND-match: all filter entries must exactly match the session's tags. */
|
|
412
|
+
private matchesTagFilter;
|
|
356
413
|
/** Notifies all completion listeners. Exceptions are caught and logged. */
|
|
357
414
|
private notifyCompletionListeners;
|
|
358
415
|
/** Evicts oldest inactive sessions if at capacity. */
|
|
@@ -388,6 +445,7 @@ declare class DebugProtocolHandler {
|
|
|
388
445
|
/** Handles a command from a connected client. */
|
|
389
446
|
handleCommand(clientId: string, command: DebugCommand): void;
|
|
390
447
|
private handleListSessions;
|
|
448
|
+
private toProtocolSummary;
|
|
391
449
|
private handleSubscribe;
|
|
392
450
|
private subscribeLive;
|
|
393
451
|
private subscribeReplay;
|
|
@@ -441,7 +499,23 @@ declare class MarkingCache {
|
|
|
441
499
|
|
|
442
500
|
/** Converts a NetEvent to a serializable NetEventInfo. */
|
|
443
501
|
declare function toEventInfo(event: NetEvent, compact?: boolean): NetEventInfo;
|
|
444
|
-
/**
|
|
502
|
+
/**
|
|
503
|
+
* Converts a Token to a serializable {@link TokenInfo}.
|
|
504
|
+
*
|
|
505
|
+
* @remarks
|
|
506
|
+
* The emitted `type` is `value.constructor.name` for objects and `typeof value`
|
|
507
|
+
* for primitives — a *simple name*, not a fully-qualified type identifier.
|
|
508
|
+
* TypeScript has no portable FQN, so cross-language replay from TypeScript
|
|
509
|
+
* archives into a Java reader loses the original type identity (Java's
|
|
510
|
+
* `Class.forName` will fail on simple names) and falls through to the
|
|
511
|
+
* `Token<JsonNode>` graceful-degradation path. The `structured` payload
|
|
512
|
+
* survives intact across languages.
|
|
513
|
+
*
|
|
514
|
+
* The v3 archive body format described in [EVT-025](../../../spec/08-events-observability.md)
|
|
515
|
+
* always emits `structured` alongside `value` so the bundled debug UI keeps
|
|
516
|
+
* rendering while LLM-facing consumers get typed fields. See {@link structuredValue}
|
|
517
|
+
* for the projection rules.
|
|
518
|
+
*/
|
|
445
519
|
declare function tokenInfo(token: Token<unknown>): TokenInfo;
|
|
446
520
|
/** Converts a Token to compact TokenInfo (type only, no value). */
|
|
447
521
|
declare function compactTokenInfo(token: Token<unknown>): TokenInfo;
|
|
@@ -468,19 +542,115 @@ declare class DebugAwareEventStore implements EventStore {
|
|
|
468
542
|
|
|
469
543
|
/**
|
|
470
544
|
* Metadata header for a session archive file.
|
|
545
|
+
*
|
|
546
|
+
* Discriminated union across format versions so callers can pattern-match on
|
|
547
|
+
* `archive.version` to access v2-only fields with type narrowing:
|
|
548
|
+
*
|
|
549
|
+
* ```ts
|
|
550
|
+
* const archive = reader.readMetadata(bytes);
|
|
551
|
+
* if (archive.version === 2) {
|
|
552
|
+
* console.log(archive.tags, archive.endTime, archive.metadata.hasErrors);
|
|
553
|
+
* }
|
|
554
|
+
* ```
|
|
555
|
+
*
|
|
556
|
+
* ## Version contract
|
|
557
|
+
*
|
|
558
|
+
* - **v1** (libpetri 1.5.x–1.6.x): original format. Header carries `sessionId`,
|
|
559
|
+
* `netName`, `dotDiagram`, `startTime`, `eventCount`, and net `structure`.
|
|
560
|
+
* - **v2** (libpetri 1.7.x): adds `endTime`, user-defined `tags`, and pre-computed
|
|
561
|
+
* {@link SessionMetadata}. Events inside v2 archives use the legacy `toString`-based
|
|
562
|
+
* token format — types are erased on disk.
|
|
563
|
+
* - **v3** (libpetri 1.8.0+): same header shape as v2. Differs in the event body —
|
|
564
|
+
* token values are serialized with a `structured` JSON payload in addition to the
|
|
565
|
+
* legacy `value` string, so consumers that understand the original shape can
|
|
566
|
+
* surface typed fields without parsing the `toString` form.
|
|
567
|
+
*
|
|
568
|
+
* The {@link SessionArchiveReader} peeks the `version` field via a lenient JSON
|
|
569
|
+
* parse and dispatches to the correct concrete type. All three versions coexist
|
|
570
|
+
* in the same storage bucket.
|
|
471
571
|
*/
|
|
472
572
|
|
|
473
|
-
|
|
474
|
-
|
|
573
|
+
/** Common fields shared by v1 and v2 archive headers. */
|
|
574
|
+
interface SessionArchiveBase {
|
|
475
575
|
readonly sessionId: string;
|
|
476
576
|
readonly netName: string;
|
|
477
577
|
readonly dotDiagram: string;
|
|
578
|
+
/** ISO-8601 instant the session started. */
|
|
478
579
|
readonly startTime: string;
|
|
479
580
|
readonly eventCount: number;
|
|
480
581
|
readonly structure: NetStructure;
|
|
481
582
|
}
|
|
482
|
-
/**
|
|
483
|
-
|
|
583
|
+
/** Legacy v1 archive header (libpetri 1.5.x–1.6.x). */
|
|
584
|
+
interface SessionArchiveV1 extends SessionArchiveBase {
|
|
585
|
+
readonly version: 1;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* v2 archive header (libpetri 1.7.0+). Adds end time, tags, and pre-computed
|
|
589
|
+
* metadata so listing tools and samplers can filter/aggregate without scanning
|
|
590
|
+
* the event body.
|
|
591
|
+
*/
|
|
592
|
+
interface SessionArchiveV2 extends SessionArchiveBase {
|
|
593
|
+
readonly version: 2;
|
|
594
|
+
/** ISO-8601 instant the session ended. Undefined for sessions archived while still active. */
|
|
595
|
+
readonly endTime?: string;
|
|
596
|
+
/** User-defined session tags (e.g., `{channel: "voice"}`). Always present; may be empty. */
|
|
597
|
+
readonly tags: Readonly<Record<string, string>>;
|
|
598
|
+
/** Pre-computed aggregate stats. Always present; `emptyMetadata()` for no-event sessions. */
|
|
599
|
+
readonly metadata: SessionMetadata;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* v3 archive header (libpetri 1.8.0+). Structurally identical to `SessionArchiveV2`;
|
|
603
|
+
* the version bump signals that the event body carries `structured` token payloads
|
|
604
|
+
* alongside the legacy `value` string.
|
|
605
|
+
*/
|
|
606
|
+
interface SessionArchiveV3 extends SessionArchiveBase {
|
|
607
|
+
readonly version: 3;
|
|
608
|
+
readonly endTime?: string;
|
|
609
|
+
readonly tags: Readonly<Record<string, string>>;
|
|
610
|
+
readonly metadata: SessionMetadata;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Discriminated union of all supported archive header versions.
|
|
614
|
+
*
|
|
615
|
+
* Type-narrowing example:
|
|
616
|
+
* ```ts
|
|
617
|
+
* if (archive.version >= 2) {
|
|
618
|
+
* // TS knows archive has tags / endTime / metadata here.
|
|
619
|
+
* }
|
|
620
|
+
* ```
|
|
621
|
+
*/
|
|
622
|
+
type SessionArchive = SessionArchiveV1 | SessionArchiveV2 | SessionArchiveV3;
|
|
623
|
+
/** Version written by default by {@link SessionArchiveWriter.write} (latest supported). */
|
|
624
|
+
declare const CURRENT_VERSION = 3;
|
|
625
|
+
/**
|
|
626
|
+
* Pre-computed aggregate statistics attached to a v2 session archive header.
|
|
627
|
+
*
|
|
628
|
+
* Computed once during archive write by a single-pass scan of the event store.
|
|
629
|
+
* Readers can answer `hasErrors`, histogram, and first/last timestamp queries
|
|
630
|
+
* without iterating the event stream — enabling cheap triage, sampling, and
|
|
631
|
+
* listing of many archives.
|
|
632
|
+
*
|
|
633
|
+
* For v1 archives (no pre-computed metadata), callers can recompute on-demand
|
|
634
|
+
* via {@link computeMetadata}.
|
|
635
|
+
*/
|
|
636
|
+
interface SessionMetadata {
|
|
637
|
+
/**
|
|
638
|
+
* Count of events per `NetEvent` subtype name (PascalCase, matching the
|
|
639
|
+
* wire format used by `NetEventInfo.type` — e.g. `TransitionStarted -> 412`).
|
|
640
|
+
* Keys are stored in alphabetical order for deterministic JSON output.
|
|
641
|
+
*/
|
|
642
|
+
readonly eventTypeHistogram: Readonly<Record<string, number>>;
|
|
643
|
+
/** ISO-8601 timestamp of the oldest event, or undefined if the session had no events. */
|
|
644
|
+
readonly firstEventTime?: string;
|
|
645
|
+
/** ISO-8601 timestamp of the newest event, or undefined if the session had no events. */
|
|
646
|
+
readonly lastEventTime?: string;
|
|
647
|
+
/**
|
|
648
|
+
* True if the session contains at least one error-signal event
|
|
649
|
+
* (`TransitionFailed`, `TransitionTimedOut`, `ActionTimedOut`, or
|
|
650
|
+
* a `LogMessage` at level `ERROR`).
|
|
651
|
+
*/
|
|
652
|
+
readonly hasErrors: boolean;
|
|
653
|
+
}
|
|
484
654
|
|
|
485
655
|
/**
|
|
486
656
|
* File-system backed storage for session archives.
|
|
@@ -501,21 +671,73 @@ declare class FileSessionArchiveStorage implements SessionArchiveStorage {
|
|
|
501
671
|
* Writes a debug session to a length-prefixed binary archive format.
|
|
502
672
|
*
|
|
503
673
|
* Format (inside gzip):
|
|
504
|
-
* [4 bytes: metadata JSON length][N bytes: metadata JSON]
|
|
505
|
-
* [4 bytes: event JSON length][N bytes: event JSON]
|
|
674
|
+
* `[4 bytes: metadata JSON length][N bytes: metadata JSON]`
|
|
675
|
+
* `[4 bytes: event JSON length][N bytes: event JSON]`
|
|
506
676
|
* ...
|
|
507
677
|
* (EOF terminates the stream)
|
|
678
|
+
*
|
|
679
|
+
* ## Format selection
|
|
680
|
+
*
|
|
681
|
+
* `write()` defaults to {@link CURRENT_VERSION} (v3 as of libpetri 1.8.0).
|
|
682
|
+
* Callers that need to emit legacy archives — compatibility tests or readers
|
|
683
|
+
* pinned to older libpetri versions — can call `writeV1()` or `writeV2()`.
|
|
684
|
+
*
|
|
685
|
+
* Note: all writers now emit the v3 token body format (structured alongside
|
|
686
|
+
* value-string) regardless of header version. A 1.8.0+ writer cannot produce
|
|
687
|
+
* byte-for-byte 1.7.x event bodies.
|
|
688
|
+
*
|
|
689
|
+
* Cross-language note: the `type` field in each serialized `TokenInfo` is
|
|
690
|
+
* `value.constructor.name` — a simple name, not an FQN. Replaying a TypeScript
|
|
691
|
+
* archive through the Java reader therefore cannot reconstruct the original
|
|
692
|
+
* typed token (Java needs an FQN to `Class.forName`); Java falls through to
|
|
693
|
+
* `Token<JsonNode>` preserving the `structured` JSON payload. See
|
|
694
|
+
* {@link tokenInfo} for the full asymmetry and the [EVT-025](../../../../spec/08-events-observability.md)
|
|
695
|
+
* spec entry for the full wire-format contract.
|
|
508
696
|
*/
|
|
509
697
|
|
|
510
698
|
declare class SessionArchiveWriter {
|
|
511
699
|
/**
|
|
512
|
-
* Writes a complete session archive
|
|
700
|
+
* Writes a complete session archive in the current format (v3 as of 1.8.0)
|
|
701
|
+
* and returns the compressed bytes.
|
|
513
702
|
*/
|
|
514
703
|
write(session: DebugSession): Buffer;
|
|
704
|
+
/**
|
|
705
|
+
* Writes a session in the legacy v1 format. Use only for compatibility
|
|
706
|
+
* testing or when producing archives for consumers pinned to libpetri ≤ 1.6.1.
|
|
707
|
+
*/
|
|
708
|
+
writeV1(session: DebugSession): Buffer;
|
|
709
|
+
/**
|
|
710
|
+
* Writes a session in the v2 format — richer header with `endTime`, `tags`,
|
|
711
|
+
* and pre-computed {@link SessionMetadata}.
|
|
712
|
+
*
|
|
713
|
+
* Two passes over the event store: one to compute metadata, one to serialize
|
|
714
|
+
* events. `DebugEventStore` stores events in a plain readonly array and its
|
|
715
|
+
* `[Symbol.iterator]()` returns a fresh array iterator each call, so both
|
|
716
|
+
* passes walk the same sequence from the start.
|
|
717
|
+
*/
|
|
718
|
+
writeV2(session: DebugSession): Buffer;
|
|
719
|
+
/**
|
|
720
|
+
* Writes a session in the v3 format — same header shape as v2, with version=3
|
|
721
|
+
* signalling that token payloads carry a `structured` field alongside the
|
|
722
|
+
* legacy `value` string (see {@link tokenInfo}).
|
|
723
|
+
*/
|
|
724
|
+
writeV3(session: DebugSession): Buffer;
|
|
725
|
+
/**
|
|
726
|
+
* Shared framing logic: length-prefixed header JSON, then length-prefixed
|
|
727
|
+
* event JSON, then gzip. Both v1 and v2 archives use the identical event
|
|
728
|
+
* wire format, so the body loop is version-agnostic.
|
|
729
|
+
*/
|
|
730
|
+
private writeFramed;
|
|
515
731
|
}
|
|
516
732
|
|
|
517
733
|
/**
|
|
518
734
|
* Reads session archives from length-prefixed binary format.
|
|
735
|
+
*
|
|
736
|
+
* Handles both v1 (libpetri 1.5.x–1.6.x) and v2 (libpetri 1.7.0+) archives via
|
|
737
|
+
* a lenient "version probe": parse the header JSON once, switch on the
|
|
738
|
+
* `version` field, narrow to the correct concrete type, and normalize missing
|
|
739
|
+
* optional fields to their defaults. Events inside the body use the same wire
|
|
740
|
+
* format across versions, so the event read path is shared.
|
|
519
741
|
*/
|
|
520
742
|
|
|
521
743
|
interface ImportedSession {
|