libpetri 0.3.4 → 0.4.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/chunk-ZE6RR3R4.js +412 -0
- package/dist/chunk-ZE6RR3R4.js.map +1 -0
- package/dist/debug/index.d.ts +408 -0
- package/dist/debug/index.js +1085 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/event-store-Y8q_wapJ.d.ts +152 -0
- package/dist/export/index.js +11 -398
- package/dist/export/index.js.map +1 -1
- package/dist/index.d.ts +3 -150
- package/dist/index.js +11 -11
- package/package.json +7 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/debug/debug-command.ts","../../src/debug/marking-cache.ts","../../src/debug/net-event-converter.ts","../../src/debug/debug-protocol-handler.ts","../../src/debug/debug-event-store.ts","../../src/debug/place-analysis.ts","../../src/debug/debug-session-registry.ts","../../src/debug/debug-aware-event-store.ts","../../src/debug/index.ts"],"sourcesContent":["/**\n * Commands sent from debug UI client to server via WebSocket.\n * TypeScript port of Java's DebugCommand sealed interface.\n */\n\nexport type SubscriptionMode = 'live' | 'replay';\n\nexport type BreakpointType =\n | 'TRANSITION_ENABLED'\n | 'TRANSITION_START'\n | 'TRANSITION_COMPLETE'\n | 'TRANSITION_FAIL'\n | 'TOKEN_ADDED'\n | 'TOKEN_REMOVED';\n\nexport interface BreakpointConfig {\n readonly id: string;\n readonly type: BreakpointType;\n readonly target: string | null;\n readonly enabled: boolean;\n}\n\nexport interface EventFilter {\n readonly eventTypes: readonly string[] | null;\n readonly transitionNames: readonly string[] | null;\n readonly placeNames: readonly string[] | null;\n}\n\nexport type DebugCommand =\n | { readonly type: 'subscribe'; readonly sessionId: string; readonly mode: SubscriptionMode; readonly fromIndex?: number }\n | { readonly type: 'unsubscribe'; readonly sessionId: string }\n | { readonly type: 'listSessions'; readonly limit?: number; readonly activeOnly?: boolean }\n | { readonly type: 'seek'; readonly sessionId: string; readonly timestamp: string }\n | { readonly type: 'playbackSpeed'; readonly sessionId: string; readonly speed: number }\n | { readonly type: 'filter'; readonly sessionId: string; readonly filter: EventFilter }\n | { readonly type: 'pause'; readonly sessionId: string }\n | { readonly type: 'resume'; readonly sessionId: string }\n | { readonly type: 'stepForward'; readonly sessionId: string }\n | { readonly type: 'stepBackward'; readonly sessionId: string }\n | { readonly type: 'setBreakpoint'; readonly sessionId: string; readonly breakpoint: BreakpointConfig }\n | { readonly type: 'clearBreakpoint'; readonly sessionId: string; readonly breakpointId: string }\n | { readonly type: 'listBreakpoints'; readonly sessionId: string };\n\nexport function eventFilterAll(): EventFilter {\n return { eventTypes: null, transitionNames: null, placeNames: null };\n}\n","/**\n * Caches computed state snapshots at periodic intervals for efficient seek/step.\n * TypeScript port of Java's MarkingCache.\n */\n\nimport type { NetEvent } from '../event/net-event.js';\nimport type { TokenInfo } from './debug-response.js';\nimport { computeState, applyEvents, toImmutableState, type ComputedState } from './debug-protocol-handler.js';\n\n/** Number of events between cached snapshots. */\nexport const SNAPSHOT_INTERVAL = 256;\n\nexport class MarkingCache {\n private readonly _snapshots: ComputedState[] = [];\n\n /**\n * Computes the state at the given event index, using cached snapshots\n * to minimize the number of events that need to be replayed.\n *\n * @param events the full event list for the session\n * @param targetIndex event index to compute state at (exclusive upper bound)\n */\n computeAt(events: readonly NetEvent[], targetIndex: number): ComputedState {\n if (targetIndex <= 0) {\n return computeState([]);\n }\n\n this.ensureCachedUpTo(events, targetIndex);\n\n if (this._snapshots.length === 0) {\n return computeState(events.slice(0, targetIndex));\n }\n\n // Find highest snapshot <= targetIndex\n const snapshotSlot = Math.min(Math.floor(targetIndex / SNAPSHOT_INTERVAL), this._snapshots.length) - 1;\n\n if (snapshotSlot < 0) {\n return computeState(events.slice(0, targetIndex));\n }\n\n const snapshotEventIndex = (snapshotSlot + 1) * SNAPSHOT_INTERVAL;\n\n if (snapshotEventIndex === targetIndex) {\n return this._snapshots[snapshotSlot]!;\n }\n\n return replayDelta(this._snapshots[snapshotSlot]!, events.slice(snapshotEventIndex, targetIndex));\n }\n\n /** Invalidates the cache. */\n invalidate(): void {\n this._snapshots.length = 0;\n }\n\n /** Extends the snapshot cache to cover at least up to the given event index. */\n private ensureCachedUpTo(events: readonly NetEvent[], targetIndex: number): void {\n const neededSnapshots = Math.floor(targetIndex / SNAPSHOT_INTERVAL);\n\n while (this._snapshots.length < neededSnapshots) {\n const nextSnapshotIndex = (this._snapshots.length + 1) * SNAPSHOT_INTERVAL;\n if (nextSnapshotIndex > events.length) break;\n\n if (this._snapshots.length === 0) {\n this._snapshots.push(computeState(events.slice(0, nextSnapshotIndex)));\n } else {\n const prevSnapshotIndex = this._snapshots.length * SNAPSHOT_INTERVAL;\n const delta = events.slice(prevSnapshotIndex, nextSnapshotIndex);\n this._snapshots.push(replayDelta(this._snapshots[this._snapshots.length - 1]!, delta));\n }\n }\n }\n}\n\n/** Replays delta events on top of a base snapshot to produce a new state. */\nfunction replayDelta(base: ComputedState, delta: readonly NetEvent[]): ComputedState {\n const marking = new Map<string, TokenInfo[]>();\n for (const [key, value] of base.marking) {\n marking.set(key, [...value]);\n }\n const enabled = new Set(base.enabledTransitions);\n const inFlight = new Set(base.inFlightTransitions);\n applyEvents(marking, enabled, inFlight, delta);\n return toImmutableState(marking, enabled, inFlight);\n}\n","/**\n * Converts CTPN NetEvent instances to serializable DebugResponse types.\n * TypeScript port of Java's NetEventConverter.\n */\n\nimport type { Token } from '../core/token.js';\nimport type { NetEvent } from '../event/net-event.js';\nimport type { NetEventInfo, TokenInfo } from './debug-response.js';\n\n/** Converts a NetEvent to a serializable NetEventInfo. */\nexport function toEventInfo(event: NetEvent, compact = false): NetEventInfo {\n switch (event.type) {\n case 'execution-started':\n return {\n type: 'ExecutionStarted',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: null,\n placeName: null,\n details: { netName: event.netName, executionId: event.executionId },\n };\n\n case 'execution-completed':\n return {\n type: 'ExecutionCompleted',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: null,\n placeName: null,\n details: {\n netName: event.netName,\n executionId: event.executionId,\n totalDurationMs: event.totalDurationMs,\n },\n };\n\n case 'transition-enabled':\n return {\n type: 'TransitionEnabled',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: {},\n };\n\n case 'transition-clock-restarted':\n return {\n type: 'TransitionClockRestarted',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: {},\n };\n\n case 'transition-started':\n return {\n type: 'TransitionStarted',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: {\n consumedTokens: event.consumedTokens.map(t => compact ? compactTokenInfo(t) : tokenInfo(t)),\n },\n };\n\n case 'transition-completed':\n return {\n type: 'TransitionCompleted',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: {\n producedTokens: event.producedTokens.map(t => compact ? compactTokenInfo(t) : tokenInfo(t)),\n durationMs: event.durationMs,\n },\n };\n\n case 'transition-failed':\n return {\n type: 'TransitionFailed',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: {\n errorMessage: event.errorMessage,\n exceptionType: event.exceptionType,\n },\n };\n\n case 'transition-timed-out':\n return {\n type: 'TransitionTimedOut',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: {\n deadlineMs: event.deadlineMs,\n actualDurationMs: event.actualDurationMs,\n },\n };\n\n case 'action-timed-out':\n return {\n type: 'ActionTimedOut',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details: { timeoutMs: event.timeoutMs },\n };\n\n case 'token-added':\n return {\n type: 'TokenAdded',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: null,\n placeName: event.placeName,\n details: {\n token: compact ? compactTokenInfo(event.token) : tokenInfo(event.token),\n },\n };\n\n case 'token-removed':\n return {\n type: 'TokenRemoved',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: null,\n placeName: event.placeName,\n details: {\n token: compact ? compactTokenInfo(event.token) : tokenInfo(event.token),\n },\n };\n\n case 'marking-snapshot':\n return {\n type: 'MarkingSnapshot',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: null,\n placeName: null,\n details: {\n marking: convertMarking(event.marking, compact),\n },\n };\n\n case 'log-message': {\n const details: Record<string, unknown> = {\n loggerName: event.logger,\n level: event.level,\n message: event.message,\n };\n if (event.error != null) details['throwable'] = event.error;\n if (event.errorMessage != null) details['throwableMessage'] = event.errorMessage;\n return {\n type: 'LogMessage',\n timestamp: new Date(event.timestamp).toISOString(),\n transitionName: event.transitionName,\n placeName: null,\n details,\n };\n }\n }\n}\n\n/** Converts a Token to serializable TokenInfo with full value. */\nexport function tokenInfo(token: Token<unknown>): TokenInfo {\n const value = token.value;\n const type = value != null ? typeof value === 'object' ? value.constructor.name : typeof value : 'null';\n const fullValue = value != null ? String(value) : 'null';\n return {\n id: null,\n type,\n value: fullValue,\n timestamp: new Date(token.createdAt).toISOString(),\n };\n}\n\n/** Converts a Token to compact TokenInfo (type only, no value). */\nexport function compactTokenInfo(token: Token<unknown>): TokenInfo {\n const value = token.value;\n const type = value != null ? typeof value === 'object' ? value.constructor.name : typeof value : 'null';\n return {\n id: null,\n type,\n value: null,\n timestamp: new Date(token.createdAt).toISOString(),\n };\n}\n\n/** Converts a marking map to serializable form. */\nexport function convertMarking(\n marking: ReadonlyMap<string, readonly Token<unknown>[]>,\n compact = false,\n): Record<string, readonly TokenInfo[]> {\n const result: Record<string, readonly TokenInfo[]> = {};\n const mapper = compact ? compactTokenInfo : tokenInfo;\n for (const [name, tokens] of marking) {\n result[name] = tokens.map(mapper);\n }\n return result;\n}\n","/**\n * Framework-agnostic handler for the Petri net debug protocol.\n * TypeScript port of Java's DebugProtocolHandler.\n *\n * Manages debug subscriptions, event filtering, breakpoints, and replay\n * for connected clients. Decoupled from any specific WebSocket framework\n * via the ResponseSink type.\n */\n\nimport type { NetEvent } from '../event/net-event.js';\nimport { sanitize } from '../export/petri-net-mapper.js';\nimport type { DebugCommand, EventFilter, BreakpointConfig } from './debug-command.js';\nimport type { DebugResponse, TokenInfo, NetEventInfo, NetStructure } from './debug-response.js';\nimport type { DebugSession } from './debug-session-registry.js';\nimport type { DebugSessionRegistry } from './debug-session-registry.js';\nimport type { Subscription } from './debug-event-store.js';\nimport { MarkingCache } from './marking-cache.js';\nimport { toEventInfo, tokenInfo, convertMarking } from './net-event-converter.js';\n\n/** Callback for sending responses to a connected client. */\nexport type ResponseSink = (response: DebugResponse) => void;\n\n/** Computed state from replaying events. */\nexport interface ComputedState {\n readonly marking: ReadonlyMap<string, readonly TokenInfo[]>;\n readonly enabledTransitions: readonly string[];\n readonly inFlightTransitions: readonly string[];\n}\n\n/** Maximum events per batch when sending historical events. */\nconst BATCH_SIZE = 500;\n\nexport class DebugProtocolHandler {\n private readonly _sessionRegistry: DebugSessionRegistry;\n private readonly _clients = new Map<string, ClientState>();\n\n constructor(sessionRegistry: DebugSessionRegistry) {\n this._sessionRegistry = sessionRegistry;\n }\n\n /** Registers a new client connection. */\n clientConnected(clientId: string, sink: ResponseSink): void {\n this._clients.set(clientId, new ClientState(sink));\n }\n\n /** Cleans up when a client disconnects. */\n clientDisconnected(clientId: string): void {\n const state = this._clients.get(clientId);\n this._clients.delete(clientId);\n if (state) state.subscriptions.cancelAll();\n }\n\n /** Handles a command from a connected client. */\n handleCommand(clientId: string, command: DebugCommand): void {\n const clientState = this._clients.get(clientId);\n if (!clientState) return;\n\n try {\n switch (command.type) {\n case 'listSessions': this.handleListSessions(clientState, command); break;\n case 'subscribe': this.handleSubscribe(clientState, command); break;\n case 'unsubscribe': this.handleUnsubscribe(clientState, command); break;\n case 'seek': this.handleSeek(clientState, command); break;\n case 'playbackSpeed': this.handlePlaybackSpeed(clientState, command); break;\n case 'filter': this.handleSetFilter(clientState, command); break;\n case 'pause': this.handlePause(clientState, command); break;\n case 'resume': this.handleResume(clientState, command); break;\n case 'stepForward': this.handleStepForward(clientState, command); break;\n case 'stepBackward': this.handleStepBackward(clientState, command); break;\n case 'setBreakpoint': this.handleSetBreakpoint(clientState, command); break;\n case 'clearBreakpoint': this.handleClearBreakpoint(clientState, command); break;\n case 'listBreakpoints': this.handleListBreakpoints(clientState, command); break;\n }\n } catch (e) {\n this.sendError(clientState, 'COMMAND_ERROR', e instanceof Error ? e.message : String(e), null);\n }\n }\n\n // ======================== Command Handlers ========================\n\n private handleListSessions(client: ClientState, cmd: Extract<DebugCommand, { type: 'listSessions' }>): void {\n const limit = cmd.limit ?? 50;\n const sessions = cmd.activeOnly\n ? this._sessionRegistry.listActiveSessions(limit)\n : this._sessionRegistry.listSessions(limit);\n\n const summaries = sessions.map(s => ({\n sessionId: s.sessionId,\n netName: s.netName,\n startTime: new Date(s.startTime).toISOString(),\n active: s.active,\n eventCount: s.eventStore.eventCount(),\n }));\n\n this.send(client, { type: 'sessionList', sessions: summaries });\n }\n\n private handleSubscribe(client: ClientState, cmd: Extract<DebugCommand, { type: 'subscribe' }>): void {\n const debugSession = this._sessionRegistry.getSession(cmd.sessionId);\n if (!debugSession) {\n this.sendError(client, 'SESSION_NOT_FOUND', `Session not found: ${cmd.sessionId}`, cmd.sessionId);\n return;\n }\n\n const eventStore = debugSession.eventStore;\n client.subscriptions.cancel(cmd.sessionId);\n\n const events = eventStore.events();\n const computed = computeState(events);\n const structure = buildNetStructure(debugSession);\n\n this.send(client, {\n type: 'subscribed',\n sessionId: cmd.sessionId,\n netName: debugSession.netName,\n dotDiagram: debugSession.dotDiagram,\n structure,\n currentMarking: mapToRecord(computed.marking),\n enabledTransitions: computed.enabledTransitions,\n inFlightTransitions: computed.inFlightTransitions,\n eventCount: eventStore.eventCount(),\n mode: cmd.mode,\n });\n\n const fromIndex = cmd.fromIndex ?? 0;\n if (cmd.mode === 'live') {\n this.subscribeLive(client, cmd.sessionId, debugSession, fromIndex);\n } else {\n this.subscribeReplay(client, cmd.sessionId, debugSession, fromIndex);\n }\n }\n\n private subscribeLive(client: ClientState, sessionId: string, debugSession: DebugSession, fromIndex: number): void {\n const eventStore = debugSession.eventStore;\n let eventIndex = fromIndex;\n\n const historicalEvents = eventStore.eventsFrom(fromIndex);\n if (historicalEvents.length > 0) {\n const filtered = historicalEvents\n .filter(e => client.subscriptions.matchesFilter(sessionId, e))\n .map(e => toEventInfo(e));\n this.sendInBatches(client, sessionId, fromIndex, filtered);\n eventIndex = fromIndex + historicalEvents.length;\n }\n\n const subscription = eventStore.subscribe(event => {\n if (!client.subscriptions.isPaused(sessionId) && client.subscriptions.matchesFilter(sessionId, event)) {\n const eventInfo = toEventInfo(event);\n const idx = eventIndex++;\n\n const hitBreakpoint = client.subscriptions.checkBreakpoints(sessionId, event);\n if (hitBreakpoint) {\n client.subscriptions.setPaused(sessionId, true);\n this.send(client, {\n type: 'breakpointHit',\n sessionId,\n breakpointId: hitBreakpoint.id,\n event: eventInfo,\n eventIndex: idx,\n });\n }\n\n this.send(client, { type: 'event', sessionId, index: idx, event: eventInfo });\n }\n });\n\n client.subscriptions.addSubscription(sessionId, subscription, eventIndex);\n }\n\n private subscribeReplay(client: ClientState, sessionId: string, debugSession: DebugSession, fromIndex: number): void {\n const eventStore = debugSession.eventStore;\n\n const events = eventStore.eventsFrom(fromIndex);\n const converted = events.map(e => toEventInfo(e));\n this.sendInBatches(client, sessionId, fromIndex, converted);\n\n const eventIndex = fromIndex + events.length;\n client.subscriptions.addSubscription(sessionId, null, eventIndex);\n client.subscriptions.setPaused(sessionId, true);\n }\n\n private handleUnsubscribe(client: ClientState, cmd: Extract<DebugCommand, { type: 'unsubscribe' }>): void {\n client.subscriptions.cancel(cmd.sessionId);\n this.send(client, { type: 'unsubscribed', sessionId: cmd.sessionId });\n }\n\n private handleSeek(client: ClientState, cmd: Extract<DebugCommand, { type: 'seek' }>): void {\n const debugSession = this._sessionRegistry.getSession(cmd.sessionId);\n if (!debugSession) {\n this.sendError(client, 'SESSION_NOT_FOUND', 'Session not found', cmd.sessionId);\n return;\n }\n\n const events = debugSession.eventStore.events();\n const targetTs = new Date(cmd.timestamp).getTime();\n\n let targetIndex = 0;\n for (let i = 0; i < events.length; i++) {\n if (events[i]!.timestamp >= targetTs) {\n targetIndex = i;\n break;\n }\n targetIndex = i + 1;\n }\n\n client.subscriptions.setEventIndex(cmd.sessionId, targetIndex);\n const computed = client.subscriptions.computeStateAt(cmd.sessionId, events, targetIndex);\n\n this.send(client, {\n type: 'markingSnapshot',\n sessionId: cmd.sessionId,\n marking: mapToRecord(computed.marking),\n enabledTransitions: computed.enabledTransitions,\n inFlightTransitions: computed.inFlightTransitions,\n });\n }\n\n private handlePlaybackSpeed(client: ClientState, cmd: Extract<DebugCommand, { type: 'playbackSpeed' }>): void {\n client.subscriptions.setSpeed(cmd.sessionId, cmd.speed);\n this.send(client, {\n type: 'playbackStateChanged',\n sessionId: cmd.sessionId,\n paused: client.subscriptions.isPaused(cmd.sessionId),\n speed: cmd.speed,\n currentIndex: client.subscriptions.getEventIndex(cmd.sessionId),\n });\n }\n\n private handleSetFilter(client: ClientState, cmd: Extract<DebugCommand, { type: 'filter' }>): void {\n client.subscriptions.setFilter(cmd.sessionId, cmd.filter);\n this.send(client, { type: 'filterApplied', sessionId: cmd.sessionId, filter: cmd.filter });\n }\n\n private handlePause(client: ClientState, cmd: Extract<DebugCommand, { type: 'pause' }>): void {\n client.subscriptions.setPaused(cmd.sessionId, true);\n this.send(client, {\n type: 'playbackStateChanged',\n sessionId: cmd.sessionId,\n paused: true,\n speed: client.subscriptions.getSpeed(cmd.sessionId),\n currentIndex: client.subscriptions.getEventIndex(cmd.sessionId),\n });\n }\n\n private handleResume(client: ClientState, cmd: Extract<DebugCommand, { type: 'resume' }>): void {\n client.subscriptions.setPaused(cmd.sessionId, false);\n this.send(client, {\n type: 'playbackStateChanged',\n sessionId: cmd.sessionId,\n paused: false,\n speed: client.subscriptions.getSpeed(cmd.sessionId),\n currentIndex: client.subscriptions.getEventIndex(cmd.sessionId),\n });\n }\n\n private handleStepForward(client: ClientState, cmd: Extract<DebugCommand, { type: 'stepForward' }>): void {\n const debugSession = this._sessionRegistry.getSession(cmd.sessionId);\n if (!debugSession) {\n this.sendError(client, 'SESSION_NOT_FOUND', `Session not found: ${cmd.sessionId}`, cmd.sessionId);\n return;\n }\n\n const events = debugSession.eventStore.events();\n const currentIndex = client.subscriptions.getEventIndex(cmd.sessionId);\n\n if (currentIndex < events.length) {\n const event = events[currentIndex]!;\n this.send(client, {\n type: 'event',\n sessionId: cmd.sessionId,\n index: currentIndex,\n event: toEventInfo(event),\n });\n client.subscriptions.setEventIndex(cmd.sessionId, currentIndex + 1);\n }\n }\n\n private handleStepBackward(client: ClientState, cmd: Extract<DebugCommand, { type: 'stepBackward' }>): void {\n const debugSession = this._sessionRegistry.getSession(cmd.sessionId);\n if (!debugSession) {\n this.sendError(client, 'SESSION_NOT_FOUND', `Session not found: ${cmd.sessionId}`, cmd.sessionId);\n return;\n }\n\n let currentIndex = client.subscriptions.getEventIndex(cmd.sessionId);\n if (currentIndex > 0) {\n currentIndex--;\n client.subscriptions.setEventIndex(cmd.sessionId, currentIndex);\n\n const events = debugSession.eventStore.events();\n const computed = client.subscriptions.computeStateAt(cmd.sessionId, events, currentIndex);\n\n this.send(client, {\n type: 'markingSnapshot',\n sessionId: cmd.sessionId,\n marking: mapToRecord(computed.marking),\n enabledTransitions: computed.enabledTransitions,\n inFlightTransitions: computed.inFlightTransitions,\n });\n }\n }\n\n private handleSetBreakpoint(client: ClientState, cmd: Extract<DebugCommand, { type: 'setBreakpoint' }>): void {\n client.subscriptions.addBreakpoint(cmd.sessionId, cmd.breakpoint);\n this.send(client, { type: 'breakpointSet', sessionId: cmd.sessionId, breakpoint: cmd.breakpoint });\n }\n\n private handleClearBreakpoint(client: ClientState, cmd: Extract<DebugCommand, { type: 'clearBreakpoint' }>): void {\n client.subscriptions.removeBreakpoint(cmd.sessionId, cmd.breakpointId);\n this.send(client, { type: 'breakpointCleared', sessionId: cmd.sessionId, breakpointId: cmd.breakpointId });\n }\n\n private handleListBreakpoints(client: ClientState, cmd: Extract<DebugCommand, { type: 'listBreakpoints' }>): void {\n const breakpoints = client.subscriptions.getBreakpoints(cmd.sessionId);\n this.send(client, { type: 'breakpointList', sessionId: cmd.sessionId, breakpoints });\n }\n\n // ======================== Helper Methods ========================\n\n private send(client: ClientState, response: DebugResponse): void {\n client.sink(response);\n }\n\n private sendError(client: ClientState, code: string, message: string, sessionId: string | null): void {\n this.send(client, { type: 'error', code, message, sessionId });\n }\n\n private sendInBatches(client: ClientState, sessionId: string, startIndex: number, events: readonly NetEventInfo[]): void {\n if (events.length === 0) {\n this.send(client, { type: 'eventBatch', sessionId, startIndex, events: [], hasMore: false });\n return;\n }\n for (let i = 0; i < events.length; i += BATCH_SIZE) {\n const end = Math.min(i + BATCH_SIZE, events.length);\n const chunk = events.slice(i, end);\n const hasMore = end < events.length;\n this.send(client, { type: 'eventBatch', sessionId, startIndex: startIndex + i, events: chunk, hasMore });\n }\n }\n}\n\n// ======================== State Computation (exported for MarkingCache) ========================\n\n/** Computes marking, enabled transitions, and in-flight transitions from events. */\nexport function computeState(events: readonly NetEvent[]): ComputedState {\n const marking = new Map<string, TokenInfo[]>();\n const enabled = new Set<string>();\n const inFlight = new Set<string>();\n applyEvents(marking, enabled, inFlight, events);\n return toImmutableState(marking, enabled, inFlight);\n}\n\n/** Applies events to mutable accumulator collections. */\nexport function applyEvents(\n marking: Map<string, TokenInfo[]>,\n enabled: Set<string>,\n inFlight: Set<string>,\n events: readonly NetEvent[],\n): void {\n for (const event of events) {\n switch (event.type) {\n case 'token-added': {\n let tokens = marking.get(event.placeName);\n if (!tokens) {\n tokens = [];\n marking.set(event.placeName, tokens);\n }\n tokens.push(tokenInfo(event.token));\n break;\n }\n case 'token-removed': {\n const tokens = marking.get(event.placeName);\n if (tokens && tokens.length > 0) tokens.shift();\n break;\n }\n case 'marking-snapshot': {\n marking.clear();\n const converted = convertMarking(event.marking);\n for (const [key, value] of Object.entries(converted)) {\n marking.set(key, [...value]);\n }\n break;\n }\n case 'transition-enabled':\n enabled.add(event.transitionName);\n break;\n case 'transition-started':\n enabled.delete(event.transitionName);\n inFlight.add(event.transitionName);\n break;\n case 'transition-completed':\n inFlight.delete(event.transitionName);\n break;\n case 'transition-failed':\n inFlight.delete(event.transitionName);\n break;\n case 'transition-timed-out':\n inFlight.delete(event.transitionName);\n break;\n case 'action-timed-out':\n inFlight.delete(event.transitionName);\n break;\n default:\n break;\n }\n }\n}\n\n/** Converts mutable accumulator collections into an immutable ComputedState. */\nexport function toImmutableState(\n marking: Map<string, TokenInfo[]>,\n enabled: Set<string>,\n inFlight: Set<string>,\n): ComputedState {\n const resultMarking = new Map<string, readonly TokenInfo[]>();\n for (const [key, value] of marking) {\n resultMarking.set(key, [...value]);\n }\n return {\n marking: resultMarking,\n enabledTransitions: [...enabled],\n inFlightTransitions: [...inFlight],\n };\n}\n\n/** Builds net structure from a debug session. */\nfunction buildNetStructure(debugSession: DebugSession): NetStructure {\n const places = debugSession.places;\n const transitions = debugSession.transitions;\n\n const placeInfos = [...places.data.entries()].map(([name, info]) => ({\n name,\n graphId: `p_${sanitize(name)}`,\n tokenType: info.tokenType,\n isStart: !info.hasIncoming,\n isEnd: !info.hasOutgoing,\n isEnvironment: false,\n }));\n\n const transitionInfos = [...transitions].map(t => ({\n name: t.name,\n graphId: `t_${sanitize(t.name)}`,\n }));\n\n return { places: placeInfos, transitions: transitionInfos };\n}\n\n/** Convert Map to Record for JSON serialization. */\nfunction mapToRecord(map: ReadonlyMap<string, readonly TokenInfo[]>): Record<string, readonly TokenInfo[]> {\n const result: Record<string, readonly TokenInfo[]> = {};\n for (const [key, value] of map) {\n result[key] = value;\n }\n return result;\n}\n\n// ======================== Client State ========================\n\nclass ClientState {\n readonly sink: ResponseSink;\n readonly subscriptions = new SubscriptionState();\n\n constructor(sink: ResponseSink) {\n this.sink = sink;\n }\n}\n\n// ======================== Subscription State ========================\n\ninterface SessionSubscription {\n subscription: Subscription | null;\n eventIndex: number;\n markingCache: MarkingCache;\n breakpoints: Map<string, BreakpointConfig>;\n paused: boolean;\n speed: number;\n filter: EventFilter | null;\n}\n\nclass SubscriptionState {\n private readonly _sessionSubs = new Map<string, SessionSubscription>();\n\n addSubscription(sessionId: string, subscription: Subscription | null, eventIndex: number): void {\n this._sessionSubs.set(sessionId, {\n subscription,\n eventIndex,\n markingCache: new MarkingCache(),\n breakpoints: new Map(),\n paused: false,\n speed: 1.0,\n filter: null,\n });\n }\n\n cancel(sessionId: string): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub?.subscription) sub.subscription.cancel();\n this._sessionSubs.delete(sessionId);\n }\n\n cancelAll(): void {\n for (const sub of this._sessionSubs.values()) {\n if (sub.subscription) sub.subscription.cancel();\n }\n this._sessionSubs.clear();\n }\n\n isPaused(sessionId: string): boolean {\n return this._sessionSubs.get(sessionId)?.paused ?? false;\n }\n\n setPaused(sessionId: string, paused: boolean): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) sub.paused = paused;\n }\n\n getSpeed(sessionId: string): number {\n return this._sessionSubs.get(sessionId)?.speed ?? 1.0;\n }\n\n setSpeed(sessionId: string, speed: number): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) sub.speed = speed;\n }\n\n getEventIndex(sessionId: string): number {\n return this._sessionSubs.get(sessionId)?.eventIndex ?? 0;\n }\n\n setEventIndex(sessionId: string, index: number): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) sub.eventIndex = index;\n }\n\n computeStateAt(sessionId: string, events: readonly NetEvent[], targetIndex: number): ComputedState {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) return sub.markingCache.computeAt(events, targetIndex);\n return computeState(events.slice(0, targetIndex));\n }\n\n setFilter(sessionId: string, filter: EventFilter): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) sub.filter = filter;\n }\n\n matchesFilter(sessionId: string, event: NetEvent): boolean {\n const sub = this._sessionSubs.get(sessionId);\n if (!sub?.filter) return true;\n\n const filter = sub.filter;\n\n if (filter.eventTypes && filter.eventTypes.length > 0) {\n const eventType = eventTypeToName(event);\n if (!filter.eventTypes.includes(eventType)) return false;\n }\n\n if (filter.transitionNames && filter.transitionNames.length > 0) {\n const name = extractTransitionName(event);\n if (!name || !filter.transitionNames.includes(name)) return false;\n }\n\n if (filter.placeNames && filter.placeNames.length > 0) {\n const name = extractPlaceName(event);\n if (!name || !filter.placeNames.includes(name)) return false;\n }\n\n return true;\n }\n\n addBreakpoint(sessionId: string, breakpoint: BreakpointConfig): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) sub.breakpoints.set(breakpoint.id, breakpoint);\n }\n\n removeBreakpoint(sessionId: string, breakpointId: string): void {\n const sub = this._sessionSubs.get(sessionId);\n if (sub) sub.breakpoints.delete(breakpointId);\n }\n\n getBreakpoints(sessionId: string): readonly BreakpointConfig[] {\n const sub = this._sessionSubs.get(sessionId);\n return sub ? [...sub.breakpoints.values()] : [];\n }\n\n checkBreakpoints(sessionId: string, event: NetEvent): BreakpointConfig | null {\n const sub = this._sessionSubs.get(sessionId);\n if (!sub || sub.breakpoints.size === 0) return null;\n\n for (const bp of sub.breakpoints.values()) {\n if (!bp.enabled) continue;\n if (matchesBreakpoint(bp, event)) return bp;\n }\n return null;\n }\n}\n\nfunction eventTypeToName(event: NetEvent): string {\n const map: Record<string, string> = {\n 'execution-started': 'ExecutionStarted',\n 'execution-completed': 'ExecutionCompleted',\n 'transition-enabled': 'TransitionEnabled',\n 'transition-clock-restarted': 'TransitionClockRestarted',\n 'transition-started': 'TransitionStarted',\n 'transition-completed': 'TransitionCompleted',\n 'transition-failed': 'TransitionFailed',\n 'transition-timed-out': 'TransitionTimedOut',\n 'action-timed-out': 'ActionTimedOut',\n 'token-added': 'TokenAdded',\n 'token-removed': 'TokenRemoved',\n 'marking-snapshot': 'MarkingSnapshot',\n 'log-message': 'LogMessage',\n };\n return map[event.type] ?? event.type;\n}\n\nfunction extractTransitionName(event: NetEvent): string | null {\n switch (event.type) {\n case 'transition-enabled':\n case 'transition-clock-restarted':\n case 'transition-started':\n case 'transition-completed':\n case 'transition-failed':\n case 'transition-timed-out':\n case 'action-timed-out':\n case 'log-message':\n return event.transitionName;\n default:\n return null;\n }\n}\n\nfunction extractPlaceName(event: NetEvent): string | null {\n switch (event.type) {\n case 'token-added':\n case 'token-removed':\n return event.placeName;\n default:\n return null;\n }\n}\n\nfunction matchesBreakpoint(bp: BreakpointConfig, event: NetEvent): boolean {\n switch (bp.type) {\n case 'TRANSITION_ENABLED':\n return event.type === 'transition-enabled' && (bp.target === null || bp.target === event.transitionName);\n case 'TRANSITION_START':\n return event.type === 'transition-started' && (bp.target === null || bp.target === event.transitionName);\n case 'TRANSITION_COMPLETE':\n return event.type === 'transition-completed' && (bp.target === null || bp.target === event.transitionName);\n case 'TRANSITION_FAIL':\n return event.type === 'transition-failed' && (bp.target === null || bp.target === event.transitionName);\n case 'TOKEN_ADDED':\n return event.type === 'token-added' && (bp.target === null || bp.target === event.placeName);\n case 'TOKEN_REMOVED':\n return event.type === 'token-removed' && (bp.target === null || bp.target === event.placeName);\n default:\n return false;\n }\n}\n","/**\n * EventStore with live tailing and historical replay.\n * TypeScript port of Java's DebugEventStore.\n *\n * Node.js simplifications: single-threaded, no locks needed,\n * synchronous Set<Function> for subscribers, microtask broadcast.\n */\n\nimport type { EventStore } from '../event/event-store.js';\nimport type { NetEvent } from '../event/net-event.js';\n\n/** Handle for managing a live event subscription. */\nexport interface Subscription {\n cancel(): void;\n isActive(): boolean;\n}\n\n/** Default maximum events to retain before evicting oldest. */\nexport const DEFAULT_MAX_EVENTS = 10_000;\n\nexport class DebugEventStore implements EventStore {\n private readonly _events: NetEvent[] = [];\n private readonly _subscribers = new Set<(event: NetEvent) => void>();\n private readonly _sessionId: string;\n private readonly _maxEvents: number;\n private _eventCount = 0;\n private _evictedCount = 0;\n\n constructor(sessionId: string, maxEvents = DEFAULT_MAX_EVENTS) {\n if (maxEvents <= 0) throw new Error(`maxEvents must be positive, got: ${maxEvents}`);\n this._sessionId = sessionId;\n this._maxEvents = maxEvents;\n }\n\n get sessionId(): string { return this._sessionId; }\n get maxEvents(): number { return this._maxEvents; }\n\n /** Total events appended (including evicted). */\n eventCount(): number { return this._eventCount; }\n\n /** Number of events evicted from the store. */\n evictedCount(): number { return this._evictedCount; }\n\n // ======================== EventStore Implementation ========================\n\n append(event: NetEvent): void {\n this._events.push(event);\n this._eventCount++;\n\n // Evict oldest when capacity exceeded\n while (this._events.length > this._maxEvents) {\n this._events.shift();\n this._evictedCount++;\n }\n\n // Broadcast to subscribers (microtask for async-like behavior)\n if (this._subscribers.size > 0) {\n // Use queueMicrotask instead of synchronous call to avoid blocking\n const subscribers = [...this._subscribers];\n queueMicrotask(() => {\n for (const sub of subscribers) {\n try {\n sub(event);\n } catch (e) {\n console.warn('Subscriber threw exception during event broadcast', e);\n }\n }\n });\n }\n }\n\n events(): readonly NetEvent[] {\n return this._events;\n }\n\n isEnabled(): boolean {\n return true;\n }\n\n size(): number {\n return this._events.length;\n }\n\n isEmpty(): boolean {\n return this._events.length === 0;\n }\n\n // ======================== Live Tailing ========================\n\n /** Subscribe to receive events as they occur. */\n subscribe(listener: (event: NetEvent) => void): Subscription {\n this._subscribers.add(listener);\n return {\n cancel: () => { this._subscribers.delete(listener); },\n isActive: () => this._subscribers.has(listener),\n };\n }\n\n /** Number of active subscribers. */\n subscriberCount(): number {\n return this._subscribers.size;\n }\n\n // ======================== Historical Replay ========================\n\n /** Returns events starting from a specific index. */\n eventsFrom(fromIndex: number): readonly NetEvent[] {\n const adjustedSkip = Math.max(0, fromIndex - this._evictedCount);\n if (adjustedSkip <= 0) return this._events;\n return this._events.slice(adjustedSkip);\n }\n\n /** Returns all events since the specified timestamp. */\n eventsSince(from: number): readonly NetEvent[] {\n return this._events.filter(e => e.timestamp >= from);\n }\n\n /** Returns events within a time range. */\n eventsBetween(from: number, to: number): readonly NetEvent[] {\n return this._events.filter(e => e.timestamp >= from && e.timestamp < to);\n }\n\n // ======================== Lifecycle ========================\n\n /** Close the store (no-op in JS, but matches Java interface). */\n close(): void {\n this._subscribers.clear();\n }\n}\n","/**\n * Analyze places for start/end/environment classification.\n * TypeScript port of Java's PlaceAnalysis.\n */\n\nimport type { PetriNet } from '../core/petri-net.js';\nimport type { Place } from '../core/place.js';\n\nexport interface PlaceAnalysisInfo {\n readonly tokenType: string;\n readonly hasIncoming: boolean;\n readonly hasOutgoing: boolean;\n}\n\nexport class PlaceAnalysis {\n private readonly _data: ReadonlyMap<string, PlaceAnalysisInfo>;\n\n constructor(data: ReadonlyMap<string, PlaceAnalysisInfo>) {\n this._data = data;\n }\n\n get data(): ReadonlyMap<string, PlaceAnalysisInfo> {\n return this._data;\n }\n\n isStart(placeName: string): boolean {\n const info = this._data.get(placeName);\n return info != null && !info.hasIncoming;\n }\n\n isEnd(placeName: string): boolean {\n const info = this._data.get(placeName);\n return info != null && !info.hasOutgoing;\n }\n\n /** Build place analysis from a PetriNet. */\n static from(net: PetriNet): PlaceAnalysis {\n const data = new Map<string, { tokenType: string; hasIncoming: boolean; hasOutgoing: boolean }>();\n\n function ensure(place: Place<unknown>): { tokenType: string; hasIncoming: boolean; hasOutgoing: boolean } {\n let info = data.get(place.name);\n if (!info) {\n info = { tokenType: 'unknown', hasIncoming: false, hasOutgoing: false };\n data.set(place.name, info);\n }\n return info;\n }\n\n for (const transition of net.transitions) {\n // Input arcs: place → transition (place has outgoing)\n for (const input of transition.inputSpecs) {\n const info = ensure((input as { place: Place<unknown> }).place);\n info.hasOutgoing = true;\n }\n\n // Output arcs: transition → place (place has incoming)\n if (transition.outputSpec) {\n const outputPlaces = collectOutputPlaces(transition.outputSpec);\n for (const place of outputPlaces) {\n const info = ensure(place);\n info.hasIncoming = true;\n }\n }\n\n // Inhibitor arcs: just ensure place exists\n for (const inh of transition.inhibitors) {\n ensure((inh as { place: Place<unknown> }).place);\n }\n\n // Read arcs: place has outgoing (read = test without consuming)\n for (const read of transition.reads) {\n const info = ensure((read as { place: Place<unknown> }).place);\n info.hasOutgoing = true;\n }\n\n // Reset arcs: just ensure place exists\n for (const reset of transition.resets) {\n ensure((reset as { place: Place<unknown> }).place);\n }\n }\n\n return new PlaceAnalysis(data as ReadonlyMap<string, PlaceAnalysisInfo>);\n }\n}\n\n/** Recursively collect all output places from an Out spec. */\nfunction collectOutputPlaces(out: unknown): Place<unknown>[] {\n const spec = out as { type: string; place?: Place<unknown>; children?: unknown[]; child?: unknown; from?: Place<unknown>; to?: Place<unknown> };\n switch (spec.type) {\n case 'place':\n return spec.place ? [spec.place] : [];\n case 'and':\n case 'xor':\n return (spec.children ?? []).flatMap(c => collectOutputPlaces(c));\n case 'timeout':\n return spec.child ? collectOutputPlaces(spec.child) : [];\n case 'forward-input':\n return spec.to ? [spec.to] : [];\n default:\n return [];\n }\n}\n","/**\n * Registry for managing Petri net debug sessions.\n * TypeScript port of Java's DebugSessionRegistry.\n */\n\nimport type { PetriNet } from '../core/petri-net.js';\nimport type { Transition } from '../core/transition.js';\nimport { dotExport } from '../export/dot-exporter.js';\nimport { PlaceAnalysis } from './place-analysis.js';\nimport { DebugEventStore } from './debug-event-store.js';\n\nexport interface DebugSession {\n readonly sessionId: string;\n readonly netName: string;\n readonly dotDiagram: string;\n readonly places: PlaceAnalysis;\n readonly transitions: ReadonlySet<Transition>;\n readonly eventStore: DebugEventStore;\n readonly startTime: number;\n readonly active: boolean;\n}\n\nexport type EventStoreFactory = (sessionId: string) => DebugEventStore;\n\nexport class DebugSessionRegistry {\n private readonly _sessions = new Map<string, DebugSession>();\n private readonly _maxSessions: number;\n private readonly _eventStoreFactory: EventStoreFactory;\n\n constructor(maxSessions = 50, eventStoreFactory?: EventStoreFactory) {\n this._maxSessions = maxSessions;\n this._eventStoreFactory = eventStoreFactory ?? ((id: string) => new DebugEventStore(id));\n }\n\n /**\n * Registers a new debug session for the given Petri net.\n * Generates DOT diagram and extracts net structure.\n */\n register(sessionId: string, net: PetriNet): DebugSession {\n const dotDiagram = dotExport(net);\n const places = PlaceAnalysis.from(net);\n const eventStore = this._eventStoreFactory(sessionId);\n\n const session: DebugSession = {\n sessionId,\n netName: net.name,\n dotDiagram,\n places,\n transitions: net.transitions,\n eventStore,\n startTime: Date.now(),\n active: true,\n };\n\n this.evictIfNecessary();\n this._sessions.set(sessionId, session);\n return session;\n }\n\n /** Marks a session as completed (no longer active). */\n complete(sessionId: string): void {\n const session = this._sessions.get(sessionId);\n if (session) {\n this._sessions.set(sessionId, { ...session, active: false });\n }\n }\n\n /** Removes a session from the registry. */\n remove(sessionId: string): DebugSession | undefined {\n const removed = this._sessions.get(sessionId);\n if (removed) {\n this._sessions.delete(sessionId);\n removed.eventStore.close();\n }\n return removed;\n }\n\n /** Returns a session by ID. */\n getSession(sessionId: string): DebugSession | undefined {\n return this._sessions.get(sessionId);\n }\n\n /** Lists sessions, ordered by start time (most recent first). */\n listSessions(limit: number): readonly DebugSession[] {\n return [...this._sessions.values()]\n .sort((a, b) => b.startTime - a.startTime)\n .slice(0, limit);\n }\n\n /** Lists only active sessions. */\n listActiveSessions(limit: number): readonly DebugSession[] {\n return [...this._sessions.values()]\n .filter(s => s.active)\n .sort((a, b) => b.startTime - a.startTime)\n .slice(0, limit);\n }\n\n /** Total number of sessions. */\n get size(): number {\n return this._sessions.size;\n }\n\n /** Evicts oldest inactive sessions if at capacity. */\n private evictIfNecessary(): void {\n if (this._sessions.size < this._maxSessions) return;\n\n const candidates = [...this._sessions.values()]\n .sort((a, b) => {\n // Inactive first, then oldest\n if (a.active !== b.active) return a.active ? 1 : -1;\n return a.startTime - b.startTime;\n });\n\n for (const candidate of candidates) {\n if (this._sessions.size < this._maxSessions) break;\n const evicted = this._sessions.get(candidate.sessionId);\n if (evicted) {\n this._sessions.delete(candidate.sessionId);\n evicted.eventStore.close();\n }\n }\n }\n}\n","/**\n * EventStore that delegates to both a primary store and a debug store.\n * TypeScript port of Java's DebugAwareEventStore.\n */\n\nimport type { EventStore } from '../event/event-store.js';\nimport type { NetEvent } from '../event/net-event.js';\nimport type { DebugEventStore } from './debug-event-store.js';\n\nexport class DebugAwareEventStore implements EventStore {\n private readonly _primary: EventStore;\n private readonly _debugStore: DebugEventStore;\n\n constructor(primary: EventStore, debugStore: DebugEventStore) {\n this._primary = primary;\n this._debugStore = debugStore;\n }\n\n append(event: NetEvent): void {\n this._primary.append(event);\n try {\n this._debugStore.append(event);\n } catch {\n // Debug failures must not break production\n }\n }\n\n events(): readonly NetEvent[] {\n return this._primary.events();\n }\n\n isEnabled(): boolean {\n return true;\n }\n\n size(): number {\n return this._primary.size();\n }\n\n isEmpty(): boolean {\n return this._primary.isEmpty();\n }\n\n /** Returns the underlying debug store for subscription management. */\n get debugStore(): DebugEventStore {\n return this._debugStore;\n }\n}\n","/**\n * Debug infrastructure for Petri net execution visualization.\n *\n * Provides a framework-agnostic debug protocol handler, event store with\n * live tailing, session registry, and marking cache for efficient replay.\n *\n * @module debug\n */\n\n// Protocol types\nexport type { DebugCommand, SubscriptionMode, BreakpointType, BreakpointConfig, EventFilter } from './debug-command.js';\nexport { eventFilterAll } from './debug-command.js';\nexport type {\n DebugResponse, SessionSummary, TokenInfo, NetEventInfo,\n PlaceInfo, TransitionInfo, NetStructure,\n} from './debug-response.js';\n\n// Core infrastructure\nexport { DebugProtocolHandler } from './debug-protocol-handler.js';\nexport type { ResponseSink, ComputedState } from './debug-protocol-handler.js';\nexport { DebugEventStore, DEFAULT_MAX_EVENTS } from './debug-event-store.js';\nexport type { Subscription } from './debug-event-store.js';\nexport { DebugSessionRegistry } from './debug-session-registry.js';\nexport type { DebugSession, EventStoreFactory } from './debug-session-registry.js';\nexport { MarkingCache, SNAPSHOT_INTERVAL } from './marking-cache.js';\n\n// Converters and analysis\nexport { toEventInfo, tokenInfo, compactTokenInfo, convertMarking } from './net-event-converter.js';\nexport { DebugAwareEventStore } from './debug-aware-event-store.js';\nexport { PlaceAnalysis } from './place-analysis.js';\nexport type { PlaceAnalysisInfo } from './place-analysis.js';\n\n/**\n * Returns the path to the bundled debug UI assets directory.\n * Requires Node.js — resolves relative to this module's location.\n */\nexport async function debugUiAssetPath(): Promise<string> {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const dynamicImport = Function('m', 'return import(m)') as (m: string) => Promise<Record<string, unknown>>;\n const nodeUrl = await dynamicImport('node:url') as { fileURLToPath(url: string | URL): string };\n const nodePath = await dynamicImport('node:path') as { dirname(p: string): string; join(...paths: string[]): string };\n const thisDir = nodePath.dirname(nodeUrl.fileURLToPath(import.meta.url));\n return nodePath.join(thisDir, '..', 'debug-ui');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { T as Token } from './petri-net-C3Jy5HCt.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Events emitted during Petri Net execution.
|
|
5
|
+
* Discriminated union capturing all observable state changes.
|
|
6
|
+
*/
|
|
7
|
+
type NetEvent = ExecutionStarted | ExecutionCompleted | TransitionEnabled | TransitionClockRestarted | TransitionStarted | TransitionCompleted | TransitionFailed | TransitionTimedOut | ActionTimedOut | TokenAdded | TokenRemoved | LogMessage | MarkingSnapshot;
|
|
8
|
+
interface ExecutionStarted {
|
|
9
|
+
readonly type: 'execution-started';
|
|
10
|
+
readonly timestamp: number;
|
|
11
|
+
readonly netName: string;
|
|
12
|
+
readonly executionId: string;
|
|
13
|
+
}
|
|
14
|
+
interface ExecutionCompleted {
|
|
15
|
+
readonly type: 'execution-completed';
|
|
16
|
+
readonly timestamp: number;
|
|
17
|
+
readonly netName: string;
|
|
18
|
+
readonly executionId: string;
|
|
19
|
+
readonly totalDurationMs: number;
|
|
20
|
+
}
|
|
21
|
+
interface TransitionEnabled {
|
|
22
|
+
readonly type: 'transition-enabled';
|
|
23
|
+
readonly timestamp: number;
|
|
24
|
+
readonly transitionName: string;
|
|
25
|
+
}
|
|
26
|
+
interface TransitionClockRestarted {
|
|
27
|
+
readonly type: 'transition-clock-restarted';
|
|
28
|
+
readonly timestamp: number;
|
|
29
|
+
readonly transitionName: string;
|
|
30
|
+
}
|
|
31
|
+
interface TransitionStarted {
|
|
32
|
+
readonly type: 'transition-started';
|
|
33
|
+
readonly timestamp: number;
|
|
34
|
+
readonly transitionName: string;
|
|
35
|
+
readonly consumedTokens: readonly Token<unknown>[];
|
|
36
|
+
}
|
|
37
|
+
interface TransitionCompleted {
|
|
38
|
+
readonly type: 'transition-completed';
|
|
39
|
+
readonly timestamp: number;
|
|
40
|
+
readonly transitionName: string;
|
|
41
|
+
readonly producedTokens: readonly Token<unknown>[];
|
|
42
|
+
readonly durationMs: number;
|
|
43
|
+
}
|
|
44
|
+
interface TransitionFailed {
|
|
45
|
+
readonly type: 'transition-failed';
|
|
46
|
+
readonly timestamp: number;
|
|
47
|
+
readonly transitionName: string;
|
|
48
|
+
readonly errorMessage: string;
|
|
49
|
+
readonly exceptionType: string;
|
|
50
|
+
/** Original stack trace, if available. */
|
|
51
|
+
readonly stack?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Emitted when a transition exceeds its deadline (upper time bound) without firing.
|
|
55
|
+
* Classical TPN semantics: transition is forcibly disabled by the executor in
|
|
56
|
+
* `updateDirtyTransitions()` when elapsed time exceeds `latest(timing)`.
|
|
57
|
+
*/
|
|
58
|
+
interface TransitionTimedOut {
|
|
59
|
+
readonly type: 'transition-timed-out';
|
|
60
|
+
readonly timestamp: number;
|
|
61
|
+
readonly transitionName: string;
|
|
62
|
+
/** The deadline that was exceeded, in milliseconds from enablement. */
|
|
63
|
+
readonly deadlineMs: number;
|
|
64
|
+
/** Actual time elapsed since enablement, in milliseconds. */
|
|
65
|
+
readonly actualDurationMs: number;
|
|
66
|
+
}
|
|
67
|
+
interface ActionTimedOut {
|
|
68
|
+
readonly type: 'action-timed-out';
|
|
69
|
+
readonly timestamp: number;
|
|
70
|
+
readonly transitionName: string;
|
|
71
|
+
readonly timeoutMs: number;
|
|
72
|
+
}
|
|
73
|
+
interface TokenAdded {
|
|
74
|
+
readonly type: 'token-added';
|
|
75
|
+
readonly timestamp: number;
|
|
76
|
+
readonly placeName: string;
|
|
77
|
+
readonly token: Token<unknown>;
|
|
78
|
+
}
|
|
79
|
+
interface TokenRemoved {
|
|
80
|
+
readonly type: 'token-removed';
|
|
81
|
+
readonly timestamp: number;
|
|
82
|
+
readonly placeName: string;
|
|
83
|
+
readonly token: Token<unknown>;
|
|
84
|
+
}
|
|
85
|
+
interface LogMessage {
|
|
86
|
+
readonly type: 'log-message';
|
|
87
|
+
readonly timestamp: number;
|
|
88
|
+
readonly transitionName: string;
|
|
89
|
+
readonly logger: string;
|
|
90
|
+
readonly level: string;
|
|
91
|
+
readonly message: string;
|
|
92
|
+
readonly error: string | null;
|
|
93
|
+
readonly errorMessage: string | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Snapshot of the full marking (token state) at a point in time.
|
|
97
|
+
* Emitted at two points during execution:
|
|
98
|
+
* 1. After initialization (before the main loop) — captures the initial marking
|
|
99
|
+
* 2. Before the execution-completed event — captures the final marking
|
|
100
|
+
*/
|
|
101
|
+
interface MarkingSnapshot {
|
|
102
|
+
readonly type: 'marking-snapshot';
|
|
103
|
+
readonly timestamp: number;
|
|
104
|
+
/** Place name -> tokens in that place at snapshot time. Only non-empty places are included. */
|
|
105
|
+
readonly marking: ReadonlyMap<string, readonly Token<unknown>[]>;
|
|
106
|
+
}
|
|
107
|
+
/** Extracts transition name from events that have one. Returns null otherwise. */
|
|
108
|
+
declare function eventTransitionName(event: NetEvent): string | null;
|
|
109
|
+
/** Checks if the event is a failure type. */
|
|
110
|
+
declare function isFailureEvent(event: NetEvent): boolean;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Storage for events emitted during Petri net execution.
|
|
114
|
+
*/
|
|
115
|
+
interface EventStore {
|
|
116
|
+
/** Appends an event to the store. */
|
|
117
|
+
append(event: NetEvent): void;
|
|
118
|
+
/** Returns all events in chronological order. */
|
|
119
|
+
events(): readonly NetEvent[];
|
|
120
|
+
/** Whether this store is enabled (false = skip event creation). */
|
|
121
|
+
isEnabled(): boolean;
|
|
122
|
+
/** Number of events captured. */
|
|
123
|
+
size(): number;
|
|
124
|
+
/** Whether no events have been captured. */
|
|
125
|
+
isEmpty(): boolean;
|
|
126
|
+
}
|
|
127
|
+
/** Returns events matching a predicate. */
|
|
128
|
+
declare function filterEvents(store: EventStore, predicate: (e: NetEvent) => boolean): NetEvent[];
|
|
129
|
+
/** Returns events of a specific type. */
|
|
130
|
+
declare function eventsOfType<T extends NetEvent['type']>(store: EventStore, type: T): Extract<NetEvent, {
|
|
131
|
+
type: T;
|
|
132
|
+
}>[];
|
|
133
|
+
/** Returns all events for a specific transition. */
|
|
134
|
+
declare function transitionEvents(store: EventStore, transitionName: string): NetEvent[];
|
|
135
|
+
/** Returns all failure events. */
|
|
136
|
+
declare function failures(store: EventStore): NetEvent[];
|
|
137
|
+
declare class InMemoryEventStore implements EventStore {
|
|
138
|
+
private readonly _events;
|
|
139
|
+
append(event: NetEvent): void;
|
|
140
|
+
events(): readonly NetEvent[];
|
|
141
|
+
isEnabled(): boolean;
|
|
142
|
+
size(): number;
|
|
143
|
+
isEmpty(): boolean;
|
|
144
|
+
/** Clears all stored events. */
|
|
145
|
+
clear(): void;
|
|
146
|
+
}
|
|
147
|
+
/** Returns a no-op event store that discards all events. */
|
|
148
|
+
declare function noopEventStore(): EventStore;
|
|
149
|
+
/** Creates a new in-memory event store. */
|
|
150
|
+
declare function inMemoryEventStore(): InMemoryEventStore;
|
|
151
|
+
|
|
152
|
+
export { type ActionTimedOut as A, type EventStore as E, InMemoryEventStore as I, type LogMessage as L, type MarkingSnapshot as M, type NetEvent as N, type TokenAdded as T, type ExecutionCompleted as a, type ExecutionStarted as b, type TokenRemoved as c, type TransitionClockRestarted as d, type TransitionCompleted as e, type TransitionEnabled as f, type TransitionFailed as g, type TransitionStarted as h, type TransitionTimedOut as i, eventTransitionName as j, eventsOfType as k, failures as l, filterEvents as m, inMemoryEventStore as n, isFailureEvent as o, noopEventStore as p, transitionEvents as t };
|