@tsplc/debug 0.2.17 → 0.2.19

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/index.js.map CHANGED
@@ -1,24 +1,27 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/debugger.ts", "../src/adapter.ts", "../src/hardware.ts", "../src/jobs.ts", "../src/paths.ts", "../src/telemetry.ts", "../src/timeline.ts", "../src/trace.ts", "../src/watch.ts", "../src/http.ts", "../src/manifest.ts", "../src/ui/index.ts", "../src/ui/page.ts", "../src/login.ts", "../src/opcua.ts"],
3
+ "sources": ["../src/debugger.ts", "../src/errors.ts", "../src/adapter.ts", "../src/hardware.ts", "../src/jobs.ts", "../src/paths.ts", "../src/timeline.ts", "../src/requests.ts", "../src/telemetry.ts", "../src/trace.ts", "../src/watch.ts", "../src/http.ts", "../src/manifest.ts", "../src/ui/index.ts", "../src/ui/page.ts", "../src/login.ts", "../src/login-value.ts", "../src/opcua.ts"],
4
4
  "sourcesContent": [
5
- "import { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { telemetryBatch, type TelemetryReply } from \"@tsplc/server/telemetry\";\nimport { z } from \"zod\";\nimport type { TargetAdapter, TargetRead, TargetSample } from \"./adapter.ts\";\nimport type {\n Interest,\n JobState,\n RequestTrace,\n Sample,\n Session,\n StreamEvents,\n TimelineEntry,\n WatchGroups,\n} from \"./api.ts\";\nimport { deviceReads, deviceState, healthReads } from \"./hardware.ts\";\nimport { busyOf, busyRead, detailReads, jobState, type TracedJob } from \"./jobs.ts\";\nimport type { DebugJob, DebugManifest } from \"./manifest.ts\";\nimport { createPaths } from \"./paths.ts\";\nimport { createTelemetryFollower, type ReceivedRecord } from \"./telemetry.ts\";\nimport { createTimeline, type Entry, timelineEntries } from \"./timeline.ts\";\nimport { createTraceDecoder } from \"./trace.ts\";\nimport { loadWatchGroups } from \"./watch.ts\";\n\nexport interface DebuggerOptions {\n manifest: DebugManifest;\n /** Owned by the debugger from here on: closing the debugger closes it. */\n adapter: TargetAdapter;\n /** Saved watch groups live here. */\n stateDirectory: string;\n /** `debug.watch` from the config. */\n watch: Record<string, string[]>;\n /** The app server, whose telemetry and request trace are pulled every second. */\n server?: { url: string; token: string };\n release?: Session[\"release\"];\n /** Entries from before the debugger started, such as the agent's deployments. */\n timeline?: readonly TimelineEntry[];\n projectRoot?: string;\n log: (message: string) => void;\n}\n\n/** A request the API refuses, with its HTTP status. */\nexport class DebugError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n }\n}\n\nexport type StreamMessage = {\n [Name in keyof StreamEvents]: { event: Name; data: StreamEvents[Name] };\n}[keyof StreamEvents];\n\nconst pullMs = 1000;\n/** Without telemetry, the build id is read through the controller this often. */\nconst buildCheckMs = 10_000;\n/** Device health, raw bytes and channels change rarely enough for this. */\nconst hardwareMs = 5000;\n/** Busy jobs whose details each poll reads; the rest show as busy only. */\nconst detailedJobs = 16;\nconst requestsRemembered = 1000;\n\nconst requestTrace = z.object({\n seq: z.number().int(),\n service: z.string(),\n job: z.number().int().optional(),\n sequence: z.number().int().optional(),\n startedAt: z.string(),\n durationMs: z.number().optional(),\n status: z.enum([\"pending\", \"ok\", \"error\", \"timeout\"]),\n httpStatus: z.number().int().optional(),\n error: z.string().optional(),\n input: z.unknown().optional(),\n output: z.unknown().optional(),\n}) satisfies z.ZodType<RequestTrace>;\nconst requestsReply = z.object({ requests: z.array(requestTrace), latest: z.number().int() });\nconst telemetryReply = z.object({\n batches: z.array(telemetryBatch.extend({ seq: z.number().int(), receivedAt: z.string() })),\n latest: z.number().int(),\n}) satisfies z.ZodType<TelemetryReply>;\n\nconst message = (error: unknown) => (error instanceof Error ? error.message : String(error));\n\n/** Counts how many streams show each key. */\nconst createShown = <Key>() => {\n const counts = new Map<Key, number>();\n return {\n has: (key: Key) => counts.has(key),\n add: (keys: readonly Key[]) => {\n for (const key of keys) counts.set(key, (counts.get(key) ?? 0) + 1);\n return () => {\n for (const key of keys) {\n const count = counts.get(key)! - 1;\n if (count) counts.set(key, count);\n else counts.delete(key);\n }\n };\n },\n };\n};\n\n/**\n * The debugger for one build on one controller (docs/design/debugging.md). It reads what the\n * pages show through the adapter, follows the app server's telemetry and requests, and keeps the\n * recent window of both. Everything it offers is read-only.\n */\nexport const createDebugger = async (options: DebuggerOptions) => {\n const { manifest, adapter } = options;\n const paths = createPaths(manifest);\n const trace = createTraceDecoder(manifest, paths);\n const telemetry = createTelemetryFollower(manifest);\n const timeline = createTimeline();\n const watchGroups = await loadWatchGroups(\n join(options.stateDirectory, \"watch.json\"),\n options.watch,\n );\n const listeners = new Set<(message: StreamMessage) => void>();\n const controller = new AbortController();\n const { signal } = controller;\n let controllerBuild: string | null = null;\n\n const emit = (message: StreamMessage) => {\n for (const listener of listeners) listener(message);\n };\n const record = (entry: TimelineEntry) => {\n timeline.add(entry);\n emit({ event: \"timeline\", data: entry });\n };\n for (const entry of options.timeline ?? []) timeline.add(entry);\n\n const session = (): Session => ({\n build: {\n manifest: manifest.build.id,\n controller: controllerBuild,\n matches: controllerBuild === manifest.build.id,\n },\n connection: { ...adapter.connection(), endpoint: adapter.endpoint },\n reading: { method: adapter.method, intervalMs: adapter.samplingMs },\n tasks: telemetry.tasks(),\n clock: telemetry.clock(),\n ...(options.release && { release: options.release }),\n ...(options.projectRoot && { projectRoot: options.projectRoot }),\n });\n\n const setBuild = (build: string) => {\n if (build === controllerBuild) return;\n controllerBuild = build;\n emit({ event: \"session\", data: session() });\n };\n\n // --- Values by TypeScript path ---------------------------------------------------------------\n\n const unavailable = (path: string, status: string): Sample => ({\n path,\n value: null,\n quality: \"unavailable\",\n status,\n receivedAt: new Date().toISOString(),\n });\n\n /** A path's target, or the sample it has without reading the controller. */\n const locate = (path: string): { target: string; type: string } | Sample => {\n const resolved = paths.resolve(path);\n if (!resolved) return unavailable(path, \"Unknown path\");\n if (resolved.kind === \"constant\")\n return {\n path,\n value: resolved.value,\n quality: \"good\",\n status: \"Constant\",\n receivedAt: new Date().toISOString(),\n };\n if (!resolved.readable) return unavailable(path, \"Not readable\");\n return resolved;\n };\n\n const targetRead = ({ target, type }: { target: string; type: string }): TargetRead => ({\n target,\n type: paths.typeOf(type),\n });\n\n const sampleOf = (path: string, type: string, sample: TargetSample): Sample => ({\n path,\n ...sample,\n value: paths.decode(type, sample.value),\n });\n\n /** Reads the leaves `patterns` match each sampling interval, until the returned function is called. */\n const watch = (patterns: readonly string[], listener: (sample: Sample) => void) => {\n const watched = new Map<string, { path: string; type: string }[]>();\n const reads: TargetRead[] = [];\n for (const path of paths.expand(patterns)) {\n const located = locate(path);\n if (!(\"target\" in located)) {\n listener(located);\n continue;\n }\n if (!watched.has(located.target)) reads.push(targetRead(located));\n watched.set(located.target, [...(watched.get(located.target) ?? []), { path, ...located }]);\n }\n if (!reads.length) return () => {};\n return adapter.subscribe(reads, (target, received) => {\n for (const { path, type } of watched.get(target) ?? [])\n listener(sampleOf(path, type, received));\n });\n };\n\n const values = async (patterns: readonly string[]) => {\n const connection = adapter.connection();\n if (connection.state !== \"connected\")\n throw new DebugError(connection.error ?? \"The controller is not connected\", 503);\n const located = paths.expand(patterns).map((path) => ({ path, located: locate(path) }));\n const read = await adapter.read(\n located.flatMap(({ located }) => (\"target\" in located ? [targetRead(located)] : [])),\n );\n return located.map(({ path, located }) => {\n if (!(\"target\" in located)) return located;\n const sample = read.get(located.target);\n return sample ? sampleOf(path, located.type, sample) : unavailable(path, \"Not read\");\n });\n };\n\n const stopBuild = adapter.subscribe(\n [{ target: manifest.build.target, type: { kind: \"scalar\", iec: \"STRING\" } }],\n (_, sample) => {\n if (sample.quality === \"good\" && typeof sample.value === \"string\") setBuild(sample.value);\n },\n buildCheckMs,\n );\n\n // --- Jobs and devices, read only while shown -------------------------------------------------\n\n const latest = new Map<string, TargetSample>();\n const traced = new Map<number, TracedJob>();\n const failures = new Map<number, NonNullable<JobState[\"failure\"]>>();\n /** The server's traces by `<job id>:<service>:<sequence>`, newest last. */\n const requests = new Map<string, RequestTrace>();\n let unread = new Set<number>();\n const shownJobs = createShown<number>();\n const shownHealth = createShown<string>();\n const shownDevices = createShown<string>();\n /** The JSON of what each stream last got, so unchanged states aren't sent again. */\n const sent = new Map<string, string>();\n\n const jobOf = (job: DebugJob) =>\n jobState(job, {\n value: (target) => latest.get(target),\n traced: traced.get(job.id),\n failure: failures.get(job.id),\n unread: unread.has(job.id),\n clock: telemetry.clock(),\n now: Date.now(),\n request: ({ job, service, sequence }) => requests.get(`${job}:${service}:${sequence}`),\n });\n const deviceOf = (id: string) =>\n deviceState(\n manifest.devices.find((device) => device.id === id)!,\n manifest.io,\n (target) => latest.get(target),\n );\n const send = (key: string, message: StreamMessage) => {\n const json = JSON.stringify(message.data);\n if (sent.get(key) === json) return;\n sent.set(key, json);\n emit(message);\n };\n const updateJob = (job: DebugJob) => send(`job:${job.id}`, { event: \"job\", data: jobOf(job) });\n const updateDevice = (id: string) =>\n send(`device:${id}`, { event: \"device\", data: deviceOf(id) });\n\n /** Re-subscribes `reads` when they change, telling `update` which owners each sample is for. */\n const reader = <Owner>(intervalMs: number, update: (owner: Owner) => void) => {\n let current = { key: \"\", stop: () => {} };\n return (reads: { owner: Owner; read: TargetRead }[]) => {\n const key = reads.map(({ read }) => read.target).join(\"\\n\");\n if (key === current.key) return;\n current.stop();\n const owners = new Map<string, Owner[]>();\n for (const { owner, read } of reads)\n owners.set(read.target, [...(owners.get(read.target) ?? []), owner]);\n current = {\n key,\n stop: reads.length\n ? adapter.subscribe(\n [...new Map(reads.map(({ read }) => [read.target, read])).values()],\n (target, sample) => {\n latest.set(target, sample);\n for (const owner of owners.get(target) ?? []) update(owner);\n schedule();\n },\n intervalMs,\n )\n : () => {},\n };\n };\n };\n const readJobs = reader<DebugJob>(adapter.samplingMs, updateJob);\n const readDevices = reader<string>(hardwareMs, updateDevice);\n\n /** Reads `busy` of the shown jobs, and the details of the busy ones. */\n const plan = () => {\n const shown = manifest.jobs.filter((job) => shownJobs.has(job.id));\n const busy = shown.filter((job) =>\n busyOf(job, (target) => latest.get(target), traced.get(job.id)),\n );\n unread = new Set(busy.slice(detailedJobs).map(({ id }) => id));\n readJobs([\n ...shown.map((job) => ({ owner: job, read: busyRead(job) })),\n ...busy\n .slice(0, detailedJobs)\n .flatMap((job) => detailReads(job).map((read) => ({ owner: job, read }))),\n ]);\n readDevices(\n manifest.devices.flatMap((device) =>\n (shownDevices.has(device.id)\n ? deviceReads(device, manifest.io, paths.typeOf)\n : shownHealth.has(device.id)\n ? healthReads(device)\n : []\n ).map((read) => ({ owner: device.id, read })),\n ),\n );\n };\n let planned = false;\n const schedule = () => {\n if (planned) return;\n planned = true;\n queueMicrotask(() => {\n planned = false;\n plan();\n });\n };\n\n /** Reads what `interest` shows until the returned function is called. */\n const show = (interest: Omit<Interest, \"watch\">) => {\n const stops = [\n shownJobs.add(interest.jobs),\n shownHealth.add(interest.health),\n shownDevices.add(interest.devices),\n ];\n schedule();\n return () => {\n for (const stop of stops) stop();\n schedule();\n };\n };\n\n // --- The app server ---------------------------------------------------------------------------\n\n const receive = ({ build, task, sequence, at, record: received }: ReceivedRecord) => {\n if (received.kind === \"trace\") {\n // Event sites of another build would decode to the wrong source.\n if (build !== manifest.build.id) return;\n const event = trace.decode(received, task, sequence);\n if (event) record(timelineEntries.trace(at, event));\n const site = trace.job(received);\n if (!site) return;\n const startedAt = site.started ? at : traced.get(site.job.id)?.startedAt;\n traced.set(site.job.id, { busy: site.started, ...(startedAt && { startedAt }) });\n updateJob(site.job);\n schedule();\n return;\n }\n record(timelineEntries.app(at, task, sequence, received));\n if (received.kind !== \"exception\" || received.handled) return;\n const job = manifest.jobs.find(\n ({ name, instance }) => name === received.function && instance === received.instance,\n );\n if (!job) return;\n failures.set(job.id, {\n at,\n code: received.code,\n ...(received.name && { name: received.name }),\n source: received.source,\n });\n updateJob(job);\n };\n\n const pull = async (url: URL, token: string) => {\n const response = await fetch(url, { headers: { authorization: `Bearer ${token}` }, signal });\n if (!response.ok) throw new Error(`The server answered ${response.status}`);\n return response.json();\n };\n\n const pullTelemetry = async ({ url, token }: { url: string; token: string }) => {\n const reply = telemetryReply.parse(\n await pull(new URL(`/tsplc/telemetry?since=${telemetry.since()}`, url), token),\n );\n const received = telemetry.accept(reply);\n for (const item of received) receive(item);\n const build = telemetry.build();\n if (build) setBuild(build);\n // Scan rates and the clock estimate change with every batch.\n if (reply.batches.length) emit({ event: \"session\", data: session() });\n };\n\n /** Follows the server's ring, asking again from before the oldest call still pending. */\n const pullRequests = ({ url, token }: { url: string; token: string }) => {\n let newest = 0;\n const pending = new Map<number, Entry<\"request\">>();\n return async () => {\n const since = pending.size ? Math.min(...pending.keys()) - 1 : newest;\n const body = requestsReply.parse(\n await pull(new URL(`/tsplc/debug/requests?since=${since}`, url), token),\n );\n // A restarted server counts from 1 again.\n if (body.latest < newest) {\n newest = 0;\n pending.clear();\n return;\n }\n const oldest = body.requests[0]?.seq;\n if (oldest !== undefined)\n for (const seq of pending.keys()) if (seq < oldest) pending.delete(seq);\n for (const request of body.requests) {\n const waiting = pending.get(request.seq);\n if (waiting && request.status === \"pending\") continue;\n if (!waiting && request.seq <= newest) continue;\n const entry = waiting ?? timelineEntries.request(request);\n entry.request = request;\n newest = Math.max(newest, request.seq);\n if (request.status === \"pending\") pending.set(request.seq, entry);\n else pending.delete(request.seq);\n if (!waiting) timeline.add(entry);\n emit({ event: \"request\", data: request });\n emit({ event: \"timeline\", data: entry });\n if (request.job === undefined || request.sequence === undefined) continue;\n requests.set(`${request.job}:${request.service}:${request.sequence}`, request);\n for (const key of [...requests.keys()].slice(0, -requestsRemembered)) requests.delete(key);\n const job = manifest.jobs.find(({ id }) => id === request.job);\n if (job) updateJob(job);\n }\n };\n };\n\n // --- Background work -------------------------------------------------------------------------\n\n const stopConnection = adapter.onConnection((connection) => {\n record(timelineEntries.connection(connection.since, connection.state, connection.error));\n emit({ event: \"session\", data: session() });\n if (connection.state !== \"connected\") {\n for (const [target, sample] of latest)\n latest.set(target, {\n ...sample,\n quality: \"unavailable\",\n status: connection.error ?? \"The controller is not connected\",\n });\n for (const job of manifest.jobs) updateJob(job);\n for (const device of manifest.devices) updateDevice(device.id);\n }\n });\n\n const repeat = async (name: string, intervalMs: number, work: () => Promise<void>) => {\n let failure: string | undefined;\n while (!signal.aborted) {\n try {\n await work();\n failure = undefined;\n } catch (error) {\n if (signal.aborted) return;\n if (message(error) !== failure) options.log(`${name} failed: ${message(error)}`);\n failure = message(error);\n }\n await delay(intervalMs, undefined, { signal }).catch(() => undefined);\n }\n };\n\n const { server } = options;\n const running = server\n ? [\n repeat(\"Reading the server's telemetry\", pullMs, () => pullTelemetry(server)),\n repeat(\"Reading the server's requests\", pullMs, pullRequests(server)),\n ]\n : [];\n\n return {\n manifest,\n paths,\n session,\n values,\n jobs: () => manifest.jobs.map(jobOf),\n hardware: () => manifest.devices.map(({ id }) => deviceOf(id)),\n timeline: (since?: string) => timeline.since(since),\n watchGroups: () => watchGroups.groups(),\n saveWatchGroups: (groups: WatchGroups) => watchGroups.save(groups),\n /** Adds an entry from another source, such as the agent's audit log. */\n record,\n watch,\n show,\n /** Calls `listener` with every other stream event until the returned function is called. */\n subscribe: (listener: (message: StreamMessage) => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n close: async () => {\n controller.abort();\n stopBuild();\n readJobs([]);\n readDevices([]);\n stopConnection();\n await Promise.all(running);\n await adapter.close();\n },\n };\n};\n\nexport type Debugger = Awaited<ReturnType<typeof createDebugger>>;\n",
6
- "import type { ConnectionState, Quality } from \"./api.ts\";\nimport type { DebugType } from \"./manifest.ts\";\n\n/** One target's value, before the debugger names it by TypeScript path and decodes it. */\nexport interface TargetSample {\n value: unknown;\n quality: Quality;\n status: string;\n receivedAt: string;\n}\n\n/** A target to read, with its type in the manifest, which an adapter may need to parse it. */\nexport interface TargetRead {\n target: string;\n type: DebugType;\n}\n\nconst qualityRank: Record<Quality, number> = { good: 0, uncertain: 1, bad: 2, unavailable: 3 };\n\n/** The worst of these qualities; nothing read is unavailable. */\nexport const worstQuality = (samples: readonly (TargetSample | undefined)[]): Quality =>\n samples.reduce<Quality>((worst, sample) => {\n const quality = sample?.quality ?? \"unavailable\";\n return qualityRank[quality] > qualityRank[worst] ? quality : worst;\n }, \"good\");\n\nexport interface Connection {\n state: ConnectionState;\n since: string;\n error?: string;\n}\n\n/**\n * Reads one vendor's controller. Only the adapter interprets `target` strings, which come from\n * the manifest (for CODESYS, IEC symbol paths). It never writes.\n */\nexport interface TargetAdapter {\n /** How it reads, for display, such as \"engineering login\". */\n readonly method: string;\n /** Where it reads, for display. */\n readonly endpoint: string;\n /** How often subscribed targets are read; a value is at most about this old while connected. */\n readonly samplingMs: number;\n connection(): Connection;\n onConnection(listener: (connection: Connection) => void): () => void;\n /** Reads targets now; fails while disconnected. Targets that can't be read come back bad or unavailable. */\n read(targets: readonly TargetRead[]): Promise<Map<string, TargetSample>>;\n /**\n * Calls `listener` with each target's value, about every `intervalMs` (`samplingMs` by\n * default) or on every change, across reconnects, until the returned function is called. While\n * disconnected each target is reported unavailable or bad.\n */\n subscribe(\n targets: readonly TargetRead[],\n listener: (target: string, sample: TargetSample) => void,\n intervalMs?: number,\n ): () => void;\n close(): Promise<void>;\n}\n",
7
- "import { type TargetRead, type TargetSample, worstQuality } from \"./adapter.ts\";\nimport type { DeviceState } from \"./api.ts\";\nimport type { DebugDevice, DebugIo, DebugType } from \"./manifest.ts\";\n\n/** Driver state names that mean the connection isn't working. */\nconst faultyState = /error|fault|fail|timeout|lost|closed/i;\n\n/** Hand-configured status symbols have no type in the manifest; they show as read. */\nconst untyped: DebugType = { kind: \"scalar\", iec: \"ANY\" };\n\n/** What a device's health is read from: the driver's own state, when the build names it. */\nexport const healthReads = (device: DebugDevice): TargetRead[] => {\n const { state, states, diagnostic, message } = device.health ?? {};\n return [\n ...(state\n ? [\n {\n target: state,\n type: states\n ? { kind: \"enum\" as const, name: \"state\", members: states }\n : { kind: \"scalar\" as const, iec: \"DINT\" },\n },\n ]\n : []),\n ...(diagnostic ? [{ target: diagnostic, type: { kind: \"scalar\" as const, iec: \"BOOL\" } }] : []),\n ...(message ? [{ target: message, type: { kind: \"scalar\" as const, iec: \"STRING\" } }] : []),\n ];\n};\n\n/** Everything a device's page shows: its health, raw assembly bytes, bound channels and status symbols. */\nexport const deviceReads = (\n device: DebugDevice,\n io: readonly DebugIo[],\n typeOf: (id: string) => DebugType,\n): TargetRead[] => [\n ...healthReads(device),\n ...device.assemblies.flatMap(({ raw, bytes }) =>\n raw\n ? [\n {\n target: raw,\n type: { kind: \"array\" as const, element: \"BYTE\", length: bytes, lower: 0 },\n },\n ]\n : [],\n ),\n ...io\n .filter((binding) => binding.device === device.id)\n .map(({ target, type }) => ({ target, type: typeOf(type) })),\n ...Object.values(device.status ?? {}).map((target) => ({ target, type: untyped })),\n];\n\nconst health = (\n device: DebugDevice,\n value: (target: string) => TargetSample | undefined,\n): DeviceState[\"health\"] => {\n const { state, states, diagnostic, message } = device.health ?? {};\n if (!state && !diagnostic) return { state: \"unknown\", quality: \"unavailable\" };\n const stateSample = state ? value(state) : undefined;\n const diagnosticSample = diagnostic ? value(diagnostic) : undefined;\n const messageSample = message ? value(message) : undefined;\n const quality = worstQuality([\n ...(state ? [stateSample] : []),\n ...(diagnostic ? [diagnosticSample] : []),\n ]);\n const number = typeof stateSample?.value === \"number\" ? stateSample.value : undefined;\n // The login names enum members the manifest may not list.\n const name =\n Object.entries(states ?? {}).find(([, member]) => member === number)?.[0] ??\n (typeof stateSample?.value === \"string\" ? stateSample.value : undefined);\n const faulted =\n diagnosticSample?.value === true || (name !== undefined && faultyState.test(name));\n return {\n state: quality !== \"good\" ? \"stale\" : faulted ? \"fault\" : \"ok\",\n ...(number !== undefined && { value: number }),\n ...(name && { name }),\n ...(typeof diagnosticSample?.value === \"boolean\" && { diagnostic: diagnosticSample.value }),\n ...(typeof messageSample?.value === \"string\" && { message: messageSample.value }),\n quality,\n };\n};\n\n/**\n * A device's driver health, raw assembly bytes, bound channel values and status symbols. Health\n * is \"unknown\" unless the manifest names the driver's own state.\n */\nexport const deviceState = (\n device: DebugDevice,\n io: readonly DebugIo[],\n value: (target: string) => TargetSample | undefined,\n): DeviceState => ({\n id: device.id,\n health: health(device, value),\n assemblies: device.assemblies.map(({ direction, address, raw }) => {\n const sample = raw ? value(raw) : undefined;\n return {\n direction,\n ...(address && { address }),\n bytes:\n Array.isArray(sample?.value) &&\n sample.value.every((byte): byte is number => typeof byte === \"number\")\n ? sample.value\n : null,\n quality: sample?.quality ?? \"unavailable\",\n };\n }),\n channels: io.flatMap((binding) =>\n binding.device === device.id && binding.channel\n ? [\n {\n id: binding.channel,\n path: binding.path,\n value: value(binding.target)?.value ?? null,\n quality: value(binding.target)?.quality ?? \"unavailable\",\n },\n ]\n : [],\n ),\n status: Object.fromEntries(\n Object.entries(device.status ?? {}).map(([label, target]) => [\n label,\n { value: value(target)?.value ?? null, quality: value(target)?.quality ?? \"unavailable\" },\n ]),\n ),\n});\n",
8
- "import type { TargetRead, TargetSample } from \"./adapter.ts\";\nimport type { JobState, RequestTrace, Session } from \"./api.ts\";\nimport type { DebugJob, DebugType } from \"./manifest.ts\";\n\nconst scalar = (iec: string): DebugType => ({ kind: \"scalar\", iec });\n\n/** What the trace said of a job: whether it is running, and when it last started. */\nexport interface TracedJob {\n busy: boolean;\n startedAt?: string;\n}\n\n/** The job's `busy` flag, read while a page shows the job and the trace says nothing of it. */\nexport const busyRead = (job: DebugJob): TargetRead => ({\n target: `${job.target}.busy`,\n type: scalar(\"BOOL\"),\n});\n\n/** What a busy job shows: where it waits, since when, and its latest request. */\nexport const detailReads = (job: DebugJob): TargetRead[] => [\n { target: `${job.target}.step`, type: scalar(\"UINT\") },\n { target: `${job.target}.cancelling`, type: scalar(\"BOOL\") },\n ...(job.startedAt ? [{ target: job.startedAt, type: scalar(\"UDINT\") }] : []),\n ...job.requests.map(({ sequence }) => ({ target: sequence, type: scalar(\"UDINT\") })),\n];\n\n/**\n * From the last read, else from the trace; null when neither knows. A read wins: a job's caller\n * stops running it once it finishes, so the trace can miss the finish.\n */\nexport const busyOf = (\n job: DebugJob,\n value: (target: string) => TargetSample | undefined,\n traced: TracedJob | undefined,\n) => {\n const read = value(busyRead(job).target);\n return read?.quality === \"good\" ? read.value === true : (traced?.busy ?? null);\n};\n\nconst numberOf = (sample: TargetSample | undefined) =>\n sample?.quality === \"good\" && typeof sample.value === \"number\" ? sample.value : undefined;\n\n/**\n * A job as the debugger shows it at host time `now`. Details are shown only while it is busy;\n * its last start stays, so a later run tells a failure apart from the current state. Without a\n * clock estimate there is no start time from the PLC's own `startedAt`.\n */\nexport const jobState = (\n job: DebugJob,\n inputs: {\n value: (target: string) => TargetSample | undefined;\n traced: TracedJob | undefined;\n failure: JobState[\"failure\"];\n /** Busy, but its details aren't read for want of room in the poll. */\n unread: boolean;\n clock: Session[\"clock\"];\n now: number;\n /** The server's trace of a call, which the PLC tags with its job and the call site's count. */\n request: (call: { job: number; service: string; sequence: number }) => RequestTrace | undefined;\n },\n): JobState => {\n const { value, traced, clock, now } = inputs;\n const busy = busyOf(job, value, traced);\n const startedPlc = job.startedAt === undefined ? undefined : numberOf(value(job.startedAt));\n const startedAt =\n traced?.startedAt ??\n (clock && startedPlc !== undefined\n ? new Date(startedPlc - clock.offsetMs).toISOString()\n : undefined);\n const base: JobState = {\n id: job.id,\n quality: value(busyRead(job).target)?.quality ?? (traced ? \"good\" : \"unavailable\"),\n busy,\n ...(startedAt && { startedAt }),\n ...(inputs.failure && { failure: inputs.failure }),\n };\n if (!busy) return base;\n if (inputs.unread) return { ...base, unread: true };\n\n const step = numberOf(value(`${job.target}.step`));\n const current = job.steps.find((candidate) => candidate.step === step);\n // Each call site counts its own requests, so the latest is the one the server saw start last,\n // or the one counted furthest while the server has yet to report them.\n const calls = job.requests\n .map((call) => {\n const sequence = numberOf(value(call.sequence)) ?? 0;\n const trace = inputs.request({ job: call.job ?? job.id, service: call.service, sequence });\n return { service: call.service, sequence, trace };\n })\n .filter(({ sequence }) => sequence > 0);\n const later = (call: (typeof calls)[number], than: (typeof calls)[number]) =>\n call.trace && than.trace\n ? call.trace.startedAt > than.trace.startedAt\n : call.sequence > than.sequence;\n const latest = calls.reduce<(typeof calls)[number] | undefined>(\n (latest, call) => (latest && !later(call, latest) ? latest : call),\n undefined,\n );\n const cancelling = value(`${job.target}.cancelling`);\n\n return {\n ...base,\n ...(cancelling?.quality === \"good\" && { cancelling: cancelling.value === true }),\n ...(step !== undefined && { step }),\n ...(current && { current: { kind: current.kind, range: current.range, text: current.text } }),\n ...(startedAt && { elapsedMs: Math.max(0, now - Date.parse(startedAt)) }),\n ...(latest && {\n request: {\n service: latest.service,\n sequence: latest.sequence,\n ...(latest.trace && { trace: latest.trace }),\n },\n }),\n };\n};\n",
9
- "import type { DebugManifest, DebugType, SourceRange } from \"./manifest.ts\";\n\n/**\n * TypeScript paths over a manifest: `program.diverters.binTrackers[10].bin` names a root\n * (`program.diverters`), then record fields and array indexes. Pure, so the browser UI can use it.\n */\n\n/** A path that reads a target, or a constant the compiler folded. */\nexport type ResolvedPath =\n | {\n kind: \"target\";\n path: string;\n target: string;\n type: string;\n readable: boolean;\n generated?: true;\n declaration?: SourceRange;\n }\n | { kind: \"constant\"; path: string; type: string; value: unknown; declaration?: SourceRange };\n\n/** Roots or constants that share a prefix, such as `program` above `program.diverters`. */\ninterface GroupPath {\n kind: \"group\";\n path: string;\n}\n\n/** A child in the instance tree. */\nexport type PathNode = { name: string } & (ResolvedPath | GroupPath);\n\nconst segmentPattern = /[^.[\\]]+|\\[(?:-?\\d+|\\*)\\]/g;\n\nexport const pathSegments = (path: string) => path.match(segmentPattern) ?? [];\n\nexport const joinPath = (prefix: string, segment: string) =>\n segment.startsWith(\"[\") || !prefix ? `${prefix}${segment}` : `${prefix}.${segment}`;\n\n/** Scalar type ids are their IEC names, and may have no entry in `types`. */\nexport const typeOf = (manifest: DebugManifest, id: string): DebugType =>\n manifest.types[id] ?? { kind: \"scalar\", iec: id };\n\nexport const createPaths = (manifest: DebugManifest) => {\n const typeOfId = (id: string) => typeOf(manifest, id);\n // I/O bindings are readable symbols with TypeScript paths of their own.\n const bases = new Map<string, Extract<ResolvedPath, { kind: \"target\" }>>([\n ...manifest.roots.map(\n ({ path, ...root }) => [path, { kind: \"target\" as const, path, ...root }] as const,\n ),\n ...manifest.io.map(\n ({ path, target, type }) =>\n [path, { kind: \"target\" as const, path, target, type, readable: true }] as const,\n ),\n ]);\n const constants = new Map(\n manifest.constants.map(({ path, ...constant }) => [\n path,\n { kind: \"constant\" as const, path, ...constant },\n ]),\n );\n /** Children of the prefixes of every root and constant path, which are groups unless they resolve. */\n const groups = new Map<string, Set<string>>();\n for (const path of [...bases.keys(), ...constants.keys()]) {\n let prefix = \"\";\n for (const segment of pathSegments(path)) {\n let children = groups.get(prefix);\n if (!children) groups.set(prefix, (children = new Set()));\n children.add(segment);\n prefix = joinPath(prefix, segment);\n }\n }\n\n const resolve = (path: string): ResolvedPath | undefined => {\n const constant = constants.get(path);\n if (constant) return constant;\n const segments = pathSegments(path);\n for (let length = segments.length; length > 0; length--) {\n const base = bases.get(segments.slice(0, length).reduce(joinPath, \"\"));\n if (!base) continue;\n let resolved: ResolvedPath = base;\n for (const segment of segments.slice(length)) {\n const type = typeOfId(resolved.type);\n if (type.kind === \"record\") {\n const field = type.fields.find(({ name }) => name === segment);\n if (!field) return;\n resolved = {\n kind: \"target\",\n path: joinPath(resolved.path, segment),\n target: `${resolved.target}.${field.target}`,\n type: field.type,\n readable: resolved.readable,\n ...(field.generated && { generated: true }),\n ...(field.declaration && { declaration: field.declaration }),\n };\n } else if (type.kind === \"array\") {\n const index = /^\\[(-?\\d+)\\]$/.exec(segment)?.[1];\n if (\n index === undefined ||\n Number(index) < type.lower ||\n Number(index) >= type.lower + type.length\n )\n return;\n resolved = {\n kind: \"target\",\n path: joinPath(resolved.path, segment),\n target: `${resolved.target}[${index}]`,\n type: type.element,\n readable: resolved.readable,\n };\n } else return;\n }\n return resolved;\n }\n };\n\n const typedChildren = (resolved: ResolvedPath | undefined) => {\n const type = resolved?.kind === \"target\" ? typeOfId(resolved.type) : undefined;\n if (type?.kind === \"record\") return type.fields.map(({ name }) => name);\n if (type?.kind === \"array\")\n return Array.from({ length: type.length }, (_, index) => `[${type.lower + index}]`);\n return [];\n };\n\n /** A path's fields or indexes, and the roots and constants below it. */\n const children = (path: string): PathNode[] => {\n const names = [...typedChildren(resolve(path)), ...(groups.get(path) ?? [])];\n return [...new Set(names)].map((name) => {\n const child = joinPath(path, name);\n return { name, ...(resolve(child) ?? { kind: \"group\", path: child }) };\n });\n };\n\n const isLeaf = (node: ResolvedPath | GroupPath) =>\n node.kind === \"constant\" ||\n (node.kind === \"target\" && [\"scalar\", \"enum\"].includes(typeOfId(node.type).kind));\n\n /**\n * Leaf paths matching `patterns`, where `*` stands for one segment. A pattern naming a record,\n * array or group stands for all its leaves; wildcards and expansion skip compiler-made fields.\n * Paths that don't resolve are kept, so callers can report them.\n */\n const expand = (patterns: readonly string[], limit = 2000) => {\n const leaves = new Set<string>();\n const add = (path: string) => {\n leaves.add(path);\n if (leaves.size > limit) throw new RangeError(`More than ${limit} values match`);\n };\n const below = (node: ResolvedPath | GroupPath) => {\n if (isLeaf(node)) return add(node.path);\n for (const child of children(node.path))\n if (!(child.kind === \"target\" && child.generated)) below(child);\n };\n const match = (prefix: string, rest: readonly string[], wildcard: boolean) => {\n const [head, ...tail] = rest;\n if (head === undefined) {\n const node: ResolvedPath | GroupPath | undefined =\n resolve(prefix) ?? (groups.has(prefix) ? { kind: \"group\", path: prefix } : undefined);\n if (node) below(node);\n else if (!wildcard) add(prefix);\n return;\n }\n if (head === \"*\" || head === \"[*]\") {\n for (const child of children(prefix))\n if (\n !(child.kind === \"target\" && child.generated) &&\n (head === \"*\" || child.name.startsWith(\"[\"))\n )\n match(child.path, tail, true);\n } else match(joinPath(prefix, head), tail, wildcard);\n };\n for (const pattern of patterns) match(\"\", pathSegments(pattern), false);\n return [...leaves];\n };\n\n /** A value as TypeScript shows it: enum members by name, BOOL as a boolean. */\n const decode = (typeId: string, raw: unknown) => {\n const type = typeOfId(typeId);\n if (type.kind === \"enum\")\n return Object.entries(type.members).find(([, value]) => value === raw)?.[0] ?? raw;\n if (type.kind === \"scalar\" && type.iec === \"BOOL\" && typeof raw === \"number\") return raw !== 0;\n return raw;\n };\n\n return { typeOf: typeOfId, resolve, children, isLeaf, expand, decode };\n};\n\nexport type Paths = ReturnType<typeof createPaths>;\n",
10
- "import type { TelemetryBatch, TelemetryRecord, TelemetryReply } from \"@tsplc/server/telemetry\";\nimport { recordedAt } from \"@tsplc/server/telemetry-log\";\nimport type { Session } from \"./api.ts\";\nimport type { DebugManifest } from \"./manifest.ts\";\n\n/** Clock estimates are kept this long, on the server's clock. */\nconst clockWindowMs = 60_000;\n\n/** A record with the batch it came in, numbered in its task's sequence, at its time on the server's clock. */\nexport interface ReceivedRecord {\n build: string;\n task: string;\n sequence: number;\n at: string;\n record: TelemetryRecord;\n}\n\n/**\n * Follows the app server's telemetry ring (`GET /tsplc/telemetry`): it hands out each new record\n * once, keeps the tasks' scan rates, and estimates the PLC's clock against the server's.\n */\nexport const createTelemetryFollower = (manifest: DebugManifest) => {\n const intervals = new Map(manifest.tasks.map(({ name, intervalMs }) => [name, intervalMs]));\n const tasks = new Map<string, Session[\"tasks\"][number]>(\n manifest.tasks.map(({ name }) => [\n name,\n { name, scan: null, scansPerSecond: null, dropped: 0 },\n ]),\n );\n const rates = new Map<string, { scan: number; now: number }>();\n let estimates: { offsetMs: number; intervalMs: number; at: number }[] = [];\n let newest = 0;\n let build: string | null = null;\n\n /**\n * A batch's `now` was read before it was sent, so `now − receivedAt` falls short of the true\n * offset by its transit time: the largest recent estimate is the closest, and their spread,\n * plus a scan, bounds how far off it may be.\n */\n const clock = (): Session[\"clock\"] => {\n if (!estimates.length) return null;\n const offsets = estimates.map(({ offsetMs }) => offsetMs);\n const best = estimates.reduce((best, estimate) =>\n estimate.offsetMs > best.offsetMs ? estimate : best,\n );\n return {\n offsetMs: best.offsetMs,\n uncertaintyMs: best.offsetMs - Math.min(...offsets) + best.intervalMs,\n };\n };\n\n const observe = (batch: TelemetryBatch, receivedAt: number) => {\n const rate = rates.get(batch.task);\n // A restarted PLC counts scans and time from zero again.\n const restarted = rate !== undefined && batch.now < rate.now;\n if (restarted) estimates = [];\n estimates = estimates.filter(({ at }) => receivedAt - at < clockWindowMs);\n estimates.push({\n offsetMs: batch.now - receivedAt,\n intervalMs: intervals.get(batch.task) ?? 0,\n at: receivedAt,\n });\n const stats = {\n name: batch.task,\n scansPerSecond: tasks.get(batch.task)?.scansPerSecond ?? null,\n scan: batch.scan,\n dropped: batch.dropped,\n };\n if (!rate || restarted) rates.set(batch.task, { scan: batch.scan, now: batch.now });\n else if (batch.now - rate.now >= 1000) {\n stats.scansPerSecond = ((batch.scan - rate.scan) * 1000) / (batch.now - rate.now);\n rates.set(batch.task, { scan: batch.scan, now: batch.now });\n }\n tasks.set(batch.task, stats);\n };\n\n return {\n /** Where the next pull starts. */\n since: () => newest,\n /** Takes a reply to `GET /tsplc/telemetry?since=<since()>`; a restarted server starts over. */\n accept: (reply: TelemetryReply): ReceivedRecord[] => {\n if (reply.latest < newest) {\n newest = 0;\n return [];\n }\n const received: ReceivedRecord[] = [];\n for (const batch of reply.batches) {\n if (batch.seq <= newest) continue;\n newest = batch.seq;\n build = batch.build;\n const receivedAt = new Date(batch.receivedAt);\n observe(batch, receivedAt.getTime());\n batch.records.forEach((record, index) =>\n received.push({\n build: batch.build,\n task: batch.task,\n sequence: batch.first + index,\n at: recordedAt(batch, record, receivedAt).toISOString(),\n record,\n }),\n );\n }\n return received;\n },\n /** The build the newest batch came from. */\n build: () => build,\n clock,\n tasks: () => [...tasks.values()].map((task) => ({ ...task })),\n };\n};\n",
11
- "import type { AppRecord, ConnectionState, RequestTrace, TimelineEntry, TraceEvent } from \"./api.ts\";\n\nexport type Entry<Kind extends TimelineEntry[\"kind\"]> = Extract<TimelineEntry, { kind: Kind }>;\ntype Details<Kind extends TimelineEntry[\"kind\"]> = Omit<\n Entry<Kind>,\n \"at\" | \"approximate\" | \"source\" | \"kind\"\n>;\n\n/**\n * Timeline entries by source. The PLC's records are placed on the app server's clock from their\n * age when the server received them, and the server keeps its own clock, so those are\n * approximate. The agent's entries reach a debugger only when the agent hosts it, on the same clock.\n */\nexport const timelineEntries = {\n app: (at: string, task: string, sequence: number, record: AppRecord): Entry<\"app\"> => ({\n at,\n approximate: true,\n source: \"plc\",\n kind: \"app\",\n task,\n sequence,\n record,\n }),\n trace: (at: string, trace: TraceEvent): Entry<\"trace\"> => ({\n at,\n approximate: true,\n source: \"plc\",\n kind: \"trace\",\n trace,\n }),\n request: (request: RequestTrace): Entry<\"request\"> => ({\n at: request.startedAt,\n approximate: true,\n source: \"server\",\n kind: \"request\",\n request,\n }),\n deploy: (at: string, details: Details<\"deploy\">): Entry<\"deploy\"> => ({\n at,\n approximate: false,\n source: \"agent\",\n kind: \"deploy\",\n ...details,\n }),\n audit: (at: string, details: Details<\"audit\">): Entry<\"audit\"> => ({\n at,\n approximate: false,\n source: \"agent\",\n kind: \"audit\",\n ...details,\n }),\n connection: (at: string, state: ConnectionState, error?: string): Entry<\"connection\"> => ({\n at,\n approximate: false,\n source: \"debugger\",\n kind: \"connection\",\n state,\n ...(error && { error }),\n }),\n};\n\n/** Entries from every source in time order, keeping the newest `limit`. */\nexport const createTimeline = (limit = 10_000) => {\n const entries: TimelineEntry[] = [];\n return {\n add: (entry: TimelineEntry) => {\n // Sources arrive late and out of order, so insert after the last entry not later than it.\n let index = entries.length;\n while (index > 0 && entry.at < (entries[index - 1]?.at ?? entry.at)) index--;\n entries.splice(index, 0, entry);\n if (entries.length > limit) entries.splice(0, entries.length - limit);\n },\n /** Entries after `at`, or all of them. */\n since: (at?: string) => (at ? entries.filter((entry) => entry.at > at) : [...entries]),\n };\n};\n\nexport type Timeline = ReturnType<typeof createTimeline>;\n",
12
- "import type { TelemetryRecord } from \"@tsplc/server/telemetry\";\nimport type { TraceEvent } from \"./api.ts\";\nimport type { DebugJob, DebugManifest } from \"./manifest.ts\";\nimport type { Paths } from \"./paths.ts\";\n\nexport type TraceRecord = Extract<TelemetryRecord, { kind: \"trace\" }>;\n\n/**\n * Decodes the opt-in trace through the manifest's event sites (docs/design/debugging.md). Only\n * records of the manifest's own build may be decoded: another build's site ids mean other code.\n */\nexport const createTraceDecoder = (manifest: DebugManifest, paths: Paths) => {\n const sites = new Map(manifest.events.map((site) => [site.id, site]));\n const jobs = new Map(manifest.jobs.map((job) => [job.id, job]));\n const jobSites = new Map(\n manifest.events.flatMap(({ id, job: jobId, phase }) => {\n const job = jobId === undefined ? undefined : jobs.get(jobId);\n return job && phase ? [[id, { job, started: phase === \"started\" }] as const] : [];\n }),\n );\n\n return {\n decode: (record: TraceRecord, task: string, sequence: number): TraceEvent | undefined => {\n const site = sites.get(record.site);\n if (!site) return undefined;\n return {\n sequence,\n task,\n scan: record.scan,\n plcTime: record.time,\n site: site.id,\n value: paths.decode(site.type, record.value),\n operands: site.operands.map(({ text, path, stable, type }, index) => ({\n text,\n ...(path && { path }),\n stable,\n value: paths.decode(type, record.operands[index]),\n })),\n };\n },\n /** The job a record starts or finishes, if its site is a job's. */\n job: (record: TraceRecord): { job: DebugJob; started: boolean } | undefined =>\n jobSites.get(record.site),\n };\n};\n",
13
- "import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport { z } from \"zod\";\nimport type { WatchGroups } from \"./api.ts\";\n\nexport const watchGroupsSchema = z.strictObject({\n groups: z.record(z.string().min(1), z.array(z.string().min(1))),\n});\n\n/**\n * Watch groups: the config's `debug.watch`, then groups saved in `file`. Saving keeps only the\n * groups that differ from the config, so the config stays their source.\n */\nexport const loadWatchGroups = async (file: string, configured: Record<string, string[]>) => {\n let saved = existsSync(file)\n ? watchGroupsSchema.parse(JSON.parse(await readFile(file, \"utf8\"))).groups\n : {};\n const groups = (): WatchGroups => ({ groups: { ...configured, ...saved } });\n return {\n groups,\n save: async ({ groups: next }: WatchGroups) => {\n saved = Object.fromEntries(\n Object.entries(next).filter(([name, paths]) => !isDeepStrictEqual(configured[name], paths)),\n );\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, JSON.stringify({ groups: saved }, null, 2));\n return groups();\n },\n };\n};\n",
14
- "import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport type { Interest, Sample } from \"./api.ts\";\nimport { DebugError, type Debugger, type StreamMessage } from \"./debugger.ts\";\nimport { debugManifest } from \"./manifest.ts\";\nimport { loadUi } from \"./ui/index.ts\";\nimport { watchGroupsSchema } from \"./watch.ts\";\n\n/** Comments keep proxies and Bun's idle timeout from closing a quiet stream. */\nconst heartbeatMs = 5000;\nconst encoder = new TextEncoder();\n\nconst json = (body: unknown, status = 200) =>\n Response.json(body, { status, headers: { \"Cache-Control\": \"no-store\" } });\n\nconst list = (value: string | null) =>\n (value ?? \"\")\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n\nexport const loadManifest = async (file: string) =>\n debugManifest.parse(JSON.parse(await readFile(file, \"utf8\")));\n\n/** What a stream's page shows, from its query. */\nconst interest = (search: URLSearchParams): Interest => {\n const jobs = list(search.get(\"jobs\")).map(Number);\n if (!jobs.every(Number.isInteger)) throw new DebugError(\"jobs must be job ids\", 400);\n return {\n watch: list(search.get(\"watch\")),\n jobs,\n health: list(search.get(\"health\")),\n devices: list(search.get(\"devices\")),\n };\n};\n\n/** Every stream event, plus samples of the watched paths and states of the shown jobs and devices. */\nconst stream = (debug: Debugger, { watch, ...shown }: Interest) => {\n // Refuse a watch that matches too much before the stream starts.\n debug.paths.expand(watch);\n let stop = () => {};\n return new Response(\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n let open = true;\n const write = (text: string) => {\n if (open) controller.enqueue(encoder.encode(text));\n };\n const send = ({ event, data }: StreamMessage) =>\n write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n send({ event: \"session\", data: debug.session() });\n const latest = new Map<string, { sample: Sample; sentAt: number }>();\n const sendSample = (sample: Sample) => {\n latest.set(sample.path, { sample, sentAt: Date.now() });\n send({ event: \"sample\", data: sample });\n };\n const unsubscribe = debug.subscribe(send);\n const unwatch = debug.watch(watch, sendSample);\n const unshow = debug.show(shown);\n const heartbeat = setInterval(() => write(\": keepalive\\n\\n\"), heartbeatMs);\n // Over OPC UA, samples come only on change. While the session holds, an unchanged value\n // is still current, so it is sent again each interval; clients mark samples stale by their age.\n const { intervalMs } = debug.session().reading;\n const refresh = setInterval(() => {\n if (debug.session().connection.state !== \"connected\") return;\n const now = Date.now();\n for (const { sample, sentAt } of latest.values())\n if (now - sentAt >= intervalMs)\n sendSample({ ...sample, receivedAt: new Date(now).toISOString() });\n }, intervalMs);\n stop = () => {\n open = false;\n clearInterval(heartbeat);\n clearInterval(refresh);\n unsubscribe();\n unwatch();\n unshow();\n };\n },\n cancel: () => stop(),\n }),\n { headers: { \"Content-Type\": \"text/event-stream\", \"Cache-Control\": \"no-store\" } },\n );\n};\n\n/**\n * The debugger's routes (docs/design/debugging.md), with `route` the request's path below where\n * the host mounts them. There is no route that writes to the controller; hosts authenticate.\n */\nexport const createDebugHandler =\n (debug: Debugger, log: (message: string) => void) =>\n async (request: Request, route: string): Promise<Response> => {\n const { searchParams } = new URL(request.url);\n const key = `${request.method} ${route}`;\n try {\n switch (key) {\n case \"GET /\":\n return new Response((await loadUi()).html, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n case \"GET /ui.js\":\n return new Response((await loadUi()).script, {\n headers: { \"Content-Type\": \"text/javascript; charset=utf-8\" },\n });\n case \"GET /api/session\":\n return json(debug.session());\n case \"GET /api/manifest\":\n return json(debug.manifest);\n case \"GET /api/stream\":\n return stream(debug, interest(searchParams));\n case \"GET /api/values\":\n return json(await debug.values(list(searchParams.get(\"paths\"))));\n case \"GET /api/jobs\":\n return json(debug.jobs());\n case \"GET /api/hardware\":\n return json(debug.hardware());\n case \"GET /api/timeline\":\n return json(debug.timeline(searchParams.get(\"since\") ?? undefined));\n case \"GET /api/watch\":\n return json(debug.watchGroups());\n case \"PUT /api/watch\":\n return json(await debug.saveWatchGroups(watchGroupsSchema.parse(await request.json())));\n }\n return json({ error: `No route ${key}` }, 404);\n } catch (error) {\n if (error instanceof DebugError) return json({ error: error.message }, error.status);\n // RangeError: a watch matches too many values; SyntaxError: a body isn't JSON.\n if (error instanceof RangeError || error instanceof SyntaxError)\n return json({ error: error.message }, 400);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n log(`${key} failed: ${error instanceof Error ? error.stack : String(error)}`);\n return json({ error: \"The debugger failed; see its log\" }, 500);\n }\n };\n\n/**\n * Serves the debugger on 127.0.0.1 without a token. Requests that name another host are refused,\n * so no website can reach it by rebinding a domain name to 127.0.0.1.\n */\nexport const serveDebugger = (\n debug: Debugger,\n options: { port: number; log: (message: string) => void },\n) => {\n const handle = createDebugHandler(debug, options.log);\n return Bun.serve({\n hostname: \"127.0.0.1\",\n port: options.port,\n fetch: (request) => {\n const host = request.headers.get(\"host\")?.replace(/:\\d+$/, \"\");\n if (host !== \"127.0.0.1\" && host !== \"localhost\")\n return json({ error: \"Use http://127.0.0.1 or http://localhost\" }, 403);\n return handle(request, new URL(request.url).pathname);\n },\n });\n};\n",
15
- "import { z } from \"zod\";\n\n/**\n * What a build tells the debugger: every TypeScript identity it can show, and the target symbol each one reads.\n * TypeScript paths (`program.diverters.binTrackers[10].bin`) are the identity; `target` strings are opaque to\n * everything except the target's adapter (for CODESYS, IEC symbol paths such as `plc_Program.diverters…`).\n * Written by the compiler to `.tsplc/artifacts/st/debug.json` and shipped with each release.\n */\n\n/** A location in the project's own sources: `file` indexes `sources`; lines and columns are 1-based. */\nexport const sourceRange = z.object({\n file: z.number().int(),\n line: z.number().int(),\n column: z.number().int(),\n endLine: z.number().int(),\n endColumn: z.number().int(),\n});\n\nconst json: z.ZodType<unknown> = z.lazy(() =>\n z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.array(json),\n z.record(z.string(), json),\n ]),\n);\n\nexport const debugField = z.object({\n name: z.string(),\n target: z.string(),\n type: z.string(),\n declaration: sourceRange.optional(),\n /** Compiler-made storage, such as an async job's `step`; hidden unless asked for. */\n generated: z.literal(true).optional(),\n});\n\n/** Keys of `types` are opaque ids; scalars use their IEC name, such as `BOOL`. */\nexport const debugType = z.discriminatedUnion(\"kind\", [\n z.object({ kind: z.literal(\"scalar\"), iec: z.string() }),\n z.object({\n kind: z.literal(\"enum\"),\n name: z.string(),\n members: z.record(z.string(), z.number().int()),\n }),\n z.object({\n kind: z.literal(\"record\"),\n name: z.string(),\n declaration: sourceRange.optional(),\n fields: z.array(debugField),\n }),\n z.object({\n kind: z.literal(\"array\"),\n element: z.string(),\n length: z.number().int(),\n /** The first index; TypeScript paths use the target's own indexes, `lower` to `lower + length - 1`. */\n lower: z.number().int(),\n }),\n]);\n\nexport const debugRoot = z.object({\n path: z.string(),\n target: z.string(),\n type: z.string(),\n declaration: sourceRange.optional(),\n /** Readable at runtime through the target's adapter; for CODESYS, all stored state is. */\n readable: z.boolean(),\n generated: z.literal(true).optional(),\n});\n\n/** A field the compiler folded away: it has no runtime storage, but its value is known. */\nexport const debugConstant = z.object({\n path: z.string(),\n type: z.string(),\n value: json,\n declaration: sourceRange.optional(),\n});\n\nexport const debugIo = z.object({\n path: z.string(),\n target: z.string(),\n direction: z.enum([\"input\", \"output\"]),\n type: z.string(),\n device: z.string().optional(),\n channel: z.string().optional(),\n address: z.string().optional(),\n inverted: z.literal(true).optional(),\n shared: z.literal(true).optional(),\n});\n\nexport const debugChannel = z.object({\n id: z.string(),\n name: z.string(),\n direction: z.enum([\"input\", \"output\"]),\n type: z.string(),\n offsetBits: z.number().int(),\n bits: z.number().int(),\n address: z.string().optional(),\n unit: z.string().optional(),\n description: z.string().optional(),\n});\n\nexport const debugDevice = z.object({\n id: z.string(),\n product: z.string().optional(),\n vendor: z.string().optional(),\n productCode: z.string().optional(),\n network: z.object({ address: z.string(), rpiMs: z.number().optional() }).optional(),\n connection: z.string().optional(),\n assemblies: z.array(\n z.object({\n direction: z.enum([\"input\", \"output\"]),\n bytes: z.number().int(),\n address: z.string().optional(),\n /** A byte array over the whole assembly, mapped or not. */\n raw: z.string().optional(),\n }),\n ),\n /**\n * Target paths of the driver's own state, such as a generated adapter's `eState`; absent means\n * the device's health is unknown.\n */\n health: z\n .object({\n state: z.string().optional(),\n states: z.record(z.string(), z.number().int()).optional(),\n diagnostic: z.string().optional(),\n message: z.string().optional(),\n })\n .optional(),\n /** Status symbols by label: hand-configured ones, and a generated Modbus server's error. */\n status: z.record(z.string(), z.string()).optional(),\n channels: z.array(debugChannel),\n});\n\n/** A specialized function: one per method per instance, so `reads` resolve to concrete paths. */\nexport const debugFunction = z.object({\n id: z.number().int(),\n name: z.string(),\n declaration: sourceRange,\n /** The TypeScript path of `this`, for a method specialized to one instance. */\n instance: z.string().optional(),\n task: z.string().optional(),\n target: z.string(),\n /** Member reads in the body whose runtime path is static in this specialization. */\n reads: z.array(z.object({ range: sourceRange, path: z.string() })),\n});\n\nexport const debugJob = z.object({\n id: z.number().int(),\n name: z.string(),\n declaration: sourceRange,\n instance: z.string().optional(),\n /** The job's state, with fields `step`, `busy`, `done`, `error` and `cancelling`. */\n target: z.string(),\n steps: z.array(\n z.object({\n step: z.number().int(),\n kind: z.enum([\"await\", \"return\", \"throw\", \"statement\"]),\n range: sourceRange,\n text: z.string(),\n }),\n ),\n /**\n * The PLC clock in milliseconds when the job last started: the clock of telemetry records'\n * `time` and a batch's `now`.\n */\n startedAt: z.string().optional(),\n /**\n * Service calls the job awaits, its nested jobs' included; `sequence` is the request counter sent\n * as `x-tsplc-request`, with `job`'s id when a nested job makes the call.\n */\n requests: z.array(\n z.object({\n service: z.string(),\n target: z.string(),\n sequence: z.string(),\n job: z.number().int().optional(),\n }),\n ),\n /** Made by the compiler, such as a service call's own job; hidden unless asked for. */\n generated: z.literal(true).optional(),\n});\n\n/**\n * Where `debug.trace` records: an enum state field changing, a decision function returning a\n * different value, or a job starting or finishing. Trace records name their site by `id`.\n */\nexport const debugEventSite = z.object({\n id: z.number().int(),\n kind: z.enum([\"state\", \"decision\", \"job\"]),\n /** For `kind: \"job\"`: the job, and whether it starts or finishes at this site. */\n job: z.number().int().optional(),\n phase: z.enum([\"started\", \"finished\"]).optional(),\n /** The TypeScript path written, or of the job. */\n path: z.string(),\n function: z.number().int().optional(),\n type: z.string(),\n range: sourceRange,\n text: z.string(),\n task: z.string(),\n /**\n * Guard values captured in the same scan, at the write: each `if` condition leaf enclosing it.\n * `stable` is false when the body between the guard and the write can change the leaf.\n */\n operands: z.array(\n z.object({\n text: z.string(),\n range: sourceRange,\n type: z.string(),\n path: z.string().optional(),\n stable: z.boolean(),\n }),\n ),\n});\n\n/** The statement that last wrote each output, per scan. */\nexport const debugWriter = z.object({\n output: z.string(),\n target: z.string(),\n sites: z.array(\n z.object({ id: z.number().int(), range: sourceRange, function: z.number().int() }),\n ),\n});\n\nexport const debugTask = z.object({\n name: z.string(),\n intervalMs: z.number(),\n priority: z.number().int(),\n});\n\nexport const debugManifest = z.object({\n kind: z.literal(\"tsplc-debug\"),\n version: z.literal(1),\n build: z.object({\n id: z.string(),\n /** A variable holding `id`, to tell which build the controller runs. */\n target: z.string(),\n compiler: z.string(),\n }),\n /** Project-relative paths. */\n sources: z.array(z.string()),\n types: z.record(z.string(), debugType),\n roots: z.array(debugRoot),\n constants: z.array(debugConstant),\n io: z.array(debugIo),\n devices: z.array(debugDevice),\n functions: z.array(debugFunction),\n jobs: z.array(debugJob),\n events: z.array(debugEventSite),\n writers: z.array(debugWriter),\n tasks: z.array(debugTask),\n /** Job error codes by number: 1 cancelled, 2 timeout… */\n errors: z.record(z.string(), z.string()),\n});\n\nexport type SourceRange = z.infer<typeof sourceRange>;\nexport type DebugType = z.infer<typeof debugType>;\nexport type DebugField = z.infer<typeof debugField>;\nexport type DebugRoot = z.infer<typeof debugRoot>;\nexport type DebugConstant = z.infer<typeof debugConstant>;\nexport type DebugIo = z.infer<typeof debugIo>;\nexport type DebugDevice = z.infer<typeof debugDevice>;\nexport type DebugChannel = z.infer<typeof debugChannel>;\nexport type DebugFunction = z.infer<typeof debugFunction>;\nexport type DebugJob = z.infer<typeof debugJob>;\nexport type DebugEventSite = z.infer<typeof debugEventSite>;\nexport type DebugWriter = z.infer<typeof debugWriter>;\nexport type DebugTask = z.infer<typeof debugTask>;\nexport type DebugManifest = z.infer<typeof debugManifest>;\n",
16
- "import { createRequire } from \"node:module\";\nimport { dirname, resolve } from \"node:path\";\nimport { html } from \"./page.ts\";\n\nlet ui: Promise<{ html: string; script: string }> | undefined;\n\nconst build = async () => {\n const result = await Bun.build({\n entrypoints: [\n resolve(dirname(createRequire(import.meta.url).resolve(\"@tsplc/debug\")), \"../src/ui/main.ts\"),\n ],\n target: \"browser\",\n minify: true,\n });\n if (!result.success) throw new AggregateError(result.logs, \"Bundling the debugger UI failed\");\n return { html, script: await result.outputs[0]!.text() };\n};\n\n/** The browser UI: serve `html` at `GET /` and `script` at `GET /ui.js`. Bundled on first call, then cached. */\nexport const loadUi = () => (ui ??= build());\n",
5
+ "import { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { requestsReply } from \"@tsplc/server/requests\";\nimport { telemetryReply } from \"@tsplc/server/telemetry\";\nimport type { TargetAdapter, TargetRead, TargetSample } from \"./adapter.ts\";\nimport type {\n\tInterest,\n\tJobState,\n\tSample,\n\tSession,\n\tStreamEvents,\n\tTimelineEntry,\n\tWatchGroups,\n} from \"./api.ts\";\nimport { errorMessage } from \"./errors.ts\";\nimport { deviceReads, deviceState, healthReads } from \"./hardware.ts\";\nimport {\n\tbusyOf,\n\tbusyRead,\n\tdetailReads,\n\tjobState,\n\ttype TracedJob,\n} from \"./jobs.ts\";\nimport type { DebugDevice, DebugJob, DebugManifest } from \"./manifest.ts\";\nimport { createPaths } from \"./paths.ts\";\nimport { createRequestFollower } from \"./requests.ts\";\nimport { createTelemetryFollower, type ReceivedRecord } from \"./telemetry.ts\";\nimport { createTimeline, timelineEntries } from \"./timeline.ts\";\nimport { createTraceDecoder } from \"./trace.ts\";\nimport { loadWatchGroups } from \"./watch.ts\";\n\nexport interface DebuggerOptions {\n\tmanifest: DebugManifest;\n\t/** Owned by the debugger from here on: closing the debugger closes it. */\n\tadapter: TargetAdapter;\n\t/** Saved watch groups live here. */\n\tstateDirectory: string;\n\t/** `debug.watch` from the config. */\n\twatch: Record<string, string[]>;\n\t/** The app server, whose telemetry and request trace are pulled every second. */\n\tserver?: { url: string; token: string };\n\trelease?: Session[\"release\"];\n\t/** Entries from before the debugger started, such as the agent's deployments. */\n\ttimeline?: readonly TimelineEntry[];\n\tprojectRoot?: string;\n\tlog: (message: string) => void;\n}\n\n/** A request the API refuses, with its HTTP status. */\nexport class DebugError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly status: number,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\nexport type StreamMessage = {\n\t[Name in keyof StreamEvents]: { event: Name; data: StreamEvents[Name] };\n}[keyof StreamEvents];\n\nconst pullMs = 1000;\n/** Without telemetry, the build id is read through the controller this often. */\nconst buildCheckMs = 10_000;\n/** Device health, raw bytes and channels change rarely enough for this. */\nconst hardwareMs = 5000;\n/** Busy jobs whose details each poll reads; the rest show as busy only. */\nconst detailedJobs = 16;\n\n/** Counts how many streams show each key. */\nconst createShown = <Key>() => {\n\tconst counts = new Map<Key, number>();\n\treturn {\n\t\thas: (key: Key) => counts.has(key),\n\t\tadd: (keys: readonly Key[]) => {\n\t\t\tfor (const key of keys) {\n\t\t\t\tcounts.set(key, (counts.get(key) ?? 0) + 1);\n\t\t\t}\n\t\t\treturn () => {\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tconst count = counts.get(key)! - 1;\n\t\t\t\t\tif (count) {\n\t\t\t\t\t\tcounts.set(key, count);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcounts.delete(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t};\n};\n\n/**\n * The debugger for one build on one controller (docs/design/debugging.md). It reads what the\n * pages show through the adapter, follows the app server's telemetry and requests, and keeps the\n * recent window of both. Everything it offers is read-only.\n */\nexport const createDebugger = async (options: DebuggerOptions) => {\n\tconst { manifest, adapter } = options;\n\tconst paths = createPaths(manifest);\n\tconst trace = createTraceDecoder(manifest, paths);\n\tconst telemetry = createTelemetryFollower(manifest);\n\tconst requests = createRequestFollower();\n\tconst timeline = createTimeline();\n\tconst watchGroups = await loadWatchGroups(\n\t\tjoin(options.stateDirectory, \"watch.json\"),\n\t\toptions.watch,\n\t);\n\tconst listeners = new Set<(message: StreamMessage) => void>();\n\tconst controller = new AbortController();\n\tconst { signal } = controller;\n\tlet controllerBuild: string | null = null;\n\n\tconst emit = (message: StreamMessage) => {\n\t\tfor (const listener of listeners) {\n\t\t\tlistener(message);\n\t\t}\n\t};\n\tconst record = (entry: TimelineEntry) => {\n\t\ttimeline.add(entry);\n\t\temit({ event: \"timeline\", data: entry });\n\t};\n\tfor (const entry of options.timeline ?? []) {\n\t\ttimeline.add(entry);\n\t}\n\n\tconst session = (): Session => ({\n\t\tbuild: {\n\t\t\tmanifest: manifest.build.id,\n\t\t\tcontroller: controllerBuild,\n\t\t\tmatches: controllerBuild === manifest.build.id,\n\t\t},\n\t\tconnection: { ...adapter.connection(), endpoint: adapter.endpoint },\n\t\treading: { method: adapter.method, intervalMs: adapter.samplingMs },\n\t\ttasks: telemetry.tasks(),\n\t\tclock: telemetry.clock(),\n\t\t...(options.release && { release: options.release }),\n\t\t...(options.projectRoot && { projectRoot: options.projectRoot }),\n\t});\n\n\tconst setBuild = (build: string) => {\n\t\tif (build === controllerBuild) {\n\t\t\treturn;\n\t\t}\n\t\tcontrollerBuild = build;\n\t\temit({ event: \"session\", data: session() });\n\t};\n\n\t// --- Values by TypeScript path ---------------------------------------------------------------\n\n\tconst unavailable = (path: string, status: string): Sample => ({\n\t\tpath,\n\t\tvalue: null,\n\t\tquality: \"unavailable\",\n\t\tstatus,\n\t\treceivedAt: new Date().toISOString(),\n\t});\n\n\t/** A path's target, or the sample it has without reading the controller. */\n\tconst locate = (path: string): { target: string; type: string } | Sample => {\n\t\tconst resolved = paths.resolve(path);\n\t\tif (!resolved) {\n\t\t\treturn unavailable(path, \"Unknown path\");\n\t\t}\n\t\tif (resolved.kind === \"constant\") {\n\t\t\treturn {\n\t\t\t\tpath,\n\t\t\t\tvalue: resolved.value,\n\t\t\t\tquality: \"good\",\n\t\t\t\tstatus: \"Constant\",\n\t\t\t\treceivedAt: new Date().toISOString(),\n\t\t\t};\n\t\t}\n\t\tif (!resolved.readable) {\n\t\t\treturn unavailable(path, \"Not readable\");\n\t\t}\n\t\treturn resolved;\n\t};\n\n\tconst targetRead = ({\n\t\ttarget,\n\t\ttype,\n\t}: {\n\t\ttarget: string;\n\t\ttype: string;\n\t}): TargetRead => ({\n\t\ttarget,\n\t\ttype: paths.typeOf(type),\n\t});\n\n\tconst sampleOf = (\n\t\tpath: string,\n\t\ttype: string,\n\t\tsample: TargetSample,\n\t): Sample => ({\n\t\tpath,\n\t\t...sample,\n\t\tvalue: paths.decode(type, sample.value),\n\t});\n\n\t/** Reads the leaves `patterns` match each sampling interval, until the returned function is called. */\n\tconst watch = (\n\t\tpatterns: readonly string[],\n\t\tlistener: (sample: Sample) => void,\n\t) => {\n\t\tconst watched = new Map<string, { path: string; type: string }[]>();\n\t\tconst reads: TargetRead[] = [];\n\t\tfor (const path of paths.expand(patterns)) {\n\t\t\tconst located = locate(path);\n\t\t\tif (!(\"target\" in located)) {\n\t\t\t\tlistener(located);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!watched.has(located.target)) {\n\t\t\t\treads.push(targetRead(located));\n\t\t\t}\n\t\t\twatched.set(located.target, [\n\t\t\t\t...(watched.get(located.target) ?? []),\n\t\t\t\t{ path, ...located },\n\t\t\t]);\n\t\t}\n\t\tif (!reads.length) {\n\t\t\treturn () => {};\n\t\t}\n\t\treturn adapter.subscribe(reads, (target, received) => {\n\t\t\tfor (const { path, type } of watched.get(target) ?? []) {\n\t\t\t\tlistener(sampleOf(path, type, received));\n\t\t\t}\n\t\t});\n\t};\n\n\tconst values = async (patterns: readonly string[]) => {\n\t\tconst connection = adapter.connection();\n\t\tif (connection.state !== \"connected\") {\n\t\t\tthrow new DebugError(\n\t\t\t\tconnection.error ?? \"The controller is not connected\",\n\t\t\t\t503,\n\t\t\t);\n\t\t}\n\t\tconst located = paths\n\t\t\t.expand(patterns)\n\t\t\t.map((path) => ({ path, located: locate(path) }));\n\t\tconst read = await adapter.read(\n\t\t\tlocated.flatMap(({ located }) =>\n\t\t\t\t\"target\" in located ? [targetRead(located)] : [],\n\t\t\t),\n\t\t);\n\t\treturn located.map(({ path, located }) => {\n\t\t\tif (!(\"target\" in located)) {\n\t\t\t\treturn located;\n\t\t\t}\n\t\t\tconst sample = read.get(located.target);\n\t\t\treturn sample\n\t\t\t\t? sampleOf(path, located.type, sample)\n\t\t\t\t: unavailable(path, \"Not read\");\n\t\t});\n\t};\n\n\tconst stopBuild = adapter.subscribe(\n\t\t[\n\t\t\t{\n\t\t\t\ttarget: manifest.build.target,\n\t\t\t\ttype: { kind: \"scalar\", iec: \"STRING\" },\n\t\t\t},\n\t\t],\n\t\t(_, sample) => {\n\t\t\tif (sample.quality === \"good\" && typeof sample.value === \"string\") {\n\t\t\t\tsetBuild(sample.value);\n\t\t\t}\n\t\t},\n\t\tbuildCheckMs,\n\t);\n\n\t// --- Jobs and devices, read only while shown -------------------------------------------------\n\n\tconst latest = new Map<string, TargetSample>();\n\tconst traced = new Map<number, TracedJob>();\n\tconst failures = new Map<number, NonNullable<JobState[\"failure\"]>>();\n\tlet unread = new Set<number>();\n\tconst shownJobs = createShown<number>();\n\tconst shownHealth = createShown<string>();\n\tconst shownDevices = createShown<string>();\n\t/** The JSON of what each stream last got, so unchanged states aren't sent again. */\n\tconst sent = new Map<string, string>();\n\n\tconst jobOf = (job: DebugJob) =>\n\t\tjobState(job, {\n\t\t\tvalue: (target) => latest.get(target),\n\t\t\ttraced: traced.get(job.id),\n\t\t\tfailure: failures.get(job.id),\n\t\t\tunread: unread.has(job.id),\n\t\t\tclock: telemetry.clock(),\n\t\t\tnow: Date.now(),\n\t\t\trequest: requests.call,\n\t\t});\n\tconst deviceOf = (device: DebugDevice) =>\n\t\tdeviceState(device, manifest.io, (target) => latest.get(target));\n\tconst send = (key: string, message: StreamMessage) => {\n\t\tconst json = JSON.stringify(message.data);\n\t\tif (sent.get(key) === json) {\n\t\t\treturn;\n\t\t}\n\t\tsent.set(key, json);\n\t\temit(message);\n\t};\n\tconst updateJob = (job: DebugJob) =>\n\t\tsend(`job:${job.id}`, { event: \"job\", data: jobOf(job) });\n\tconst updateDevice = (device: DebugDevice) =>\n\t\tsend(`device:${device.id}`, { event: \"device\", data: deviceOf(device) });\n\n\t/** Re-subscribes `reads` when they change, telling `update` which owners each sample is for. */\n\tconst reader = <Owner>(\n\t\tintervalMs: number,\n\t\tupdate: (owner: Owner) => void,\n\t) => {\n\t\tlet current = { key: \"\", stop: () => {} };\n\t\treturn (reads: { owner: Owner; read: TargetRead }[]) => {\n\t\t\tconst key = reads.map(({ read }) => read.target).join(\"\\n\");\n\t\t\tif (key === current.key) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcurrent.stop();\n\t\t\tconst owners = new Map<string, Owner[]>();\n\t\t\tfor (const { owner, read } of reads) {\n\t\t\t\towners.set(read.target, [...(owners.get(read.target) ?? []), owner]);\n\t\t\t}\n\t\t\tcurrent = {\n\t\t\t\tkey,\n\t\t\t\tstop: reads.length\n\t\t\t\t\t? adapter.subscribe(\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t...new Map(\n\t\t\t\t\t\t\t\t\treads.map(({ read }) => [read.target, read]),\n\t\t\t\t\t\t\t\t).values(),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t(target, sample) => {\n\t\t\t\t\t\t\t\tlatest.set(target, sample);\n\t\t\t\t\t\t\t\tfor (const owner of owners.get(target) ?? []) {\n\t\t\t\t\t\t\t\t\tupdate(owner);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tschedule();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tintervalMs,\n\t\t\t\t\t\t)\n\t\t\t\t\t: () => {},\n\t\t\t};\n\t\t};\n\t};\n\tconst readJobs = reader<DebugJob>(adapter.samplingMs, updateJob);\n\tconst readDevices = reader<DebugDevice>(hardwareMs, updateDevice);\n\n\t/** Everything of a device whose page is shown, else its health while a list shows it. */\n\tconst shownDeviceReads = (device: DebugDevice) => {\n\t\tif (shownDevices.has(device.id)) {\n\t\t\treturn deviceReads(device, manifest.io, paths.typeOf);\n\t\t}\n\t\tif (shownHealth.has(device.id)) {\n\t\t\treturn healthReads(device);\n\t\t}\n\t\treturn [];\n\t};\n\n\t/** Reads `busy` of the shown jobs, and the details of the busy ones. */\n\tconst plan = () => {\n\t\tconst shown = manifest.jobs.filter((job) => shownJobs.has(job.id));\n\t\tconst busy = shown.filter((job) =>\n\t\t\tbusyOf(job, (target) => latest.get(target), traced.get(job.id)),\n\t\t);\n\t\tunread = new Set(busy.slice(detailedJobs).map(({ id }) => id));\n\t\treadJobs([\n\t\t\t...shown.map((job) => ({ owner: job, read: busyRead(job) })),\n\t\t\t...busy\n\t\t\t\t.slice(0, detailedJobs)\n\t\t\t\t.flatMap((job) =>\n\t\t\t\t\tdetailReads(job).map((read) => ({ owner: job, read })),\n\t\t\t\t),\n\t\t]);\n\t\treadDevices(\n\t\t\tmanifest.devices.flatMap((device) =>\n\t\t\t\tshownDeviceReads(device).map((read) => ({ owner: device, read })),\n\t\t\t),\n\t\t);\n\t};\n\tlet planned = false;\n\tconst schedule = () => {\n\t\tif (planned) {\n\t\t\treturn;\n\t\t}\n\t\tplanned = true;\n\t\tqueueMicrotask(() => {\n\t\t\tplanned = false;\n\t\t\tplan();\n\t\t});\n\t};\n\n\t/** Reads what `interest` shows until the returned function is called. */\n\tconst show = (interest: Omit<Interest, \"watch\">) => {\n\t\tconst stops = [\n\t\t\tshownJobs.add(interest.jobs),\n\t\t\tshownHealth.add(interest.health),\n\t\t\tshownDevices.add(interest.devices),\n\t\t];\n\t\tschedule();\n\t\treturn () => {\n\t\t\tfor (const stop of stops) {\n\t\t\t\tstop();\n\t\t\t}\n\t\t\tschedule();\n\t\t};\n\t};\n\n\t// --- The app server ---------------------------------------------------------------------------\n\n\tconst receive = ({\n\t\tbuild,\n\t\ttask,\n\t\tsequence,\n\t\tat,\n\t\trecord: received,\n\t}: ReceivedRecord) => {\n\t\tif (received.kind === \"trace\") {\n\t\t\t// Event sites of another build would decode to the wrong source.\n\t\t\tif (build !== manifest.build.id) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst event = trace.decode(received, task, sequence);\n\t\t\tif (event) {\n\t\t\t\trecord(timelineEntries.trace(at, event));\n\t\t\t}\n\t\t\tconst site = trace.job(received);\n\t\t\tif (!site) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst startedAt = site.started ? at : traced.get(site.job.id)?.startedAt;\n\t\t\ttraced.set(site.job.id, {\n\t\t\t\tbusy: site.started,\n\t\t\t\t...(startedAt && { startedAt }),\n\t\t\t});\n\t\t\tupdateJob(site.job);\n\t\t\tschedule();\n\t\t\treturn;\n\t\t}\n\t\trecord(timelineEntries.app(at, task, sequence, received));\n\t\tif (received.kind !== \"exception\" || received.handled) {\n\t\t\treturn;\n\t\t}\n\t\tconst job = manifest.jobs.find(\n\t\t\t({ name, instance }) =>\n\t\t\t\tname === received.function && instance === received.instance,\n\t\t);\n\t\tif (!job) {\n\t\t\treturn;\n\t\t}\n\t\tfailures.set(job.id, {\n\t\t\tat,\n\t\t\tcode: received.code,\n\t\t\t...(received.name && { name: received.name }),\n\t\t\tsource: received.source,\n\t\t});\n\t\tupdateJob(job);\n\t};\n\n\tconst pull = async (url: URL, token: string) => {\n\t\tconst response = await fetch(url, {\n\t\t\theaders: { authorization: `Bearer ${token}` },\n\t\t\tsignal,\n\t\t});\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`The server answered ${response.status}`);\n\t\t}\n\t\treturn response.json();\n\t};\n\n\tconst pullTelemetry = async ({\n\t\turl,\n\t\ttoken,\n\t}: {\n\t\turl: string;\n\t\ttoken: string;\n\t}) => {\n\t\tconst reply = telemetryReply.parse(\n\t\t\tawait pull(\n\t\t\t\tnew URL(`/tsplc/telemetry?since=${telemetry.since()}`, url),\n\t\t\t\ttoken,\n\t\t\t),\n\t\t);\n\t\tconst received = telemetry.accept(reply);\n\t\tfor (const item of received) {\n\t\t\treceive(item);\n\t\t}\n\t\tconst build = telemetry.build();\n\t\tif (build) {\n\t\t\tsetBuild(build);\n\t\t}\n\t\t// Scan rates and the clock estimate change with every batch.\n\t\tif (reply.batches.length) {\n\t\t\temit({ event: \"session\", data: session() });\n\t\t}\n\t};\n\n\tconst pullRequests = async ({\n\t\turl,\n\t\ttoken,\n\t}: {\n\t\turl: string;\n\t\ttoken: string;\n\t}) => {\n\t\tconst reply = requestsReply.parse(\n\t\t\tawait pull(\n\t\t\t\tnew URL(`/tsplc/debug/requests?since=${requests.since()}`, url),\n\t\t\t\ttoken,\n\t\t\t),\n\t\t);\n\t\trequests.accept(reply, ({ request, entry, added }) => {\n\t\t\tif (added) {\n\t\t\t\ttimeline.add(entry);\n\t\t\t}\n\t\t\temit({ event: \"request\", data: request });\n\t\t\temit({ event: \"timeline\", data: entry });\n\t\t\tif (request.job === undefined || request.sequence === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst job = manifest.jobs.find(({ id }) => id === request.job);\n\t\t\tif (job) {\n\t\t\t\tupdateJob(job);\n\t\t\t}\n\t\t});\n\t};\n\n\t// --- Background work -------------------------------------------------------------------------\n\n\tconst stopConnection = adapter.onConnection((connection) => {\n\t\trecord(\n\t\t\ttimelineEntries.connection(\n\t\t\t\tconnection.since,\n\t\t\t\tconnection.state,\n\t\t\t\tconnection.error,\n\t\t\t),\n\t\t);\n\t\temit({ event: \"session\", data: session() });\n\t\tif (connection.state !== \"connected\") {\n\t\t\tfor (const [target, sample] of latest) {\n\t\t\t\tlatest.set(target, {\n\t\t\t\t\t...sample,\n\t\t\t\t\tquality: \"unavailable\",\n\t\t\t\t\tstatus: connection.error ?? \"The controller is not connected\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tfor (const job of manifest.jobs) {\n\t\t\t\tupdateJob(job);\n\t\t\t}\n\t\t\tfor (const device of manifest.devices) {\n\t\t\t\tupdateDevice(device);\n\t\t\t}\n\t\t}\n\t});\n\n\tconst repeat = async (\n\t\tname: string,\n\t\tintervalMs: number,\n\t\twork: () => Promise<void>,\n\t) => {\n\t\tlet failure: string | undefined;\n\t\twhile (!signal.aborted) {\n\t\t\ttry {\n\t\t\t\tawait work();\n\t\t\t\tfailure = undefined;\n\t\t\t} catch (error) {\n\t\t\t\tif (signal.aborted) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst message = errorMessage(error);\n\t\t\t\tif (message !== failure) {\n\t\t\t\t\toptions.log(`${name} failed: ${message}`);\n\t\t\t\t}\n\t\t\t\tfailure = message;\n\t\t\t}\n\t\t\tawait delay(intervalMs, undefined, { signal }).catch(() => undefined);\n\t\t}\n\t};\n\n\tconst { server } = options;\n\tconst running = server\n\t\t? [\n\t\t\t\trepeat(\"Reading the server's telemetry\", pullMs, () =>\n\t\t\t\t\tpullTelemetry(server),\n\t\t\t\t),\n\t\t\t\trepeat(\"Reading the server's requests\", pullMs, () =>\n\t\t\t\t\tpullRequests(server),\n\t\t\t\t),\n\t\t\t]\n\t\t: [];\n\n\treturn {\n\t\tmanifest,\n\t\tpaths,\n\t\tsession,\n\t\tvalues,\n\t\tjobs: () => manifest.jobs.map(jobOf),\n\t\thardware: () => manifest.devices.map(deviceOf),\n\t\ttimeline: (since?: string) => timeline.since(since),\n\t\twatchGroups: () => watchGroups.groups(),\n\t\tsaveWatchGroups: (groups: WatchGroups) => watchGroups.save(groups),\n\t\t/** Adds an entry from another source, such as the agent's audit log. */\n\t\trecord,\n\t\twatch,\n\t\tshow,\n\t\t/** Calls `listener` with every other stream event until the returned function is called. */\n\t\tsubscribe: (listener: (message: StreamMessage) => void) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => listeners.delete(listener);\n\t\t},\n\t\tclose: async () => {\n\t\t\tcontroller.abort();\n\t\t\tstopBuild();\n\t\t\treadJobs([]);\n\t\t\treadDevices([]);\n\t\t\tstopConnection();\n\t\t\tawait Promise.all(running);\n\t\t\tawait adapter.close();\n\t\t},\n\t};\n};\n\nexport type Debugger = Awaited<ReturnType<typeof createDebugger>>;\n",
6
+ "/** What to show for a caught value: an error's message, or anything else as text. */\nexport const errorMessage = (error: unknown) =>\n\terror instanceof Error ? error.message : String(error);\n",
7
+ "import type { ConnectionState, Quality } from \"./api.ts\";\nimport type { DebugType } from \"./manifest.ts\";\n\n/** One target's value, before the debugger names it by TypeScript path and decodes it. */\nexport interface TargetSample {\n\tvalue: unknown;\n\tquality: Quality;\n\tstatus: string;\n\treceivedAt: string;\n}\n\n/** A target to read, with its type in the manifest, which an adapter may need to parse it. */\nexport interface TargetRead {\n\ttarget: string;\n\ttype: DebugType;\n}\n\nconst qualityRank: Record<Quality, number> = {\n\tgood: 0,\n\tuncertain: 1,\n\tbad: 2,\n\tunavailable: 3,\n};\n\n/** The worst of these qualities; nothing read is unavailable. */\nexport const worstQuality = (\n\tsamples: readonly (TargetSample | undefined)[],\n): Quality =>\n\tsamples.reduce<Quality>((worst, sample) => {\n\t\tconst quality = sample?.quality ?? \"unavailable\";\n\t\treturn qualityRank[quality] > qualityRank[worst] ? quality : worst;\n\t}, \"good\");\n\nexport interface Connection {\n\tstate: ConnectionState;\n\tsince: string;\n\terror?: string;\n}\n\n/**\n * Reads one vendor's controller. Only the adapter interprets `target` strings, which come from\n * the manifest (for CODESYS, IEC symbol paths). It never writes.\n */\nexport interface TargetAdapter {\n\t/** How it reads, for display, such as \"engineering login\". */\n\treadonly method: string;\n\t/** Where it reads, for display. */\n\treadonly endpoint: string;\n\t/** How often subscribed targets are read; a value is at most about this old while connected. */\n\treadonly samplingMs: number;\n\tconnection(): Connection;\n\tonConnection(listener: (connection: Connection) => void): () => void;\n\t/** Reads targets now; fails while disconnected. Targets that can't be read come back bad or unavailable. */\n\tread(targets: readonly TargetRead[]): Promise<Map<string, TargetSample>>;\n\t/**\n\t * Calls `listener` with each target's value, about every `intervalMs` (`samplingMs` by\n\t * default) or on every change, across reconnects, until the returned function is called. While\n\t * disconnected each target is reported unavailable or bad.\n\t */\n\tsubscribe(\n\t\ttargets: readonly TargetRead[],\n\t\tlistener: (target: string, sample: TargetSample) => void,\n\t\tintervalMs?: number,\n\t): () => void;\n\tclose(): Promise<void>;\n}\n",
8
+ "import { type TargetRead, type TargetSample, worstQuality } from \"./adapter.ts\";\nimport type { DeviceState, Quality } from \"./api.ts\";\nimport type { DebugDevice, DebugIo, DebugType } from \"./manifest.ts\";\n\n/** Driver state names that mean the connection isn't working. */\nconst faultyState = /error|fault|fail|timeout|lost|closed/i;\n\n/** Hand-configured status symbols have no type in the manifest; they show as read. */\nconst untyped: DebugType = { kind: \"scalar\", iec: \"ANY\" };\n\n/** What a device's health is read from: the driver's own state, when the build names it. */\nexport const healthReads = (device: DebugDevice): TargetRead[] => {\n\tconst { state, states, diagnostic, message } = device.health ?? {};\n\treturn [\n\t\t...(state\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: state,\n\t\t\t\t\t\ttype: states\n\t\t\t\t\t\t\t? { kind: \"enum\" as const, name: \"state\", members: states }\n\t\t\t\t\t\t\t: { kind: \"scalar\" as const, iec: \"DINT\" },\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: []),\n\t\t...(diagnostic\n\t\t\t? [{ target: diagnostic, type: { kind: \"scalar\" as const, iec: \"BOOL\" } }]\n\t\t\t: []),\n\t\t...(message\n\t\t\t? [{ target: message, type: { kind: \"scalar\" as const, iec: \"STRING\" } }]\n\t\t\t: []),\n\t];\n};\n\n/** Everything a device's page shows: its health, raw assembly bytes, bound channels and status symbols. */\nexport const deviceReads = (\n\tdevice: DebugDevice,\n\tio: readonly DebugIo[],\n\ttypeOf: (id: string) => DebugType,\n): TargetRead[] => [\n\t...healthReads(device),\n\t...device.assemblies.flatMap(({ raw, bytes }) =>\n\t\traw\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: raw,\n\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\tkind: \"array\" as const,\n\t\t\t\t\t\t\telement: \"BYTE\",\n\t\t\t\t\t\t\tlength: bytes,\n\t\t\t\t\t\t\tlower: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: [],\n\t),\n\t...io\n\t\t.filter((binding) => binding.device === device.id)\n\t\t.map(({ target, type }) => ({ target, type: typeOf(type) })),\n\t...Object.values(device.status ?? {}).map((target) => ({\n\t\ttarget,\n\t\ttype: untyped,\n\t})),\n];\n\n/** A reading that is no longer good says nothing current, fault or not. */\nconst healthState = (quality: Quality, faulted: boolean) => {\n\tif (quality !== \"good\") {\n\t\treturn \"stale\";\n\t}\n\treturn faulted ? \"fault\" : \"ok\";\n};\n\nconst health = (\n\tdevice: DebugDevice,\n\tvalue: (target: string) => TargetSample | undefined,\n): DeviceState[\"health\"] => {\n\tconst { state, states, diagnostic, message } = device.health ?? {};\n\tif (!state && !diagnostic) {\n\t\treturn { state: \"unknown\", quality: \"unavailable\" };\n\t}\n\tconst stateSample = state ? value(state) : undefined;\n\tconst diagnosticSample = diagnostic ? value(diagnostic) : undefined;\n\tconst messageSample = message ? value(message) : undefined;\n\tconst quality = worstQuality([\n\t\t...(state ? [stateSample] : []),\n\t\t...(diagnostic ? [diagnosticSample] : []),\n\t]);\n\tconst number =\n\t\ttypeof stateSample?.value === \"number\" ? stateSample.value : undefined;\n\t// The login names enum members the manifest may not list.\n\tconst name =\n\t\tObject.entries(states ?? {}).find(([, member]) => member === number)?.[0] ??\n\t\t(typeof stateSample?.value === \"string\" ? stateSample.value : undefined);\n\tconst faulted =\n\t\tdiagnosticSample?.value === true ||\n\t\t(name !== undefined && faultyState.test(name));\n\treturn {\n\t\tstate: healthState(quality, faulted),\n\t\t...(number !== undefined && { value: number }),\n\t\t...(name && { name }),\n\t\t...(typeof diagnosticSample?.value === \"boolean\" && {\n\t\t\tdiagnostic: diagnosticSample.value,\n\t\t}),\n\t\t...(typeof messageSample?.value === \"string\" && {\n\t\t\tmessage: messageSample.value,\n\t\t}),\n\t\tquality,\n\t};\n};\n\n/**\n * A device's driver health, raw assembly bytes, bound channel values and status symbols. Health\n * is \"unknown\" unless the manifest names the driver's own state.\n */\nexport const deviceState = (\n\tdevice: DebugDevice,\n\tio: readonly DebugIo[],\n\tvalue: (target: string) => TargetSample | undefined,\n): DeviceState => ({\n\tid: device.id,\n\thealth: health(device, value),\n\tassemblies: device.assemblies.map(({ direction, address, raw }) => {\n\t\tconst sample = raw ? value(raw) : undefined;\n\t\treturn {\n\t\t\tdirection,\n\t\t\t...(address && { address }),\n\t\t\tbytes:\n\t\t\t\tArray.isArray(sample?.value) &&\n\t\t\t\tsample.value.every((byte): byte is number => typeof byte === \"number\")\n\t\t\t\t\t? sample.value\n\t\t\t\t\t: null,\n\t\t\tquality: sample?.quality ?? \"unavailable\",\n\t\t};\n\t}),\n\tchannels: io.flatMap((binding) =>\n\t\tbinding.device === device.id && binding.channel\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: binding.channel,\n\t\t\t\t\t\tpath: binding.path,\n\t\t\t\t\t\tvalue: value(binding.target)?.value ?? null,\n\t\t\t\t\t\tquality: value(binding.target)?.quality ?? \"unavailable\",\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: [],\n\t),\n\tstatus: Object.fromEntries(\n\t\tObject.entries(device.status ?? {}).map(([label, target]) => [\n\t\t\tlabel,\n\t\t\t{\n\t\t\t\tvalue: value(target)?.value ?? null,\n\t\t\t\tquality: value(target)?.quality ?? \"unavailable\",\n\t\t\t},\n\t\t]),\n\t),\n});\n",
9
+ "import type { TargetRead, TargetSample } from \"./adapter.ts\";\nimport type { JobState, RequestTrace, Session } from \"./api.ts\";\nimport type { DebugJob, DebugType } from \"./manifest.ts\";\n\nconst scalar = (iec: string): DebugType => ({ kind: \"scalar\", iec });\n\n/** What the trace said of a job: whether it is running, and when it last started. */\nexport interface TracedJob {\n\tbusy: boolean;\n\tstartedAt?: string;\n}\n\n/** The job's `busy` flag, read while a page shows the job and the trace says nothing of it. */\nexport const busyRead = (job: DebugJob): TargetRead => ({\n\ttarget: `${job.target}.busy`,\n\ttype: scalar(\"BOOL\"),\n});\n\n/** What a busy job shows: where it waits, since when, and its latest request. */\nexport const detailReads = (job: DebugJob): TargetRead[] => [\n\t{ target: `${job.target}.step`, type: scalar(\"UINT\") },\n\t{ target: `${job.target}.cancelling`, type: scalar(\"BOOL\") },\n\t...(job.startedAt ? [{ target: job.startedAt, type: scalar(\"UDINT\") }] : []),\n\t...job.requests.map(({ sequence }) => ({\n\t\ttarget: sequence,\n\t\ttype: scalar(\"UDINT\"),\n\t})),\n];\n\n/**\n * From the last read, else from the trace; null when neither knows. A read wins: a job's caller\n * stops running it once it finishes, so the trace can miss the finish.\n */\nexport const busyOf = (\n\tjob: DebugJob,\n\tvalue: (target: string) => TargetSample | undefined,\n\ttraced: TracedJob | undefined,\n) => {\n\tconst read = value(busyRead(job).target);\n\treturn read?.quality === \"good\"\n\t\t? read.value === true\n\t\t: (traced?.busy ?? null);\n};\n\nconst numberOf = (sample: TargetSample | undefined) =>\n\tsample?.quality === \"good\" && typeof sample.value === \"number\"\n\t\t? sample.value\n\t\t: undefined;\n\n/**\n * A job as the debugger shows it at host time `now`. Details are shown only while it is busy;\n * its last start stays, so a later run tells a failure apart from the current state. Without a\n * clock estimate there is no start time from the PLC's own `startedAt`.\n */\nexport const jobState = (\n\tjob: DebugJob,\n\tinputs: {\n\t\tvalue: (target: string) => TargetSample | undefined;\n\t\ttraced: TracedJob | undefined;\n\t\tfailure: JobState[\"failure\"];\n\t\t/** Busy, but its details aren't read for want of room in the poll. */\n\t\tunread: boolean;\n\t\tclock: Session[\"clock\"];\n\t\tnow: number;\n\t\t/** The server's trace of a call, which the PLC tags with its job and the call site's count. */\n\t\trequest: (call: {\n\t\t\tjob: number;\n\t\t\tservice: string;\n\t\t\tsequence: number;\n\t\t}) => RequestTrace | undefined;\n\t},\n): JobState => {\n\tconst { value, traced, clock, now } = inputs;\n\tconst busy = busyOf(job, value, traced);\n\tconst startedPlc =\n\t\tjob.startedAt === undefined ? undefined : numberOf(value(job.startedAt));\n\tconst startedAt =\n\t\ttraced?.startedAt ??\n\t\t(clock && startedPlc !== undefined\n\t\t\t? new Date(startedPlc - clock.offsetMs).toISOString()\n\t\t\t: undefined);\n\tconst base: JobState = {\n\t\tid: job.id,\n\t\tquality:\n\t\t\tvalue(busyRead(job).target)?.quality ?? (traced ? \"good\" : \"unavailable\"),\n\t\tbusy,\n\t\t...(startedAt && { startedAt }),\n\t\t...(inputs.failure && { failure: inputs.failure }),\n\t};\n\tif (!busy) {\n\t\treturn base;\n\t}\n\tif (inputs.unread) {\n\t\treturn { ...base, unread: true };\n\t}\n\n\tconst step = numberOf(value(`${job.target}.step`));\n\tconst current = job.steps.find((candidate) => candidate.step === step);\n\t// Each call site counts its own requests, so the latest is the one the server saw start last,\n\t// or the one counted furthest while the server has yet to report them.\n\tconst calls = job.requests\n\t\t.map((call) => {\n\t\t\tconst sequence = numberOf(value(call.sequence)) ?? 0;\n\t\t\tconst trace = inputs.request({\n\t\t\t\tjob: call.job ?? job.id,\n\t\t\t\tservice: call.service,\n\t\t\t\tsequence,\n\t\t\t});\n\t\t\treturn { service: call.service, sequence, trace };\n\t\t})\n\t\t.filter(({ sequence }) => sequence > 0);\n\tconst later = (call: (typeof calls)[number], than: (typeof calls)[number]) =>\n\t\tcall.trace && than.trace\n\t\t\t? call.trace.startedAt > than.trace.startedAt\n\t\t\t: call.sequence > than.sequence;\n\tconst latest = calls.reduce<(typeof calls)[number] | undefined>(\n\t\t(latest, call) => (latest && !later(call, latest) ? latest : call),\n\t\tundefined,\n\t);\n\tconst cancelling = value(`${job.target}.cancelling`);\n\n\treturn {\n\t\t...base,\n\t\t...(cancelling?.quality === \"good\" && {\n\t\t\tcancelling: cancelling.value === true,\n\t\t}),\n\t\t...(step !== undefined && { step }),\n\t\t...(current && {\n\t\t\tcurrent: { kind: current.kind, range: current.range, text: current.text },\n\t\t}),\n\t\t...(startedAt && { elapsedMs: Math.max(0, now - Date.parse(startedAt)) }),\n\t\t...(latest && {\n\t\t\trequest: {\n\t\t\t\tservice: latest.service,\n\t\t\t\tsequence: latest.sequence,\n\t\t\t\t...(latest.trace && { trace: latest.trace }),\n\t\t\t},\n\t\t}),\n\t};\n};\n",
10
+ "import { isArrayIndexSegment, symbolPathSegments } from \"@tsplc/opcua/contract\";\nimport type { DebugManifest, DebugType, SourceRange } from \"./manifest.ts\";\n\n/**\n * TypeScript paths over a manifest: `program.diverters.binTrackers[10].bin` names a root\n * (`program.diverters`), then record fields and array indexes. Pure, so the browser UI can use it.\n */\n\n/** A path that reads a target, or a constant the compiler folded. */\nexport type ResolvedPath =\n\t| {\n\t\t\tkind: \"target\";\n\t\t\tpath: string;\n\t\t\ttarget: string;\n\t\t\ttype: string;\n\t\t\treadable: boolean;\n\t\t\tgenerated?: true;\n\t\t\tdeclaration?: SourceRange;\n\t }\n\t| {\n\t\t\tkind: \"constant\";\n\t\t\tpath: string;\n\t\t\ttype: string;\n\t\t\tvalue: unknown;\n\t\t\tdeclaration?: SourceRange;\n\t };\n\n/** Roots or constants that share a prefix, such as `program` above `program.diverters`. */\ninterface GroupPath {\n\tkind: \"group\";\n\tpath: string;\n}\n\n/** A child in the instance tree. */\nexport type PathNode = { name: string } & (ResolvedPath | GroupPath);\n\n/** In a pattern, every index of an array. */\nconst anyIndex = \"[*]\";\n\n/** Names and indexes as the controller's symbol paths split them, and `[*]` in patterns. */\nexport const pathSegments = (path: string) =>\n\tpath\n\t\t.split(anyIndex)\n\t\t.flatMap((part, index) => [\n\t\t\t...(index > 0 ? [anyIndex] : []),\n\t\t\t...symbolPathSegments(part),\n\t\t]);\n\nexport const joinPath = (prefix: string, segment: string) =>\n\tsegment.startsWith(\"[\") || !prefix\n\t\t? `${prefix}${segment}`\n\t\t: `${prefix}.${segment}`;\n\n/** Scalar type ids are their IEC names, and may have no entry in `types`. */\nexport const typeOf = (manifest: DebugManifest, id: string): DebugType =>\n\tmanifest.types[id] ?? { kind: \"scalar\", iec: id };\n\nexport const createPaths = (manifest: DebugManifest) => {\n\tconst typeOfId = (id: string) => typeOf(manifest, id);\n\t// I/O bindings are readable symbols with TypeScript paths of their own.\n\tconst bases = new Map<string, Extract<ResolvedPath, { kind: \"target\" }>>([\n\t\t...manifest.roots.map(\n\t\t\t({ path, ...root }) =>\n\t\t\t\t[path, { kind: \"target\" as const, path, ...root }] as const,\n\t\t),\n\t\t...manifest.io.map(\n\t\t\t({ path, target, type }) =>\n\t\t\t\t[\n\t\t\t\t\tpath,\n\t\t\t\t\t{ kind: \"target\" as const, path, target, type, readable: true },\n\t\t\t\t] as const,\n\t\t),\n\t]);\n\tconst constants = new Map(\n\t\tmanifest.constants.map(({ path, ...constant }) => [\n\t\t\tpath,\n\t\t\t{ kind: \"constant\" as const, path, ...constant },\n\t\t]),\n\t);\n\t/** Children of the prefixes of every root and constant path, which are groups unless they resolve. */\n\tconst groups = new Map<string, Set<string>>();\n\tfor (const path of [...bases.keys(), ...constants.keys()]) {\n\t\tlet prefix = \"\";\n\t\tfor (const segment of pathSegments(path)) {\n\t\t\tlet children = groups.get(prefix);\n\t\t\tif (!children) {\n\t\t\t\tgroups.set(prefix, (children = new Set()));\n\t\t\t}\n\t\t\tchildren.add(segment);\n\t\t\tprefix = joinPath(prefix, segment);\n\t\t}\n\t}\n\n\tconst resolve = (path: string): ResolvedPath | undefined => {\n\t\tconst constant = constants.get(path);\n\t\tif (constant) {\n\t\t\treturn constant;\n\t\t}\n\t\tconst segments = pathSegments(path);\n\t\tfor (let length = segments.length; length > 0; length--) {\n\t\t\tconst base = bases.get(segments.slice(0, length).reduce(joinPath, \"\"));\n\t\t\tif (!base) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet resolved: ResolvedPath = base;\n\t\t\tfor (const segment of segments.slice(length)) {\n\t\t\t\tconst type = typeOfId(resolved.type);\n\t\t\t\tif (type.kind === \"record\") {\n\t\t\t\t\tconst field = type.fields.find(({ name }) => name === segment);\n\t\t\t\t\tif (!field) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolved = {\n\t\t\t\t\t\tkind: \"target\",\n\t\t\t\t\t\tpath: joinPath(resolved.path, segment),\n\t\t\t\t\t\ttarget: `${resolved.target}.${field.target}`,\n\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t\treadable: resolved.readable,\n\t\t\t\t\t\t...(field.generated && { generated: true }),\n\t\t\t\t\t\t...(field.declaration && { declaration: field.declaration }),\n\t\t\t\t\t};\n\t\t\t\t} else if (type.kind === \"array\") {\n\t\t\t\t\tif (!isArrayIndexSegment(segment)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst index = Number(segment.slice(1, -1));\n\t\t\t\t\tif (index < type.lower || index >= type.lower + type.length) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolved = {\n\t\t\t\t\t\tkind: \"target\",\n\t\t\t\t\t\tpath: joinPath(resolved.path, segment),\n\t\t\t\t\t\ttarget: `${resolved.target}${segment}`,\n\t\t\t\t\t\ttype: type.element,\n\t\t\t\t\t\treadable: resolved.readable,\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resolved;\n\t\t}\n\t};\n\n\tconst typedChildren = (resolved: ResolvedPath | undefined) => {\n\t\tconst type =\n\t\t\tresolved?.kind === \"target\" ? typeOfId(resolved.type) : undefined;\n\t\tif (type?.kind === \"record\") {\n\t\t\treturn type.fields.map(({ name }) => name);\n\t\t}\n\t\tif (type?.kind === \"array\") {\n\t\t\treturn Array.from(\n\t\t\t\t{ length: type.length },\n\t\t\t\t(_, index) => `[${type.lower + index}]`,\n\t\t\t);\n\t\t}\n\t\treturn [];\n\t};\n\n\t/** A path's fields or indexes, and the roots and constants below it. */\n\tconst children = (path: string): PathNode[] => {\n\t\tconst names = [\n\t\t\t...typedChildren(resolve(path)),\n\t\t\t...(groups.get(path) ?? []),\n\t\t];\n\t\treturn [...new Set(names)].map((name) => {\n\t\t\tconst child = joinPath(path, name);\n\t\t\treturn { name, ...(resolve(child) ?? { kind: \"group\", path: child }) };\n\t\t});\n\t};\n\n\tconst isLeaf = (node: ResolvedPath | GroupPath) =>\n\t\tnode.kind === \"constant\" ||\n\t\t(node.kind === \"target\" &&\n\t\t\t[\"scalar\", \"enum\"].includes(typeOfId(node.type).kind));\n\n\t/**\n\t * Leaf paths matching `patterns`, where `*` stands for one segment. A pattern naming a record,\n\t * array or group stands for all its leaves; wildcards and expansion skip compiler-made fields.\n\t * Paths that don't resolve are kept, so callers can report them.\n\t */\n\tconst expand = (patterns: readonly string[], limit = 2000) => {\n\t\tconst leaves = new Set<string>();\n\t\tconst add = (path: string) => {\n\t\t\tleaves.add(path);\n\t\t\tif (leaves.size > limit) {\n\t\t\t\tthrow new RangeError(`More than ${limit} values match`);\n\t\t\t}\n\t\t};\n\t\tconst below = (node: ResolvedPath | GroupPath) => {\n\t\t\tif (isLeaf(node)) {\n\t\t\t\treturn add(node.path);\n\t\t\t}\n\t\t\tfor (const child of children(node.path)) {\n\t\t\t\tif (!(child.kind === \"target\" && child.generated)) {\n\t\t\t\t\tbelow(child);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst match = (\n\t\t\tprefix: string,\n\t\t\trest: readonly string[],\n\t\t\twildcard: boolean,\n\t\t) => {\n\t\t\tconst [head, ...tail] = rest;\n\t\t\tif (head === undefined) {\n\t\t\t\tconst node: ResolvedPath | GroupPath | undefined =\n\t\t\t\t\tresolve(prefix) ??\n\t\t\t\t\t(groups.has(prefix) ? { kind: \"group\", path: prefix } : undefined);\n\t\t\t\tif (node) {\n\t\t\t\t\tbelow(node);\n\t\t\t\t} else if (!wildcard) {\n\t\t\t\t\tadd(prefix);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (head === \"*\" || head === anyIndex) {\n\t\t\t\tfor (const child of children(prefix)) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(child.kind === \"target\" && child.generated) &&\n\t\t\t\t\t\t(head === \"*\" || child.name.startsWith(\"[\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tmatch(child.path, tail, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmatch(joinPath(prefix, head), tail, wildcard);\n\t\t\t}\n\t\t};\n\t\tfor (const pattern of patterns) {\n\t\t\tmatch(\"\", pathSegments(pattern), false);\n\t\t}\n\t\treturn [...leaves];\n\t};\n\n\t/** A value as TypeScript shows it: enum members by name, BOOL as a boolean. */\n\tconst decode = (typeId: string, raw: unknown) => {\n\t\tconst type = typeOfId(typeId);\n\t\tif (type.kind === \"enum\") {\n\t\t\treturn (\n\t\t\t\tObject.entries(type.members).find(([, value]) => value === raw)?.[0] ??\n\t\t\t\traw\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\ttype.kind === \"scalar\" &&\n\t\t\ttype.iec === \"BOOL\" &&\n\t\t\ttypeof raw === \"number\"\n\t\t) {\n\t\t\treturn raw !== 0;\n\t\t}\n\t\treturn raw;\n\t};\n\n\treturn { typeOf: typeOfId, resolve, children, isLeaf, expand, decode };\n};\n\nexport type Paths = ReturnType<typeof createPaths>;\n",
11
+ "import type {\n\tAppRecord,\n\tConnectionState,\n\tRequestTrace,\n\tTimelineEntry,\n\tTraceEvent,\n} from \"./api.ts\";\n\nexport type Entry<Kind extends TimelineEntry[\"kind\"]> = Extract<\n\tTimelineEntry,\n\t{ kind: Kind }\n>;\ntype Details<Kind extends TimelineEntry[\"kind\"]> = Omit<\n\tEntry<Kind>,\n\t\"at\" | \"approximate\" | \"source\" | \"kind\"\n>;\n\n/**\n * Timeline entries by source. The PLC's records are placed on the app server's clock from their\n * age when the server received them, and the server keeps its own clock, so those are\n * approximate. The agent's entries reach a debugger only when the agent hosts it, on the same clock.\n */\nexport const timelineEntries = {\n\tapp: (\n\t\tat: string,\n\t\ttask: string,\n\t\tsequence: number,\n\t\trecord: AppRecord,\n\t): Entry<\"app\"> => ({\n\t\tat,\n\t\tapproximate: true,\n\t\tsource: \"plc\",\n\t\tkind: \"app\",\n\t\ttask,\n\t\tsequence,\n\t\trecord,\n\t}),\n\ttrace: (at: string, trace: TraceEvent): Entry<\"trace\"> => ({\n\t\tat,\n\t\tapproximate: true,\n\t\tsource: \"plc\",\n\t\tkind: \"trace\",\n\t\ttrace,\n\t}),\n\trequest: (request: RequestTrace): Entry<\"request\"> => ({\n\t\tat: request.startedAt,\n\t\tapproximate: true,\n\t\tsource: \"server\",\n\t\tkind: \"request\",\n\t\trequest,\n\t}),\n\tdeploy: (at: string, details: Details<\"deploy\">): Entry<\"deploy\"> => ({\n\t\tat,\n\t\tapproximate: false,\n\t\tsource: \"agent\",\n\t\tkind: \"deploy\",\n\t\t...details,\n\t}),\n\taudit: (at: string, details: Details<\"audit\">): Entry<\"audit\"> => ({\n\t\tat,\n\t\tapproximate: false,\n\t\tsource: \"agent\",\n\t\tkind: \"audit\",\n\t\t...details,\n\t}),\n\tconnection: (\n\t\tat: string,\n\t\tstate: ConnectionState,\n\t\terror?: string,\n\t): Entry<\"connection\"> => ({\n\t\tat,\n\t\tapproximate: false,\n\t\tsource: \"debugger\",\n\t\tkind: \"connection\",\n\t\tstate,\n\t\t...(error && { error }),\n\t}),\n};\n\n/**\n * Adds `entry` to `entries`, which are oldest first. Sources arrive late and out of order, so it\n * goes after the last entry not later than it.\n */\nexport const insertInTimeOrder = (\n\tentries: TimelineEntry[],\n\tentry: TimelineEntry,\n) => {\n\tfor (let index = entries.length; index >= 0; index--) {\n\t\tconst before = entries[index - 1];\n\t\tif (before === undefined || before.at <= entry.at) {\n\t\t\tentries.splice(index, 0, entry);\n\t\t\treturn;\n\t\t}\n\t}\n};\n\n/** Entries from every source in time order, keeping the newest `limit`. */\nexport const createTimeline = (limit = 10_000) => {\n\tconst entries: TimelineEntry[] = [];\n\treturn {\n\t\tadd: (entry: TimelineEntry) => {\n\t\t\tinsertInTimeOrder(entries, entry);\n\t\t\tif (entries.length > limit) {\n\t\t\t\tentries.splice(0, entries.length - limit);\n\t\t\t}\n\t\t},\n\t\t/** Entries after `at`, or all of them. */\n\t\tsince: (at?: string) =>\n\t\t\tat ? entries.filter((entry) => entry.at > at) : [...entries],\n\t};\n};\n\nexport type Timeline = ReturnType<typeof createTimeline>;\n",
12
+ "import type { RequestsReply } from \"@tsplc/server/requests\";\nimport type { RequestTrace } from \"./api.ts\";\nimport { type Entry, timelineEntries } from \"./timeline.ts\";\n\n/** Traces kept for jobs to find their calls by; older ones are forgotten. */\nconst callsRemembered = 1000;\n\n/** A call that started or ended, with its timeline entry; `added` when the entry is new. */\ninterface RequestChange {\n\trequest: RequestTrace;\n\tentry: Entry<\"request\">;\n\tadded: boolean;\n}\n\n/**\n * Follows the app server's request trace (`GET /tsplc/debug/requests`), asking again from before\n * the oldest call still pending, so each call is seen when it starts and again when it ends.\n */\nexport const createRequestFollower = () => {\n\tlet newest = 0;\n\tconst pending = new Map<number, Entry<\"request\">>();\n\t/** By `<job id>:<service>:<sequence>`, newest last. */\n\tconst calls = new Map<string, RequestTrace>();\n\n\treturn {\n\t\t/** Where the next pull starts. */\n\t\tsince: () => (pending.size ? Math.min(...pending.keys()) - 1 : newest),\n\t\t/** Takes a reply to `?since=<since()>`, telling `changed` of each call as it is taken. */\n\t\taccept: (\n\t\t\treply: RequestsReply,\n\t\t\tchanged: (change: RequestChange) => void,\n\t\t) => {\n\t\t\t// A restarted server counts from 1 again.\n\t\t\tif (reply.latest < newest) {\n\t\t\t\tnewest = 0;\n\t\t\t\tpending.clear();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst oldest = reply.requests[0]?.seq;\n\t\t\tif (oldest !== undefined) {\n\t\t\t\tfor (const seq of pending.keys()) {\n\t\t\t\t\tif (seq < oldest) {\n\t\t\t\t\t\tpending.delete(seq);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const request of reply.requests) {\n\t\t\t\tconst waiting = pending.get(request.seq);\n\t\t\t\tif (waiting && request.status === \"pending\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!waiting && request.seq <= newest) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst entry = waiting ?? timelineEntries.request(request);\n\t\t\t\tentry.request = request;\n\t\t\t\tnewest = Math.max(newest, request.seq);\n\t\t\t\tif (request.status === \"pending\") {\n\t\t\t\t\tpending.set(request.seq, entry);\n\t\t\t\t} else {\n\t\t\t\t\tpending.delete(request.seq);\n\t\t\t\t}\n\t\t\t\tif (request.job !== undefined && request.sequence !== undefined) {\n\t\t\t\t\tcalls.set(\n\t\t\t\t\t\t`${request.job}:${request.service}:${request.sequence}`,\n\t\t\t\t\t\trequest,\n\t\t\t\t\t);\n\t\t\t\t\tfor (const key of [...calls.keys()].slice(0, -callsRemembered)) {\n\t\t\t\t\t\tcalls.delete(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tchanged({ request, entry, added: !waiting });\n\t\t\t}\n\t\t},\n\t\t/** The server's trace of a call, which the PLC tags with its job and the call site's count. */\n\t\tcall: ({\n\t\t\tjob,\n\t\t\tservice,\n\t\t\tsequence,\n\t\t}: {\n\t\t\tjob: number;\n\t\t\tservice: string;\n\t\t\tsequence: number;\n\t\t}) => calls.get(`${job}:${service}:${sequence}`),\n\t};\n};\n",
13
+ "import type {\n\tTelemetryBatch,\n\tTelemetryRecord,\n\tTelemetryReply,\n} from \"@tsplc/server/telemetry\";\nimport { recordedAt } from \"@tsplc/server/telemetry-log\";\nimport type { Session } from \"./api.ts\";\nimport type { DebugManifest } from \"./manifest.ts\";\n\n/** Clock estimates are kept this long, on the server's clock. */\nconst clockWindowMs = 60_000;\n\n/** A record with the batch it came in, numbered in its task's sequence, at its time on the server's clock. */\nexport interface ReceivedRecord {\n\tbuild: string;\n\ttask: string;\n\tsequence: number;\n\tat: string;\n\trecord: TelemetryRecord;\n}\n\n/**\n * Follows the app server's telemetry ring (`GET /tsplc/telemetry`): it hands out each new record\n * once, keeps the tasks' scan rates, and estimates the PLC's clock against the server's.\n */\nexport const createTelemetryFollower = (manifest: DebugManifest) => {\n\tconst intervals = new Map(\n\t\tmanifest.tasks.map(({ name, intervalMs }) => [name, intervalMs]),\n\t);\n\tconst tasks = new Map<string, Session[\"tasks\"][number]>(\n\t\tmanifest.tasks.map(({ name }) => [\n\t\t\tname,\n\t\t\t{ name, scan: null, scansPerSecond: null, dropped: 0 },\n\t\t]),\n\t);\n\tconst rates = new Map<string, { scan: number; now: number }>();\n\tlet estimates: { offsetMs: number; intervalMs: number; at: number }[] = [];\n\tlet newest = 0;\n\tlet build: string | null = null;\n\n\t/**\n\t * A batch's `now` was read before it was sent, so `now − receivedAt` falls short of the true\n\t * offset by its transit time: the largest recent estimate is the closest, and their spread,\n\t * plus a scan, bounds how far off it may be.\n\t */\n\tconst clock = (): Session[\"clock\"] => {\n\t\tif (!estimates.length) {\n\t\t\treturn null;\n\t\t}\n\t\tconst offsets = estimates.map(({ offsetMs }) => offsetMs);\n\t\tconst best = estimates.reduce((best, estimate) =>\n\t\t\testimate.offsetMs > best.offsetMs ? estimate : best,\n\t\t);\n\t\treturn {\n\t\t\toffsetMs: best.offsetMs,\n\t\t\tuncertaintyMs: best.offsetMs - Math.min(...offsets) + best.intervalMs,\n\t\t};\n\t};\n\n\tconst observe = (batch: TelemetryBatch, receivedAt: number) => {\n\t\tconst rate = rates.get(batch.task);\n\t\t// A restarted PLC counts scans and time from zero again.\n\t\tconst restarted = rate !== undefined && batch.now < rate.now;\n\t\tif (restarted) {\n\t\t\testimates = [];\n\t\t}\n\t\testimates = estimates.filter(({ at }) => receivedAt - at < clockWindowMs);\n\t\testimates.push({\n\t\t\toffsetMs: batch.now - receivedAt,\n\t\t\tintervalMs: intervals.get(batch.task) ?? 0,\n\t\t\tat: receivedAt,\n\t\t});\n\t\tconst stats = {\n\t\t\tname: batch.task,\n\t\t\tscansPerSecond: tasks.get(batch.task)?.scansPerSecond ?? null,\n\t\t\tscan: batch.scan,\n\t\t\tdropped: batch.dropped,\n\t\t};\n\t\tif (!rate || restarted) {\n\t\t\trates.set(batch.task, { scan: batch.scan, now: batch.now });\n\t\t} else if (batch.now - rate.now >= 1000) {\n\t\t\tstats.scansPerSecond =\n\t\t\t\t((batch.scan - rate.scan) * 1000) / (batch.now - rate.now);\n\t\t\trates.set(batch.task, { scan: batch.scan, now: batch.now });\n\t\t}\n\t\ttasks.set(batch.task, stats);\n\t};\n\n\treturn {\n\t\t/** Where the next pull starts. */\n\t\tsince: () => newest,\n\t\t/** Takes a reply to `GET /tsplc/telemetry?since=<since()>`; a restarted server starts over. */\n\t\taccept: (reply: TelemetryReply): ReceivedRecord[] => {\n\t\t\tif (reply.latest < newest) {\n\t\t\t\tnewest = 0;\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tconst received: ReceivedRecord[] = [];\n\t\t\tfor (const batch of reply.batches) {\n\t\t\t\tif (batch.seq <= newest) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tnewest = batch.seq;\n\t\t\t\tbuild = batch.build;\n\t\t\t\tconst receivedAt = new Date(batch.receivedAt);\n\t\t\t\tobserve(batch, receivedAt.getTime());\n\t\t\t\tbatch.records.forEach((record, index) =>\n\t\t\t\t\treceived.push({\n\t\t\t\t\t\tbuild: batch.build,\n\t\t\t\t\t\ttask: batch.task,\n\t\t\t\t\t\tsequence: batch.first + index,\n\t\t\t\t\t\tat: recordedAt(batch, record, receivedAt).toISOString(),\n\t\t\t\t\t\trecord,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn received;\n\t\t},\n\t\t/** The build the newest batch came from. */\n\t\tbuild: () => build,\n\t\tclock,\n\t\ttasks: () => [...tasks.values()].map((task) => ({ ...task })),\n\t};\n};\n",
14
+ "import type { TelemetryRecord } from \"@tsplc/server/telemetry\";\nimport type { TraceEvent } from \"./api.ts\";\nimport type { DebugJob, DebugManifest } from \"./manifest.ts\";\nimport type { Paths } from \"./paths.ts\";\n\nexport type TraceRecord = Extract<TelemetryRecord, { kind: \"trace\" }>;\n\n/**\n * Decodes the opt-in trace through the manifest's event sites (docs/design/debugging.md). Only\n * records of the manifest's own build may be decoded: another build's site ids mean other code.\n */\nexport const createTraceDecoder = (manifest: DebugManifest, paths: Paths) => {\n\tconst sites = new Map(manifest.events.map((site) => [site.id, site]));\n\tconst jobs = new Map(manifest.jobs.map((job) => [job.id, job]));\n\tconst jobSites = new Map(\n\t\tmanifest.events.flatMap(({ id, job: jobId, phase }) => {\n\t\t\tconst job = jobId === undefined ? undefined : jobs.get(jobId);\n\t\t\treturn job && phase\n\t\t\t\t? [[id, { job, started: phase === \"started\" }] as const]\n\t\t\t\t: [];\n\t\t}),\n\t);\n\n\treturn {\n\t\tdecode: (\n\t\t\trecord: TraceRecord,\n\t\t\ttask: string,\n\t\t\tsequence: number,\n\t\t): TraceEvent | undefined => {\n\t\t\tconst site = sites.get(record.site);\n\t\t\tif (!site) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsequence,\n\t\t\t\ttask,\n\t\t\t\tscan: record.scan,\n\t\t\t\tplcTime: record.time,\n\t\t\t\tsite: site.id,\n\t\t\t\tvalue: paths.decode(site.type, record.value),\n\t\t\t\toperands: site.operands.map(({ text, path, stable, type }, index) => ({\n\t\t\t\t\ttext,\n\t\t\t\t\t...(path && { path }),\n\t\t\t\t\tstable,\n\t\t\t\t\tvalue: paths.decode(type, record.operands[index]),\n\t\t\t\t})),\n\t\t\t};\n\t\t},\n\t\t/** The job a record starts or finishes, if its site is a job's. */\n\t\tjob: (\n\t\t\trecord: TraceRecord,\n\t\t): { job: DebugJob; started: boolean } | undefined =>\n\t\t\tjobSites.get(record.site),\n\t};\n};\n",
15
+ "import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport { z } from \"zod\";\nimport type { WatchGroups } from \"./api.ts\";\n\nexport const watchGroupsSchema = z.strictObject({\n\tgroups: z.record(z.string().nonempty(), z.array(z.string().nonempty())),\n});\n\n/**\n * Watch groups: the config's `debug.watch`, then groups saved in `file`. Saving keeps only the\n * groups that differ from the config, so the config stays their source.\n */\nexport const loadWatchGroups = async (\n\tfile: string,\n\tconfigured: Record<string, string[]>,\n) => {\n\tlet saved = existsSync(file)\n\t\t? watchGroupsSchema.parse(JSON.parse(await readFile(file, \"utf8\"))).groups\n\t\t: {};\n\tconst groups = (): WatchGroups => ({ groups: { ...configured, ...saved } });\n\treturn {\n\t\tgroups,\n\t\tsave: async ({ groups: next }: WatchGroups) => {\n\t\t\tsaved = Object.fromEntries(\n\t\t\t\tObject.entries(next).filter(\n\t\t\t\t\t([name, paths]) => !isDeepStrictEqual(configured[name], paths),\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait mkdir(dirname(file), { recursive: true });\n\t\t\tawait writeFile(file, JSON.stringify({ groups: saved }, null, 2));\n\t\t\treturn groups();\n\t\t},\n\t};\n};\n",
16
+ "import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport type { Interest, Sample } from \"./api.ts\";\nimport { DebugError, type Debugger, type StreamMessage } from \"./debugger.ts\";\nimport { debugManifest } from \"./manifest.ts\";\nimport { loadUi } from \"./ui/index.ts\";\nimport { watchGroupsSchema } from \"./watch.ts\";\n\n/** Comments keep proxies and Bun's idle timeout from closing a quiet stream. */\nconst heartbeatMs = 5000;\nconst encoder = new TextEncoder();\n\nconst json = (body: unknown, status = 200) =>\n\tResponse.json(body, { status, headers: { \"Cache-Control\": \"no-store\" } });\n\nconst list = (value: string | null) =>\n\t(value ?? \"\")\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n\nexport const loadManifest = async (file: string) =>\n\tdebugManifest.parse(JSON.parse(await readFile(file, \"utf8\")));\n\n/** What a stream's page shows, from its query. */\nconst interest = (search: URLSearchParams): Interest => {\n\tconst jobs = list(search.get(\"jobs\")).map(Number);\n\tif (!jobs.every(Number.isInteger)) {\n\t\tthrow new DebugError(\"jobs must be job ids\", 400);\n\t}\n\treturn {\n\t\twatch: list(search.get(\"watch\")),\n\t\tjobs,\n\t\thealth: list(search.get(\"health\")),\n\t\tdevices: list(search.get(\"devices\")),\n\t};\n};\n\n/** Every stream event, plus samples of the watched paths and states of the shown jobs and devices. */\nconst stream = (debug: Debugger, { watch, ...shown }: Interest) => {\n\t// Refuse a watch that matches too much before the stream starts.\n\tdebug.paths.expand(watch);\n\tlet stop = () => {};\n\treturn new Response(\n\t\tnew ReadableStream<Uint8Array>({\n\t\t\tstart: (controller) => {\n\t\t\t\tlet open = true;\n\t\t\t\tconst write = (text: string) => {\n\t\t\t\t\tif (open) {\n\t\t\t\t\t\tcontroller.enqueue(encoder.encode(text));\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tconst send = ({ event, data }: StreamMessage) =>\n\t\t\t\t\twrite(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n\t\t\t\tsend({ event: \"session\", data: debug.session() });\n\t\t\t\tconst latest = new Map<string, { sample: Sample; sentAt: number }>();\n\t\t\t\tconst sendSample = (sample: Sample) => {\n\t\t\t\t\tlatest.set(sample.path, { sample, sentAt: Date.now() });\n\t\t\t\t\tsend({ event: \"sample\", data: sample });\n\t\t\t\t};\n\t\t\t\tconst unsubscribe = debug.subscribe(send);\n\t\t\t\tconst unwatch = debug.watch(watch, sendSample);\n\t\t\t\tconst unshow = debug.show(shown);\n\t\t\t\tconst heartbeat = setInterval(\n\t\t\t\t\t() => write(\": keepalive\\n\\n\"),\n\t\t\t\t\theartbeatMs,\n\t\t\t\t);\n\t\t\t\t// Over OPC UA, samples come only on change. While the session holds, an unchanged value\n\t\t\t\t// is still current, so it is sent again each interval; clients mark samples stale by their age.\n\t\t\t\tconst { intervalMs } = debug.session().reading;\n\t\t\t\tconst refresh = setInterval(() => {\n\t\t\t\t\tif (debug.session().connection.state !== \"connected\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tfor (const { sample, sentAt } of latest.values()) {\n\t\t\t\t\t\tif (now - sentAt >= intervalMs) {\n\t\t\t\t\t\t\tsendSample({\n\t\t\t\t\t\t\t\t...sample,\n\t\t\t\t\t\t\t\treceivedAt: new Date(now).toISOString(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, intervalMs);\n\t\t\t\tstop = () => {\n\t\t\t\t\topen = false;\n\t\t\t\t\tclearInterval(heartbeat);\n\t\t\t\t\tclearInterval(refresh);\n\t\t\t\t\tunsubscribe();\n\t\t\t\t\tunwatch();\n\t\t\t\t\tunshow();\n\t\t\t\t};\n\t\t\t},\n\t\t\tcancel: () => stop(),\n\t\t}),\n\t\t{\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t},\n\t\t},\n\t);\n};\n\n/**\n * The debugger's routes (docs/design/debugging.md), with `route` the request's path below where\n * the host mounts them. There is no route that writes to the controller; hosts authenticate.\n */\nexport const createDebugHandler =\n\t(debug: Debugger, log: (message: string) => void) =>\n\tasync (request: Request, route: string): Promise<Response> => {\n\t\tconst { searchParams } = new URL(request.url);\n\t\tconst key = `${request.method} ${route}`;\n\t\ttry {\n\t\t\tswitch (key) {\n\t\t\t\tcase \"GET /\":\n\t\t\t\t\treturn new Response((await loadUi()).html, {\n\t\t\t\t\t\theaders: { \"Content-Type\": \"text/html; charset=utf-8\" },\n\t\t\t\t\t});\n\t\t\t\tcase \"GET /ui.js\":\n\t\t\t\t\treturn new Response((await loadUi()).script, {\n\t\t\t\t\t\theaders: { \"Content-Type\": \"text/javascript; charset=utf-8\" },\n\t\t\t\t\t});\n\t\t\t\tcase \"GET /api/session\":\n\t\t\t\t\treturn json(debug.session());\n\t\t\t\tcase \"GET /api/manifest\":\n\t\t\t\t\treturn json(debug.manifest);\n\t\t\t\tcase \"GET /api/stream\":\n\t\t\t\t\treturn stream(debug, interest(searchParams));\n\t\t\t\tcase \"GET /api/values\":\n\t\t\t\t\treturn json(await debug.values(list(searchParams.get(\"paths\"))));\n\t\t\t\tcase \"GET /api/jobs\":\n\t\t\t\t\treturn json(debug.jobs());\n\t\t\t\tcase \"GET /api/hardware\":\n\t\t\t\t\treturn json(debug.hardware());\n\t\t\t\tcase \"GET /api/timeline\":\n\t\t\t\t\treturn json(debug.timeline(searchParams.get(\"since\") ?? undefined));\n\t\t\t\tcase \"GET /api/watch\":\n\t\t\t\t\treturn json(debug.watchGroups());\n\t\t\t\tcase \"PUT /api/watch\":\n\t\t\t\t\treturn json(\n\t\t\t\t\t\tawait debug.saveWatchGroups(\n\t\t\t\t\t\t\twatchGroupsSchema.parse(await request.json()),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t}\n\t\t\treturn json({ error: `No route ${key}` }, 404);\n\t\t} catch (error) {\n\t\t\tif (error instanceof DebugError) {\n\t\t\t\treturn json({ error: error.message }, error.status);\n\t\t\t}\n\t\t\t// RangeError: a watch matches too many values; SyntaxError: a body isn't JSON.\n\t\t\tif (error instanceof RangeError || error instanceof SyntaxError) {\n\t\t\t\treturn json({ error: error.message }, 400);\n\t\t\t}\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\treturn json({ error: z.prettifyError(error) }, 400);\n\t\t\t}\n\t\t\tlog(\n\t\t\t\t`${key} failed: ${error instanceof Error ? error.stack : String(error)}`,\n\t\t\t);\n\t\t\treturn json({ error: \"The debugger failed; see its log\" }, 500);\n\t\t}\n\t};\n\n/**\n * Serves the debugger on 127.0.0.1 without a token. Requests that name another host are refused,\n * so no website can reach it by rebinding a domain name to 127.0.0.1.\n */\nexport const serveDebugger = (\n\tdebug: Debugger,\n\toptions: { port: number; log: (message: string) => void },\n) => {\n\tconst handle = createDebugHandler(debug, options.log);\n\treturn Bun.serve({\n\t\thostname: \"127.0.0.1\",\n\t\tport: options.port,\n\t\tfetch: (request) => {\n\t\t\tconst host = request.headers.get(\"host\")?.replace(/:\\d+$/, \"\");\n\t\t\tif (host !== \"127.0.0.1\" && host !== \"localhost\") {\n\t\t\t\treturn json({ error: \"Use http://127.0.0.1 or http://localhost\" }, 403);\n\t\t\t}\n\t\t\treturn handle(request, new URL(request.url).pathname);\n\t\t},\n\t});\n};\n",
17
+ "import { z } from \"zod\";\n\n/**\n * What a build tells the debugger: every TypeScript identity it can show, and the target symbol each one reads.\n * TypeScript paths (`program.diverters.binTrackers[10].bin`) are the identity; `target` strings are opaque to\n * everything except the target's adapter (for CODESYS, IEC symbol paths such as `plc_Program.diverters…`).\n * Written by the compiler to `.tsplc/artifacts/st/debug.json` and shipped with each release.\n */\n\n/** A location in the project's own sources: `file` indexes `sources`; lines and columns are 1-based. */\nexport const sourceRange = z.object({\n\tfile: z.number().int(),\n\tline: z.number().int(),\n\tcolumn: z.number().int(),\n\tendLine: z.number().int(),\n\tendColumn: z.number().int(),\n});\n\nconst json: z.ZodType<unknown> = z.lazy(() =>\n\tz.union([\n\t\tz.string(),\n\t\tz.number(),\n\t\tz.boolean(),\n\t\tz.null(),\n\t\tz.array(json),\n\t\tz.record(z.string(), json),\n\t]),\n);\n\nexport const debugField = z.object({\n\tname: z.string(),\n\ttarget: z.string(),\n\ttype: z.string(),\n\tdeclaration: sourceRange.optional(),\n\t/** Compiler-made storage, such as an async job's `step`; hidden unless asked for. */\n\tgenerated: z.literal(true).optional(),\n});\n\n/** Keys of `types` are opaque ids; scalars use their IEC name, such as `BOOL`. */\nexport const debugType = z.discriminatedUnion(\"kind\", [\n\tz.object({ kind: z.literal(\"scalar\"), iec: z.string() }),\n\tz.object({\n\t\tkind: z.literal(\"enum\"),\n\t\tname: z.string(),\n\t\tmembers: z.record(z.string(), z.number().int()),\n\t}),\n\tz.object({\n\t\tkind: z.literal(\"record\"),\n\t\tname: z.string(),\n\t\tdeclaration: sourceRange.optional(),\n\t\tfields: z.array(debugField),\n\t}),\n\tz.object({\n\t\tkind: z.literal(\"array\"),\n\t\telement: z.string(),\n\t\tlength: z.number().int(),\n\t\t/** The first index; TypeScript paths use the target's own indexes, `lower` to `lower + length - 1`. */\n\t\tlower: z.number().int(),\n\t}),\n]);\n\nexport const debugRoot = z.object({\n\tpath: z.string(),\n\ttarget: z.string(),\n\ttype: z.string(),\n\tdeclaration: sourceRange.optional(),\n\t/** Readable at runtime through the target's adapter; for CODESYS, all stored state is. */\n\treadable: z.boolean(),\n\tgenerated: z.literal(true).optional(),\n});\n\n/** A field the compiler folded away: it has no runtime storage, but its value is known. */\nexport const debugConstant = z.object({\n\tpath: z.string(),\n\ttype: z.string(),\n\tvalue: json,\n\tdeclaration: sourceRange.optional(),\n});\n\nexport const debugIo = z.object({\n\tpath: z.string(),\n\ttarget: z.string(),\n\tdirection: z.enum([\"input\", \"output\"]),\n\ttype: z.string(),\n\tdevice: z.string().optional(),\n\tchannel: z.string().optional(),\n\taddress: z.string().optional(),\n\tinverted: z.literal(true).optional(),\n\tshared: z.literal(true).optional(),\n});\n\nexport const debugChannel = z.object({\n\tid: z.string(),\n\tname: z.string(),\n\tdirection: z.enum([\"input\", \"output\"]),\n\ttype: z.string(),\n\toffsetBits: z.number().int(),\n\tbits: z.number().int(),\n\taddress: z.string().optional(),\n\tunit: z.string().optional(),\n\tdescription: z.string().optional(),\n});\n\nexport const debugDevice = z.object({\n\tid: z.string(),\n\tproduct: z.string().optional(),\n\tvendor: z.string().optional(),\n\tproductCode: z.string().optional(),\n\tnetwork: z\n\t\t.object({ address: z.string(), rpiMs: z.number().optional() })\n\t\t.optional(),\n\tconnection: z.string().optional(),\n\tassemblies: z.array(\n\t\tz.object({\n\t\t\tdirection: z.enum([\"input\", \"output\"]),\n\t\t\tbytes: z.number().int(),\n\t\t\taddress: z.string().optional(),\n\t\t\t/** A byte array over the whole assembly, mapped or not. */\n\t\t\traw: z.string().optional(),\n\t\t}),\n\t),\n\t/**\n\t * Target paths of the driver's own state, such as a generated adapter's `eState`; absent means\n\t * the device's health is unknown.\n\t */\n\thealth: z\n\t\t.object({\n\t\t\tstate: z.string().optional(),\n\t\t\tstates: z.record(z.string(), z.number().int()).optional(),\n\t\t\tdiagnostic: z.string().optional(),\n\t\t\tmessage: z.string().optional(),\n\t\t})\n\t\t.optional(),\n\t/** Status symbols by label: hand-configured ones, and a generated Modbus server's error. */\n\tstatus: z.record(z.string(), z.string()).optional(),\n\tchannels: z.array(debugChannel),\n});\n\n/** A specialized function: one per method per instance, so `reads` resolve to concrete paths. */\nexport const debugFunction = z.object({\n\tid: z.number().int(),\n\tname: z.string(),\n\tdeclaration: sourceRange,\n\t/** The TypeScript path of `this`, for a method specialized to one instance. */\n\tinstance: z.string().optional(),\n\ttask: z.string().optional(),\n\ttarget: z.string(),\n\t/** Member reads in the body whose runtime path is static in this specialization. */\n\treads: z.array(z.object({ range: sourceRange, path: z.string() })),\n});\n\nexport const debugJob = z.object({\n\tid: z.number().int(),\n\tname: z.string(),\n\tdeclaration: sourceRange,\n\tinstance: z.string().optional(),\n\t/** The job's state, with fields `step`, `busy`, `done`, `error` and `cancelling`. */\n\ttarget: z.string(),\n\tsteps: z.array(\n\t\tz.object({\n\t\t\tstep: z.number().int(),\n\t\t\tkind: z.enum([\"await\", \"return\", \"throw\", \"statement\"]),\n\t\t\trange: sourceRange,\n\t\t\ttext: z.string(),\n\t\t}),\n\t),\n\t/**\n\t * The PLC clock in milliseconds when the job last started: the clock of telemetry records'\n\t * `time` and a batch's `now`.\n\t */\n\tstartedAt: z.string().optional(),\n\t/**\n\t * Service calls the job awaits, its nested jobs' included; `sequence` is the request counter sent\n\t * as `x-tsplc-request`, with `job`'s id when a nested job makes the call.\n\t */\n\trequests: z.array(\n\t\tz.object({\n\t\t\tservice: z.string(),\n\t\t\ttarget: z.string(),\n\t\t\tsequence: z.string(),\n\t\t\tjob: z.number().int().optional(),\n\t\t}),\n\t),\n\t/** Made by the compiler, such as a service call's own job; hidden unless asked for. */\n\tgenerated: z.literal(true).optional(),\n});\n\n/**\n * Where `debug.trace` records: an enum state field changing, a decision function returning a\n * different value, or a job starting or finishing. Trace records name their site by `id`.\n */\nexport const debugEventSite = z.object({\n\tid: z.number().int(),\n\tkind: z.enum([\"state\", \"decision\", \"job\"]),\n\t/** For `kind: \"job\"`: the job, and whether it starts or finishes at this site. */\n\tjob: z.number().int().optional(),\n\tphase: z.enum([\"started\", \"finished\"]).optional(),\n\t/** The TypeScript path written, or of the job. */\n\tpath: z.string(),\n\tfunction: z.number().int().optional(),\n\ttype: z.string(),\n\trange: sourceRange,\n\ttext: z.string(),\n\ttask: z.string(),\n\t/**\n\t * Guard values captured in the same scan, at the write: each `if` condition leaf enclosing it.\n\t * `stable` is false when the body between the guard and the write can change the leaf.\n\t */\n\toperands: z.array(\n\t\tz.object({\n\t\t\ttext: z.string(),\n\t\t\trange: sourceRange,\n\t\t\ttype: z.string(),\n\t\t\tpath: z.string().optional(),\n\t\t\tstable: z.boolean(),\n\t\t}),\n\t),\n});\n\n/** The statement that last wrote each output, per scan. */\nexport const debugWriter = z.object({\n\toutput: z.string(),\n\ttarget: z.string(),\n\tsites: z.array(\n\t\tz.object({\n\t\t\tid: z.number().int(),\n\t\t\trange: sourceRange,\n\t\t\tfunction: z.number().int(),\n\t\t}),\n\t),\n});\n\nexport const debugTask = z.object({\n\tname: z.string(),\n\tintervalMs: z.number(),\n\tpriority: z.number().int(),\n});\n\nexport const debugManifest = z.object({\n\tkind: z.literal(\"tsplc-debug\"),\n\tversion: z.literal(1),\n\tbuild: z.object({\n\t\tid: z.string(),\n\t\t/** A variable holding `id`, to tell which build the controller runs. */\n\t\ttarget: z.string(),\n\t\tcompiler: z.string(),\n\t}),\n\t/** Project-relative paths. */\n\tsources: z.array(z.string()),\n\ttypes: z.record(z.string(), debugType),\n\troots: z.array(debugRoot),\n\tconstants: z.array(debugConstant),\n\tio: z.array(debugIo),\n\tdevices: z.array(debugDevice),\n\tfunctions: z.array(debugFunction),\n\tjobs: z.array(debugJob),\n\tevents: z.array(debugEventSite),\n\twriters: z.array(debugWriter),\n\ttasks: z.array(debugTask),\n\t/** Job error codes by number: 1 cancelled, 2 timeout… */\n\terrors: z.record(z.string(), z.string()),\n});\n\nexport type SourceRange = z.infer<typeof sourceRange>;\nexport type DebugType = z.infer<typeof debugType>;\nexport type DebugField = z.infer<typeof debugField>;\nexport type DebugRoot = z.infer<typeof debugRoot>;\nexport type DebugConstant = z.infer<typeof debugConstant>;\nexport type DebugIo = z.infer<typeof debugIo>;\nexport type DebugDevice = z.infer<typeof debugDevice>;\nexport type DebugChannel = z.infer<typeof debugChannel>;\nexport type DebugFunction = z.infer<typeof debugFunction>;\nexport type DebugJob = z.infer<typeof debugJob>;\nexport type DebugEventSite = z.infer<typeof debugEventSite>;\nexport type DebugWriter = z.infer<typeof debugWriter>;\nexport type DebugTask = z.infer<typeof debugTask>;\nexport type DebugManifest = z.infer<typeof debugManifest>;\n",
18
+ "import { createRequire } from \"node:module\";\nimport { dirname, resolve } from \"node:path\";\nimport { html } from \"./page.ts\";\n\nlet ui: Promise<{ html: string; script: string }> | undefined;\n\nconst build = async () => {\n\tconst result = await Bun.build({\n\t\tentrypoints: [\n\t\t\tresolve(\n\t\t\t\tdirname(createRequire(import.meta.url).resolve(\"@tsplc/debug\")),\n\t\t\t\t\"../src/ui/main.ts\",\n\t\t\t),\n\t\t],\n\t\ttarget: \"browser\",\n\t\t// Workspace packages resolve to their sources, as they do for the host, so no build is needed first.\n\t\tconditions: [\"bun\"],\n\t\tminify: true,\n\t});\n\tif (!result.success) {\n\t\tthrow new AggregateError(result.logs, \"Bundling the debugger UI failed\");\n\t}\n\treturn { html, script: await result.outputs[0]!.text() };\n};\n\n/** The browser UI: serve `html` at `GET /` and `script` at `GET /ui.js`. Bundled on first call, then cached. */\nexport const loadUi = () => (ui ??= build());\n",
17
19
  "const css = `\n:root{color-scheme:dark;\n--bg:#0c0e11;--grid:rgba(255,255,255,.025);--panel:#13161b;--panel-2:#191d23;--line:#262b33;--line-soft:#1d2128;\n--fg:#d8dce2;--dim:#7c848f;--accent:#f2a33a;--link:#79c0ff;\n--live:#5ee0a0;--uncertain:#f3c64a;--bad:#ff6b6b;--stale:#8a919b;--unavailable:#5a616b;--constant:#b8a2ff;\n--hatch:rgba(138,145,155,.16);\n--mono:\"JetBrains Mono\",\"Cascadia Mono\",\"IBM Plex Mono\",\"SF Mono\",Menlo,Consolas,monospace;\n--sans:\"IBM Plex Sans\",\"Segoe UI Variable Text\",\"Segoe UI\",\"Helvetica Neue\",sans-serif}\n@media (prefers-color-scheme:light){:root{color-scheme:light;\n--bg:#f3f1ec;--grid:rgba(0,0,0,.035);--panel:#fffefb;--panel-2:#f6f4ef;--line:#d8d3c8;--line-soft:#e7e3da;\n--fg:#1b1e22;--dim:#6a6e75;--accent:#b5650a;--link:#0a5bb0;\n--live:#0d8048;--uncertain:#9a6400;--bad:#c42525;--stale:#767b83;--unavailable:#a1a6ad;--constant:#6447cc;\n--hatch:rgba(118,123,131,.16)}}\n*{box-sizing:border-box}\nhtml,body{height:100%}\nbody{margin:0;font:13px/1.45 var(--sans);color:var(--fg);background:var(--bg);\nbackground-image:linear-gradient(var(--grid) 1px,transparent 1px),linear-gradient(90deg,var(--grid) 1px,transparent 1px);\nbackground-size:24px 24px;display:grid;grid-template-rows:auto minmax(0,1fr);font-variant-numeric:tabular-nums}\na{color:var(--link);text-decoration:none}a:hover{text-decoration:underline}\ncode,.mono,.path,.src{font-family:var(--mono);font-size:12px}\n.src,.nowrap,.grid td.num{white-space:nowrap}\ncode{color:var(--fg);background:var(--panel-2);border:1px solid var(--line-soft);border-radius:3px;padding:0 4px}\n.dim,.hint,.empty{color:var(--dim)}.hint{margin:4px 0 12px}.empty{margin:8px 0;font-style:italic}\n.err{color:var(--bad)}.num{text-align:right}\nbutton,input{font:inherit;color:inherit}\nbutton{background:var(--panel-2);border:1px solid var(--line);border-radius:4px;padding:3px 10px;cursor:pointer}\nbutton:hover{border-color:var(--dim)}button.primary{background:var(--accent);border-color:var(--accent);color:#16110a;font-weight:600}\nbutton:disabled{opacity:.5;cursor:default}\ninput{background:var(--panel);border:1px solid var(--line);border-radius:4px;padding:4px 8px}\ninput:focus,button:focus-visible,.vlist:focus-visible{outline:1px solid var(--accent);outline-offset:1px}\nh1{font:600 18px var(--sans);margin:0 0 12px;letter-spacing:-.01em}\nh2{font:600 10.5px var(--sans);text-transform:uppercase;letter-spacing:.14em;color:var(--dim);margin:0 0 10px}\nh2 a{color:inherit}h3{font:600 12px var(--sans);margin:14px 0 6px}\n\nheader{background:var(--panel);border-top:2px solid var(--accent);border-bottom:1px solid var(--line)}\n.bar{display:flex;align-items:stretch;gap:0;overflow-x:auto}\n.brand{display:flex;align-items:center;gap:6px;padding:8px 16px;border-right:1px solid var(--line);white-space:nowrap}\n.brand b{font:700 13px var(--mono);letter-spacing:.04em}.brand span{font:500 13px var(--mono);color:var(--accent)}\n.brand .ro{font:600 9.5px var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:3px;padding:1px 5px;margin-left:6px}\n.readouts{display:flex;flex:1}\n.readout{display:flex;flex-direction:column;justify-content:center;padding:6px 14px;border-right:1px solid var(--line-soft);white-space:nowrap}\n.readout .label{font:600 9px var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}\n.readout .reading{font:12px var(--mono);display:flex;align-items:center;gap:8px}\n.build.match i{color:var(--live);font-style:normal}.build.mismatch{color:var(--bad)}.build.mismatch i{font-style:normal;font-weight:700}\n.task b{color:var(--fg);font-weight:600}\n.dot{width:8px;height:8px;border-radius:50%;display:inline-block;background:var(--unavailable)}\n.dot.c-connected{background:var(--live);box-shadow:0 0 6px var(--live)}.dot.c-lost,.dot.c-failed{background:var(--bad)}.dot.c-unavailable{background:var(--uncertain)}\n.dot.c-connecting{background:var(--uncertain);animation:pulse 1s infinite alternate}\n@keyframes pulse{to{opacity:.3}}\nnav{display:flex;gap:2px;padding:0 10px;border-top:1px solid var(--line-soft)}\nnav a{color:var(--dim);padding:7px 12px 6px;text-transform:capitalize;border-bottom:2px solid transparent;font-weight:500}\nnav a:hover{color:var(--fg);text-decoration:none}nav a.on{color:var(--fg);border-bottom-color:var(--accent)}\n.banner{padding:7px 16px;font-weight:600;display:flex;gap:12px;align-items:center}\n.banner.danger{background:var(--bad);color:#fff}\n.banner.warn{background:repeating-linear-gradient(135deg,var(--uncertain) 0 14px,color-mix(in srgb,var(--uncertain) 85%,#000) 14px 28px);color:#1b1404}\n.banner.error{background:var(--panel-2);color:var(--bad);border-top:1px solid var(--bad)}\n.banner button{margin-left:auto}\n\nmain{overflow:auto;min-height:0}\n.page{padding:16px 18px 28px;animation:enter .18s ease-out}\n@keyframes enter{from{opacity:0;transform:translateY(3px)}}\n.panel{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:12px 14px}\n.toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:10px}\n.check{display:inline-flex;gap:5px;align-items:center;color:var(--dim);cursor:pointer}.check input{margin:0}\n.sep{margin-left:8px}.count{color:var(--dim);font:12px var(--mono);margin-left:auto}\n.tabs{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px;align-items:center}\n.tab{background:transparent}.tab.on{border-color:var(--accent);color:var(--fg)}\n.tab .n{color:var(--dim);margin-left:6px;font:11px var(--mono)}\n.tag{font:600 9.5px var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:3px;padding:0 4px;margin:0 4px}\ndl{display:grid;grid-template-columns:max-content 1fr;gap:3px 14px;margin:0}dt{color:var(--dim)}dd{margin:0;min-width:0;overflow-wrap:anywhere}\n.facts{margin-bottom:14px}.readings dd{display:flex;gap:8px;align-items:baseline}\n.crumbs{color:var(--dim);margin-bottom:4px}\n\ntable.grid{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--line);border-radius:6px}\n.grid th{font:600 9.5px var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--dim);text-align:left;padding:7px 10px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--panel)}\n.grid td{padding:6px 10px;border-bottom:1px solid var(--line-soft);vertical-align:top}\n.grid tr:last-child td{border-bottom:0}.link-row{cursor:pointer}.link-row:hover td{background:var(--panel-2)}\ntr.highlight td{background:color-mix(in srgb,var(--accent) 12%,transparent)}\n\n.value{font:12.5px var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.meta{font:11px var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.meta::before{display:inline-block;width:1.4ch}\n.s-live{color:var(--live)}.meta.s-live::before{content:\"●\"}\n.s-uncertain{color:var(--uncertain)}.value.s-uncertain{text-decoration:underline dotted}.meta.s-uncertain::before{content:\"◐\"}\n.s-bad{color:var(--bad)}.value.s-bad{text-decoration:line-through}.meta.s-bad::before{content:\"✕\"}\n.s-stale{color:var(--stale)}.value.s-stale{background:repeating-linear-gradient(135deg,transparent 0 4px,var(--hatch) 4px 8px)}.meta.s-stale::before{content:\"○\"}\n.s-unavailable{color:var(--unavailable)}.meta.s-unavailable::before{content:\"–\"}\n.s-constant{color:var(--constant)}.value.s-constant{font-style:italic}.meta.s-constant::before{content:\"◆\"}\n.s-group{color:var(--dim)}\n\n.variables{height:100%;display:flex;flex-direction:column;padding-bottom:12px}\n.search{flex:1;min-width:280px;max-width:640px;font-family:var(--mono);font-size:12.5px;padding:6px 10px}\n.split{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:12px}\n.listwrap{display:flex;flex-direction:column;min-height:0;background:var(--panel);border:1px solid var(--line);border-radius:6px;overflow:hidden}\n.vlist{flex:1;overflow:auto;position:relative;outline:none}\n.vspacer{position:relative}.vwindow{position:absolute;left:0;right:0;top:0}\n.row{display:grid;grid-template-columns:minmax(220px,1fr) minmax(90px,15ch) 21ch 17ch 40px minmax(110px,19ch);gap:8px;align-items:center;height:26px;padding-right:10px;border-bottom:1px solid var(--line-soft);cursor:default}\n.row:hover{background:var(--panel-2)}.row.selected{background:color-mix(in srgb,var(--accent) 13%,transparent);box-shadow:inset 2px 0 0 var(--accent)}\n.row.head{font:600 9.5px var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--dim);border-bottom:1px solid var(--line);padding-left:10px}\n.row.generated .name{opacity:.7}\n.name{font:12.5px var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center}\n.name mark{background:color-mix(in srgb,var(--accent) 35%,transparent);color:inherit;border-radius:2px}\n.twisty{display:inline-grid;place-items:center;width:18px;height:18px;flex:none;padding:0;border:0;background:none;color:var(--dim);font-size:10px}\n.type{font:11.5px var(--mono);color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.row .src{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:11px}\n.rec{padding:0;width:22px;height:18px;border:1px solid transparent;background:none;color:var(--line);font-size:11px}\n.rec:hover{color:var(--dim);border-color:var(--line)}.rec.on{color:var(--bad)}.rec.elsewhere{color:var(--dim)}\n.side{display:flex;flex-direction:column;gap:12px;overflow:auto;min-height:0}\n.detail-path{font-size:12.5px;overflow-wrap:anywhere;margin-bottom:8px;color:var(--fg)}\n.detail-value{display:flex;gap:12px;align-items:baseline;margin-bottom:10px;padding:8px 10px;background:var(--panel-2);border-radius:4px}\n.detail-value .value{font-size:20px}.detail .site{margin:3px 0}.detail button{margin-top:10px}\n.member{display:grid;grid-template-columns:minmax(0,1fr) auto auto 22px;gap:8px;align-items:center;padding:3px 0;border-bottom:1px solid var(--line-soft)}\n.member .path{font-size:11.5px}.remove{padding:0 5px;border:0;background:none;color:var(--dim)}\n.groups form input{width:110px;padding:2px 6px}\n\n.badge{display:inline-block;font:600 10.5px var(--mono);letter-spacing:.04em;padding:1px 7px;border-radius:3px;border:1px solid;text-transform:uppercase}\n.h-ok{color:var(--live);border-color:var(--live)}\n.h-fault{color:#fff;background:var(--bad);border-color:var(--bad)}\n.h-stale{color:var(--stale);border-color:var(--stale);background:repeating-linear-gradient(135deg,transparent 0 4px,var(--hatch) 4px 8px)}\n.h-unknown{color:var(--dim);border-color:var(--dim);border-style:dashed}\n.st{font:600 11px var(--mono);text-transform:lowercase}\n.st-busy,.st-pending,.st-connecting,.st-cancelling{color:var(--uncertain)}\n.st-failed,.st-error,.st-timeout,.st-lost{color:var(--bad)}.st-unavailable{color:var(--uncertain)}\n.st-done,.st-ok,.st-connected{color:var(--live)}.st-idle,.st-unknown{color:var(--dim)}\n.await code{white-space:pre-wrap}\n\n.overview{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:start}\n.overview .wide{grid-column:1/-1}\n.overview>*{animation:enter .25s ease-out backwards}.overview>:nth-child(2){animation-delay:.04s}.overview>:nth-child(3){animation-delay:.08s}.overview>:nth-child(4){animation-delay:.12s}\n.counts{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:10px}\n.count-box{border:1px solid;border-radius:5px;padding:6px 10px;display:flex;flex-direction:column}\n.count-box b{font:600 22px var(--mono)}.count-box span{font:600 9.5px var(--sans);letter-spacing:.14em;text-transform:uppercase}\n.count-box.h-fault{background:color-mix(in srgb,var(--bad) 12%,transparent);color:var(--bad)}\n.device-line{padding:3px 0}\n\n.assemblies{display:flex;flex-direction:column;gap:12px;margin-bottom:18px}\n.assembly h3{margin:0 0 10px}\n.bitgrid{display:grid;grid-template-columns:4ch repeat(8,52px) 4ch minmax(0,1fr);gap:3px;align-items:stretch}\n.bh{font:600 9.5px var(--mono);color:var(--dim);text-align:center;letter-spacing:.06em}.legend-head{text-align:left;padding-left:6px}\n.byte,.hex{font-size:11.5px;color:var(--dim);align-self:center}\n.bit{position:relative;height:34px;display:flex;flex-direction:column;align-items:center;justify-content:center;font:600 13px var(--mono);\nborder:1px dashed var(--line);border-radius:3px;color:var(--unavailable)}\n.bit small{font:9px var(--mono);color:var(--dim);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 2px}\n.bit.mapped{border-style:solid;color:var(--dim);background:var(--panel-2)}\n.bit.on{color:var(--fg)}\n.bit.mapped.on{color:var(--live);background:color-mix(in srgb,var(--live) 16%,transparent);border-color:color-mix(in srgb,var(--live) 60%,transparent);box-shadow:0 0 8px color-mix(in srgb,var(--live) 25%,transparent)}\n.bit.none{color:var(--unavailable)}\n.q-stale .bit,.q-uncertain .bit,.q-bad .bit{background-image:repeating-linear-gradient(135deg,transparent 0 4px,var(--hatch) 4px 8px)}\n.q-stale .bit.on,.q-bad .bit.on{color:var(--stale);box-shadow:none;border-color:var(--line)}\n.legend{display:flex;flex-wrap:wrap;gap:4px 12px;align-items:center;font-size:11.5px;padding-left:6px}\n.legend-item{display:inline-flex;gap:6px;align-items:baseline}.legend-item b{font:600 11px var(--mono)}\n.mapped-path{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline}\n\n.recent .entries{display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:6px}\n.entry{display:grid;grid-template-columns:14ch 9ch minmax(0,1fr);gap:10px;padding:7px 12px;border-bottom:1px solid var(--line-soft)}\n.overview .entry{padding:6px 0}\n.when{color:var(--dim);font-size:11.5px}.approx{color:var(--uncertain);margin-left:4px;cursor:help}\n.source{font:600 9.5px var(--sans);letter-spacing:.12em;text-transform:uppercase;padding-top:2px}\n.src-plc{color:var(--accent)}.src-server{color:var(--link)}.src-agent{color:var(--constant)}.src-debugger{color:var(--dim)}\n.body>div{margin:1px 0}.val{font:600 12.5px var(--mono)}\n.chips{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin-top:3px}\n.chip{display:inline-flex;align-items:baseline;gap:3px;font:11.5px var(--mono);border:1px solid var(--line);border-radius:10px;padding:0 8px;background:var(--panel-2)}\n.chip.unstable{border-style:dashed}\n.tag.lvl-info{color:var(--link);border-color:var(--link)}.tag.lvl-warn{color:var(--uncertain);border-color:var(--uncertain)}.tag.lvl-error{color:var(--bad);border-color:var(--bad)}\n.recent>button{margin-top:10px}\n\n.fatal{padding:40px;max-width:720px}.fatal h1{color:var(--bad)}\n@media (max-width:1100px){.split{grid-template-columns:minmax(0,1fr)}.side{max-height:40vh}.overview{grid-template-columns:minmax(0,1fr)}}\n`;\n\n/** The page shell; `./ui.js` builds everything from the API, so the same page works at `/` and under `/debug/`. */\nexport const html = `<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>tsPLC debug</title><link rel=\"icon\" href=\"data:,\">\n<script>if(!location.pathname.endsWith(\"/\"))location.replace(location.pathname+\"/\"+location.search+location.hash)</script>\n<style>${css}</style></head>\n<body><p class=\"empty\" style=\"padding:24px\">Loading the debugger…</p>\n<script type=\"module\" src=\"./ui.js\"></script></body></html>`;\n",
18
- "import { setTimeout as delay } from \"node:timers/promises\";\nimport type { Connection, TargetAdapter, TargetRead, TargetSample } from \"./adapter.ts\";\nimport type { DebugType } from \"./manifest.ts\";\n\n/** Why the login can't read now; `state` is what the debugger shows meanwhile. */\nexport class LoginUnavailable extends Error {\n constructor(message: string, options?: ErrorOptions & { state?: \"connecting\" | \"unavailable\" }) {\n super(message, options);\n this.state = options?.state ?? \"unavailable\";\n }\n\n readonly state: \"connecting\" | \"unavailable\";\n}\n\nexport const noLogin = \"Live values need an engineering login: run `tsplc login`.\";\n\n/** How long to wait between attempts while there is no login to read through. */\nconst retryMs = 5000;\n\nconst integerTypes = new Set([\n ...[\"SINT\", \"INT\", \"DINT\", \"LINT\", \"USINT\", \"UINT\", \"UDINT\", \"ULINT\"],\n ...[\"BYTE\", \"WORD\", \"DWORD\", \"LWORD\"],\n]);\nconst timeUnits: Record<string, number> = {\n d: 86_400_000,\n h: 3_600_000,\n m: 60_000,\n s: 1000,\n ms: 1,\n us: 0.001,\n ns: 0.000_001,\n};\n\nconst typeName = (type: DebugType) => (type.kind === \"scalar\" ? type.iec : type.kind);\n\nconst message = (error: unknown) => (error instanceof Error ? error.message : String(error));\n\n/** `16#FF`, `2#1010`, `-42`, with IEC's digit separators; beyond doubles' exact range, a string. */\nconst integer = (text: string) => {\n const radix = /^(2|8|16)#([0-9a-f_]+)$/i.exec(text);\n const digits = radix ? radix[2]!.replaceAll(\"_\", \"\") : text.replaceAll(\"_\", \"\");\n if (!radix && !/^[+-]?\\d+$/.test(digits)) return undefined;\n const value = BigInt(radix ? `0${{ 2: \"b\", 8: \"o\", 16: \"x\" }[radix[1]!]}${digits}` : digits);\n return Number.isSafeInteger(Number(value)) ? Number(value) : String(value);\n};\n\n/** `T#1h2m3s4ms`, `TIME#-1.5s`, `LTIME#5us`, in milliseconds. */\nconst duration = (text: string) => {\n const body = /^L?T(?:IME)?#(-?)(.+)$/i.exec(text);\n if (!body) return undefined;\n const parts = [...body[2]!.replaceAll(\"_\", \"\").matchAll(/(\\d+(?:\\.\\d+)?)(ms|us|ns|d|h|m|s)/gi)];\n if (parts.map(([part]) => part).join(\"\") !== body[2]!.replaceAll(\"_\", \"\")) return undefined;\n const ms = parts.reduce(\n (total, [, amount, unit]) => total + Number(amount) * timeUnits[unit!.toLowerCase()]!,\n 0,\n );\n return body[1] ? -ms : ms;\n};\n\n/** `'it$'s'` or `\"wide\"`, with IEC's `$` escapes. */\nconst quoted = (text: string) => {\n const body = /^(['\"])(.*)\\1$/s.exec(text);\n if (!body) return undefined;\n return body[2]!.replace(/\\$([0-9a-f]{2}|[$'\"lnprt])/gi, (_, code: string) => {\n if (code.length === 2) return String.fromCharCode(parseInt(code, 16));\n const named: Record<string, string> = { l: \"\\n\", n: \"\\n\", p: \"\\f\", r: \"\\r\", t: \"\\t\" };\n return named[code.toLowerCase()] ?? code;\n });\n};\n\n/**\n * A value as `read_value` returns it, in the form the debugger decodes: BOOL as a boolean,\n * numbers and TIME (in ms) as numbers, enums as their member's number (or its name when the\n * manifest doesn't list it), STRING unquoted, and arrays read whole as arrays. Undefined when the\n * text doesn't fit the type.\n */\nexport const parseLoginValue = (type: DebugType, text: string): unknown => {\n const trimmed = text.trim();\n // Typed literals such as `INT#5`; TIME's own `T#` prefix is kept.\n const untyped = trimmed.replace(/^(?!L?T(?:IME)?#)[a-z_]+#(?=.)/i, \"\");\n switch (type.kind) {\n case \"enum\": {\n const number = integer(untyped);\n if (typeof number === \"number\") return number;\n const named = /^(?:\\w+\\.)*(\\w+)(?:\\s*\\((-?\\d+)\\))?$/.exec(untyped);\n if (!named) return undefined;\n return type.members[named[1]!] ?? (named[2] === undefined ? named[1] : Number(named[2]));\n }\n case \"array\": {\n const items = /^\\[?(.*?)\\]?$/s.exec(untyped)![1]!.trim();\n if (!items) return [];\n // Only raw assembly bytes are read whole; their elements are scalars named by IEC type.\n const element = { kind: \"scalar\", iec: type.element } as const;\n const values = items.split(/\\s*,\\s*/).map((item) => parseLoginValue(element, item));\n return values.length === type.length && values.every((value) => value !== undefined)\n ? values\n : undefined;\n }\n case \"record\":\n return undefined;\n case \"scalar\":\n break;\n }\n const iec = type.iec.toUpperCase();\n if (iec === \"BOOL\") return { TRUE: true, FALSE: false, 1: true, 0: false }[untyped.toUpperCase()];\n if (integerTypes.has(iec)) return integer(untyped);\n if (iec === \"REAL\" || iec === \"LREAL\") {\n const number = Number(untyped);\n return untyped !== \"\" && !Number.isNaN(number) ? number : undefined;\n }\n if (iec === \"TIME\" || iec === \"LTIME\") return duration(trimmed);\n if (/^W?STRING\\b/.test(iec)) return quoted(trimmed) ?? trimmed;\n return trimmed;\n};\n\n/**\n * Reads through an engineering login that answers `read(expressions)` with CODESYS's own text\n * for each value: no publication is needed, and nothing is subscribed. Watched targets are polled\n * every `samplingMs`, one command per poll, and a poll that overruns delays the next by as long.\n *\n * A read fails as a whole when one expression can't be read, so a failing read is retried with\n * `probe` alone: if that fails too the login is lost; otherwise the read is split until the\n * expressions that fail are found, and those are reported bad until the next login.\n */\nexport const createLoginAdapter = (options: {\n read: (expressions: string[]) => Promise<Record<string, string>>;\n /** A target that always reads, such as the build id. */\n probe: string;\n endpoint: string;\n samplingMs?: number;\n}): TargetAdapter => {\n const samplingMs = options.samplingMs ?? 1000;\n let connection: Connection = { state: \"connecting\", since: new Date().toISOString() };\n const connectionListeners = new Set<(connection: Connection) => void>();\n const subscriptions = new Set<{\n targets: readonly TargetRead[];\n listener: (target: string, sample: TargetSample) => void;\n intervalMs: number;\n due: number;\n }>();\n /** Expressions the controller refused, with its reason, until the login is lost. */\n const rejected = new Map<string, string>();\n const controller = new AbortController();\n\n const setConnection = (state: Connection[\"state\"], error?: string) => {\n if (controller.signal.aborted) return;\n if (connection.state === state && connection.error === error) return;\n if (state !== \"connected\") rejected.clear();\n connection = { state, since: new Date().toISOString(), ...(error && { error }) };\n for (const listener of connectionListeners) listener(connection);\n };\n\n const split = async (expressions: string[]): Promise<Record<string, string>> => {\n try {\n return await options.read(expressions);\n } catch (error) {\n if (error instanceof LoginUnavailable) throw error;\n if (expressions.length === 1) {\n rejected.set(expressions[0]!, message(error));\n return {};\n }\n const half = Math.ceil(expressions.length / 2);\n return {\n ...(await split(expressions.slice(0, half))),\n ...(await split(expressions.slice(half))),\n };\n }\n };\n\n const readText = async (expressions: string[]) => {\n try {\n return await options.read(expressions);\n } catch (error) {\n if (error instanceof LoginUnavailable) throw error;\n // One expression the controller can't read fails the whole read; a lost login fails the probe too.\n await options.read([options.probe]);\n return split(expressions);\n }\n };\n\n /** Never fails: while the login can't read, every target is unavailable. */\n const read = async (targets: readonly TargetRead[]) => {\n const unique = [...new Map(targets.map((target) => [target.target, target])).values()];\n const expressions = unique\n .map(({ target }) => target)\n .filter((target) => !rejected.has(target));\n const samples = new Map<string, TargetSample>();\n let values: Record<string, string>;\n const overdue = setTimeout(\n () => setConnection(\"lost\", \"The engineering login stopped answering\"),\n 3 * samplingMs,\n );\n try {\n values = expressions.length ? await readText(expressions) : {};\n setConnection(\"connected\");\n } catch (error) {\n setConnection(error instanceof LoginUnavailable ? error.state : \"lost\", message(error));\n const receivedAt = new Date().toISOString();\n for (const { target } of unique)\n samples.set(target, {\n value: null,\n quality: \"unavailable\",\n status: message(error),\n receivedAt,\n });\n return samples;\n } finally {\n clearTimeout(overdue);\n }\n const receivedAt = new Date().toISOString();\n for (const { target, type } of unique) {\n const text = values[target];\n const refused = rejected.get(target);\n const value = text === undefined ? undefined : parseLoginValue(type, text);\n samples.set(\n target,\n value !== undefined\n ? { value, quality: \"good\", status: \"Good\", receivedAt }\n : {\n value: text ?? null,\n quality: \"bad\",\n status:\n refused ??\n (text === undefined ? \"Not returned by the login\" : `Not a ${typeName(type)}`),\n receivedAt,\n },\n );\n }\n return samples;\n };\n\n const poll = async () => {\n while (!controller.signal.aborted) {\n const started = Date.now();\n // Timers fire a little early or late; a subscription due within half an interval is read now.\n const due = [...subscriptions].filter(({ due }) => due <= started + samplingMs / 2);\n if (due.length) {\n for (const subscription of due) subscription.due = started + subscription.intervalMs;\n // Closing the debugger must not wait for an engineering worker that stopped answering.\n const stopped = Promise.withResolvers<void>();\n const stop = () => stopped.resolve();\n controller.signal.addEventListener(\"abort\", stop, { once: true });\n const samples = await Promise.race([\n read(due.flatMap(({ targets }) => targets)),\n stopped.promise,\n ]).finally(() => controller.signal.removeEventListener(\"abort\", stop));\n if (!samples || controller.signal.aborted) break;\n for (const subscription of due)\n if (subscriptions.has(subscription))\n for (const { target } of subscription.targets)\n subscription.listener(target, samples.get(target)!);\n }\n const took = Date.now() - started;\n const waiting = connection.state !== \"connected\" && connection.state !== \"connecting\";\n await delay(waiting ? retryMs : took > samplingMs ? took : samplingMs - took, undefined, {\n signal: controller.signal,\n }).catch(() => undefined);\n }\n };\n const running = poll();\n\n return {\n method: \"engineering login\",\n endpoint: options.endpoint,\n samplingMs,\n connection: () => connection,\n onConnection: (listener) => {\n connectionListeners.add(listener);\n return () => connectionListeners.delete(listener);\n },\n read,\n subscribe: (targets, listener, intervalMs = samplingMs) => {\n const subscription = { targets, listener, intervalMs, due: 0 };\n subscriptions.add(subscription);\n return () => subscriptions.delete(subscription);\n },\n close: async () => {\n controller.abort();\n subscriptions.clear();\n connectionListeners.clear();\n await running;\n },\n };\n};\n",
19
- "import { resolve } from \"node:path\";\nimport { createMonitor, type MonitorOptions, type Reading } from \"@tsplc/opcua\";\nimport type { ResolvedTsplcConfig } from \"@tsplc/config\";\nimport type { TargetAdapter, TargetRead, TargetSample } from \"./adapter.ts\";\n\ntype MonitorConfig = NonNullable<ResolvedTsplcConfig[\"monitor\"]>;\n\n/**\n * The connection the config's `monitor` section describes. Its certificate directory is relative\n * to `root`, and the password comes from `passwordEnv` in `env`.\n */\nexport const opcUaConnection = (\n monitor: MonitorConfig,\n options: { root: string; env: Record<string, string | undefined> },\n): MonitorOptions => {\n const password = monitor.passwordEnv && options.env[monitor.passwordEnv];\n if (monitor.username && !password)\n throw new Error(\n monitor.passwordEnv\n ? `Set ${monitor.passwordEnv} to the OPC UA password of ${monitor.username}.`\n : \"Configure monitor.passwordEnv for the OPC UA user.\",\n );\n return {\n endpoint: monitor.endpoint,\n namespaceUri: monitor.namespaceUri,\n certificateDirectory: resolve(options.root, monitor.certificateDirectory),\n security: monitor.securityPolicy,\n securityMode: monitor.securityMode === \"Sign\" ? \"Sign\" : \"SignAndEncrypt\",\n ...(monitor.username && password && { credentials: { username: monitor.username, password } }),\n };\n};\n\n/**\n * Reads a CODESYS controller over OPC UA, where targets are IEC symbol paths. It reads only\n * what the build publishes, so it suits a local virtual PLC; samples arrive on change.\n */\nexport const createOpcUaAdapter = (options: MonitorOptions): TargetAdapter => {\n const monitor = createMonitor(options);\n const controller = new AbortController();\n const running = monitor.run(controller.signal);\n const sample = ({ value, quality, status }: Reading): TargetSample => ({\n value,\n quality,\n status,\n receivedAt: new Date().toISOString(),\n });\n const names = (targets: readonly TargetRead[]) => targets.map(({ target }) => target);\n\n return {\n method: \"OPC UA\",\n endpoint: options.endpoint,\n samplingMs: monitor.samplingMs,\n connection: monitor.status,\n onConnection: monitor.onStatus,\n read: async (targets) =>\n new Map(\n Object.entries(await monitor.read(names(targets))).map(([target, reading]) => [\n target,\n sample(reading),\n ]),\n ),\n subscribe: (targets, listener) =>\n monitor.watch(names(targets), (target, reading) => listener(target, sample(reading))),\n close: async () => {\n controller.abort();\n await running;\n },\n };\n};\n"
20
+ "import { setTimeout as delay } from \"node:timers/promises\";\nimport type {\n\tConnection,\n\tTargetAdapter,\n\tTargetRead,\n\tTargetSample,\n} from \"./adapter.ts\";\nimport { errorMessage } from \"./errors.ts\";\nimport { parseLoginValue } from \"./login-value.ts\";\nimport type { DebugType } from \"./manifest.ts\";\n\n/** Why the login can't read now; `state` is what the debugger shows meanwhile. */\nexport class LoginUnavailable extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: ErrorOptions & { state?: \"connecting\" | \"unavailable\" },\n\t) {\n\t\tsuper(message, options);\n\t\tthis.state = options?.state ?? \"unavailable\";\n\t}\n\n\treadonly state: \"connecting\" | \"unavailable\";\n}\n\nexport const noLogin =\n\t\"Live values need an engineering login: run `tsplc login`.\";\n\n/** How long to wait between attempts while there is no login to read through. */\nconst retryMs = 5000;\n\nconst typeName = (type: DebugType) =>\n\ttype.kind === \"scalar\" ? type.iec : type.kind;\n\n/**\n * Reads through an engineering login that answers `read(expressions)` with CODESYS's own text\n * for each value: no publication is needed, and nothing is subscribed. Watched targets are polled\n * every `samplingMs`, one command per poll, and a poll that overruns delays the next by as long.\n *\n * A read fails as a whole when one expression can't be read, so a failing read is retried with\n * `probe` alone: if that fails too the login is lost; otherwise the read is split until the\n * expressions that fail are found, and those are reported bad until the next login.\n */\nexport const createLoginAdapter = (options: {\n\tread: (expressions: string[]) => Promise<Record<string, string>>;\n\t/** A target that always reads, such as the build id. */\n\tprobe: string;\n\tendpoint: string;\n\tsamplingMs?: number;\n}): TargetAdapter => {\n\tconst samplingMs = options.samplingMs ?? 1000;\n\tlet connection: Connection = {\n\t\tstate: \"connecting\",\n\t\tsince: new Date().toISOString(),\n\t};\n\tconst connectionListeners = new Set<(connection: Connection) => void>();\n\tconst subscriptions = new Set<{\n\t\ttargets: readonly TargetRead[];\n\t\tlistener: (target: string, sample: TargetSample) => void;\n\t\tintervalMs: number;\n\t\tdue: number;\n\t}>();\n\t/** Expressions the controller refused, with its reason, until the login is lost. */\n\tconst rejected = new Map<string, string>();\n\tconst controller = new AbortController();\n\n\tconst setConnection = (state: Connection[\"state\"], error?: string) => {\n\t\tif (controller.signal.aborted) {\n\t\t\treturn;\n\t\t}\n\t\tif (connection.state === state && connection.error === error) {\n\t\t\treturn;\n\t\t}\n\t\tif (state !== \"connected\") {\n\t\t\trejected.clear();\n\t\t}\n\t\tconnection = {\n\t\t\tstate,\n\t\t\tsince: new Date().toISOString(),\n\t\t\t...(error && { error }),\n\t\t};\n\t\tfor (const listener of connectionListeners) {\n\t\t\tlistener(connection);\n\t\t}\n\t};\n\n\tconst split = async (\n\t\texpressions: string[],\n\t): Promise<Record<string, string>> => {\n\t\ttry {\n\t\t\treturn await options.read(expressions);\n\t\t} catch (error) {\n\t\t\tif (error instanceof LoginUnavailable) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (expressions.length === 1) {\n\t\t\t\trejected.set(expressions[0]!, errorMessage(error));\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst half = Math.ceil(expressions.length / 2);\n\t\t\treturn {\n\t\t\t\t...(await split(expressions.slice(0, half))),\n\t\t\t\t...(await split(expressions.slice(half))),\n\t\t\t};\n\t\t}\n\t};\n\n\tconst readText = async (expressions: string[]) => {\n\t\ttry {\n\t\t\treturn await options.read(expressions);\n\t\t} catch (error) {\n\t\t\tif (error instanceof LoginUnavailable) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\t// One expression the controller can't read fails the whole read; a lost login fails the probe too.\n\t\t\tawait options.read([options.probe]);\n\t\t\treturn split(expressions);\n\t\t}\n\t};\n\n\t/** The login's text for each expression, or why it can't read; keeps `connection` current. */\n\tconst readTexts = async (\n\t\texpressions: string[],\n\t): Promise<{ texts: Record<string, string> } | { error: string }> => {\n\t\tconst overdue = setTimeout(\n\t\t\t() => setConnection(\"lost\", \"The engineering login stopped answering\"),\n\t\t\t3 * samplingMs,\n\t\t);\n\t\ttry {\n\t\t\tconst texts = expressions.length ? await readText(expressions) : {};\n\t\t\tsetConnection(\"connected\");\n\t\t\treturn { texts };\n\t\t} catch (error) {\n\t\t\tsetConnection(\n\t\t\t\terror instanceof LoginUnavailable ? error.state : \"lost\",\n\t\t\t\terrorMessage(error),\n\t\t\t);\n\t\t\treturn { error: errorMessage(error) };\n\t\t} finally {\n\t\t\tclearTimeout(overdue);\n\t\t}\n\t};\n\n\t/** A target's value from the login's text, or bad with the reason it has none. */\n\tconst parsedSample = (\n\t\t{ target, type }: TargetRead,\n\t\ttext: string | undefined,\n\t\treceivedAt: string,\n\t): TargetSample => {\n\t\tconst value = text === undefined ? undefined : parseLoginValue(type, text);\n\t\tif (value !== undefined) {\n\t\t\treturn { value, quality: \"good\", status: \"Good\", receivedAt };\n\t\t}\n\t\tconst reason =\n\t\t\ttext === undefined\n\t\t\t\t? \"Not returned by the login\"\n\t\t\t\t: `Not a ${typeName(type)}`;\n\t\treturn {\n\t\t\tvalue: text ?? null,\n\t\t\tquality: \"bad\",\n\t\t\tstatus: rejected.get(target) ?? reason,\n\t\t\treceivedAt,\n\t\t};\n\t};\n\n\t/** Never fails: while the login can't read, every target is unavailable. */\n\tconst read = async (targets: readonly TargetRead[]) => {\n\t\tconst unique = [\n\t\t\t...new Map(targets.map((target) => [target.target, target])).values(),\n\t\t];\n\t\tconst result = await readTexts(\n\t\t\tunique\n\t\t\t\t.map(({ target }) => target)\n\t\t\t\t.filter((target) => !rejected.has(target)),\n\t\t);\n\t\tconst receivedAt = new Date().toISOString();\n\t\tif (\"error\" in result) {\n\t\t\treturn new Map<string, TargetSample>(\n\t\t\t\tunique.map(({ target }) => [\n\t\t\t\t\ttarget,\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: null,\n\t\t\t\t\t\tquality: \"unavailable\",\n\t\t\t\t\t\tstatus: result.error,\n\t\t\t\t\t\treceivedAt,\n\t\t\t\t\t},\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\t\treturn new Map(\n\t\t\tunique.map((read) => [\n\t\t\t\tread.target,\n\t\t\t\tparsedSample(read, result.texts[read.target], receivedAt),\n\t\t\t]),\n\t\t);\n\t};\n\n\t/** Until the next poll: the rest of the interval, as long again after an overrun, longer without a login. */\n\tconst pauseAfter = (tookMs: number) => {\n\t\tif (connection.state !== \"connected\" && connection.state !== \"connecting\") {\n\t\t\treturn retryMs;\n\t\t}\n\t\treturn tookMs > samplingMs ? tookMs : samplingMs - tookMs;\n\t};\n\n\tconst poll = async () => {\n\t\twhile (!controller.signal.aborted) {\n\t\t\tconst started = Date.now();\n\t\t\t// Timers fire a little early or late; a subscription due within half an interval is read now.\n\t\t\tconst due = [...subscriptions].filter(\n\t\t\t\t({ due }) => due <= started + samplingMs / 2,\n\t\t\t);\n\t\t\tif (due.length) {\n\t\t\t\tfor (const subscription of due) {\n\t\t\t\t\tsubscription.due = started + subscription.intervalMs;\n\t\t\t\t}\n\t\t\t\t// Closing the debugger must not wait for an engineering worker that stopped answering.\n\t\t\t\tconst stopped = Promise.withResolvers<void>();\n\t\t\t\tconst stop = () => stopped.resolve();\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", stop, { once: true });\n\t\t\t\tconst samples = await Promise.race([\n\t\t\t\t\tread(due.flatMap(({ targets }) => targets)),\n\t\t\t\t\tstopped.promise,\n\t\t\t\t]).finally(() => controller.signal.removeEventListener(\"abort\", stop));\n\t\t\t\tif (!samples || controller.signal.aborted) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfor (const subscription of due) {\n\t\t\t\t\tif (subscriptions.has(subscription)) {\n\t\t\t\t\t\tfor (const { target } of subscription.targets) {\n\t\t\t\t\t\t\tsubscription.listener(target, samples.get(target)!);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait delay(pauseAfter(Date.now() - started), undefined, {\n\t\t\t\tsignal: controller.signal,\n\t\t\t}).catch(() => undefined);\n\t\t}\n\t};\n\tconst running = poll();\n\n\treturn {\n\t\tmethod: \"engineering login\",\n\t\tendpoint: options.endpoint,\n\t\tsamplingMs,\n\t\tconnection: () => connection,\n\t\tonConnection: (listener) => {\n\t\t\tconnectionListeners.add(listener);\n\t\t\treturn () => connectionListeners.delete(listener);\n\t\t},\n\t\tread,\n\t\tsubscribe: (targets, listener, intervalMs = samplingMs) => {\n\t\t\tconst subscription = { targets, listener, intervalMs, due: 0 };\n\t\t\tsubscriptions.add(subscription);\n\t\t\treturn () => subscriptions.delete(subscription);\n\t\t},\n\t\tclose: async () => {\n\t\t\tcontroller.abort();\n\t\t\tsubscriptions.clear();\n\t\t\tconnectionListeners.clear();\n\t\t\tawait running;\n\t\t},\n\t};\n};\n",
21
+ "import { elementaryType } from \"@tsplc/iec\";\nimport type { DebugType } from \"./manifest.ts\";\n\n/** CODESYS's `TRUE`/`FALSE`, and the digits a BOOL may also read as. */\nconst booleans: Record<string, boolean> = {\n\tTRUE: true,\n\tFALSE: false,\n\t\"1\": true,\n\t\"0\": false,\n};\n\nconst radixPrefixes: Record<string, string> = { 2: \"0b\", 8: \"0o\", 16: \"0x\" };\n\nconst timeUnits: Record<string, number> = {\n\td: 86_400_000,\n\th: 3_600_000,\n\tm: 60_000,\n\ts: 1000,\n\tms: 1,\n\tus: 0.001,\n\tns: 0.000_001,\n};\n\n/** IEC's `$` escapes by letter; `$$`, `$'` and `$\"` stand for themselves. */\nconst stringEscapes: Record<string, string> = {\n\tl: \"\\n\",\n\tn: \"\\n\",\n\tp: \"\\f\",\n\tr: \"\\r\",\n\tt: \"\\t\",\n};\n\n/** Typed literals such as `INT#5`, without their type; TIME's own `T#` prefix is kept. */\nconst withoutTypePrefix = (text: string) =>\n\ttext.replace(/^(?!L?T(?:IME)?#)[a-z_]+#(?=.)/i, \"\");\n\n/** `16#FF`, `2#1010`, `-42`, with IEC's digit separators, as a BigInt literal. */\nconst bigIntLiteral = (text: string) => {\n\tconst [, radix, digits] = /^(2|8|16)#([0-9a-f_]+)$/i.exec(text) ?? [];\n\tif (radix !== undefined && digits !== undefined) {\n\t\treturn `${radixPrefixes[radix]}${digits.replaceAll(\"_\", \"\")}`;\n\t}\n\tconst decimal = text.replaceAll(\"_\", \"\");\n\treturn /^[+-]?\\d+$/.test(decimal) ? decimal : undefined;\n};\n\n/** An integer literal; beyond doubles' exact range, a string. */\nconst integer = (text: string) => {\n\tconst literal = bigIntLiteral(text);\n\tif (literal === undefined) {\n\t\treturn undefined;\n\t}\n\tconst value = BigInt(literal);\n\treturn Number.isSafeInteger(Number(value)) ? Number(value) : String(value);\n};\n\nconst real = (text: string) => {\n\tconst number = Number(text);\n\treturn text !== \"\" && !Number.isNaN(number) ? number : undefined;\n};\n\n/** `T#1h2m3s4ms`, `TIME#-1.5s`, `LTIME#5us`, in milliseconds. */\nconst duration = (text: string) => {\n\tconst [, sign, body] = /^L?T(?:IME)?#(-?)(.+)$/i.exec(text) ?? [];\n\tif (body === undefined) {\n\t\treturn undefined;\n\t}\n\tconst units = body.replaceAll(\"_\", \"\");\n\tconst parts = [...units.matchAll(/(\\d+(?:\\.\\d+)?)(ms|us|ns|d|h|m|s)/gi)];\n\tif (parts.map(([part]) => part).join(\"\") !== units) {\n\t\treturn undefined;\n\t}\n\tconst ms = parts.reduce(\n\t\t(total, [, amount, unit]) =>\n\t\t\ttotal + Number(amount) * timeUnits[unit!.toLowerCase()]!,\n\t\t0,\n\t);\n\treturn sign ? -ms : ms;\n};\n\n/** `'it$'s'` or `\"wide\"`, with IEC's `$` escapes. */\nconst quoted = (text: string) => {\n\tconst [, , body] = /^(['\"])(.*)\\1$/s.exec(text) ?? [];\n\treturn body?.replace(/\\$([0-9a-f]{2}|[$'\"lnprt])/gi, (_, code: string) =>\n\t\tcode.length === 2\n\t\t\t? String.fromCharCode(parseInt(code, 16))\n\t\t\t: (stringEscapes[code.toLowerCase()] ?? code),\n\t);\n};\n\n/** A member's number, or the name the login gave when the manifest doesn't list it. */\nconst enumValue = (\n\ttype: Extract<DebugType, { kind: \"enum\" }>,\n\ttext: string,\n) => {\n\tconst number = integer(text);\n\tif (typeof number === \"number\") {\n\t\treturn number;\n\t}\n\t// `E_Bin.Present`, `Present`, or a member the manifest lacks with its number: `Missing (7)`.\n\tconst [, name, value] =\n\t\t/^(?:\\w+\\.)*(\\w+)(?:\\s*\\((-?\\d+)\\))?$/.exec(text) ?? [];\n\tif (name === undefined) {\n\t\treturn undefined;\n\t}\n\treturn type.members[name] ?? (value === undefined ? name : Number(value));\n};\n\n/** Only raw assembly bytes are read whole; their elements are scalars named by IEC type. */\nconst arrayValue = (\n\ttype: Extract<DebugType, { kind: \"array\" }>,\n\ttext: string,\n) => {\n\tconst items = text.replace(/^\\[/, \"\").replace(/\\]$/, \"\").trim();\n\tif (!items) {\n\t\treturn [];\n\t}\n\tconst values = items\n\t\t.split(/\\s*,\\s*/)\n\t\t.map((item) => scalarValue(type.element, item));\n\treturn values.length === type.length &&\n\t\tvalues.every((value) => value !== undefined)\n\t\t? values\n\t\t: undefined;\n};\n\nconst scalarValue = (iec: string, text: string): unknown => {\n\tconst untyped = withoutTypePrefix(text);\n\tconst name = iec.toUpperCase();\n\tswitch (elementaryType(name)?.family) {\n\t\tcase \"bool\":\n\t\t\treturn booleans[untyped.toUpperCase()];\n\t\tcase \"integer\":\n\t\tcase \"bits\":\n\t\t\treturn integer(untyped);\n\t\tcase \"real\":\n\t\t\treturn real(untyped);\n\t\tcase \"duration\":\n\t\t\treturn duration(text);\n\t}\n\tif (/^W?STRING\\b/.test(name)) {\n\t\treturn quoted(text) ?? text;\n\t}\n\treturn text;\n};\n\n/**\n * A value as `read_value` returns it, in the form the debugger decodes: BOOL as a boolean,\n * numbers and TIME (in ms) as numbers, enums as their member's number (or its name when the\n * manifest doesn't list it), STRING unquoted, and arrays read whole as arrays. Undefined when the\n * text doesn't fit the type.\n */\nexport const parseLoginValue = (type: DebugType, text: string): unknown => {\n\tconst trimmed = text.trim();\n\tswitch (type.kind) {\n\t\tcase \"enum\":\n\t\t\treturn enumValue(type, withoutTypePrefix(trimmed));\n\t\tcase \"array\":\n\t\t\treturn arrayValue(type, withoutTypePrefix(trimmed));\n\t\tcase \"record\":\n\t\t\treturn undefined;\n\t\tcase \"scalar\":\n\t\t\treturn scalarValue(type.iec, trimmed);\n\t}\n};\n",
22
+ "import {\n\tcreateMonitor,\n\tmonitorConnection,\n\ttype MonitorOptions,\n\ttype Reading,\n} from \"@tsplc/opcua\";\nimport type { ResolvedTsplcConfig } from \"@tsplc/config\";\nimport type { TargetAdapter, TargetRead, TargetSample } from \"./adapter.ts\";\n\n/** The config's `monitor` connection, with the user's password from `passwordEnv` in `env`. */\nexport const opcUaConnection = (\n\tmonitor: NonNullable<ResolvedTsplcConfig[\"monitor\"]>,\n\toptions: { root: string; env: Record<string, string | undefined> },\n): MonitorOptions => {\n\tconst password = monitor.passwordEnv\n\t\t? options.env[monitor.passwordEnv]\n\t\t: undefined;\n\tif (monitor.username && !password) {\n\t\tthrow new Error(\n\t\t\tmonitor.passwordEnv\n\t\t\t\t? `Set ${monitor.passwordEnv} to the OPC UA password of ${monitor.username}.`\n\t\t\t\t: \"Configure monitor.passwordEnv for the OPC UA user.\",\n\t\t);\n\t}\n\treturn monitorConnection(monitor, {\n\t\troot: options.root,\n\t\tpassword: password ?? null,\n\t});\n};\n\n/**\n * Reads a CODESYS controller over OPC UA, where targets are IEC symbol paths. It reads only\n * what the build publishes, so it suits a local virtual PLC; samples arrive on change.\n */\nexport const createOpcUaAdapter = (options: MonitorOptions): TargetAdapter => {\n\tconst monitor = createMonitor(options);\n\tconst controller = new AbortController();\n\tconst running = monitor.run(controller.signal);\n\tconst sample = ({ value, quality, status }: Reading): TargetSample => ({\n\t\tvalue,\n\t\tquality,\n\t\tstatus,\n\t\treceivedAt: new Date().toISOString(),\n\t});\n\tconst names = (targets: readonly TargetRead[]) =>\n\t\ttargets.map(({ target }) => target);\n\n\treturn {\n\t\tmethod: \"OPC UA\",\n\t\tendpoint: options.endpoint,\n\t\tsamplingMs: monitor.samplingMs,\n\t\tconnection: monitor.status,\n\t\tonConnection: monitor.onStatus,\n\t\tread: async (targets) =>\n\t\t\tnew Map(\n\t\t\t\tObject.entries(await monitor.read(names(targets))).map(\n\t\t\t\t\t([target, reading]) => [target, sample(reading)],\n\t\t\t\t),\n\t\t\t),\n\t\tsubscribe: (targets, listener) =>\n\t\t\tmonitor.watch(names(targets), (target, reading) =>\n\t\t\t\tlistener(target, sample(reading)),\n\t\t\t),\n\t\tclose: async () => {\n\t\t\tcontroller.abort();\n\t\t\tawait running;\n\t\t},\n\t};\n};\n"
20
23
  ],
21
- "mappings": "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",
22
- "debugId": "19B08BFA048A0C5264756E2164756E21",
24
+ "mappings": "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",
25
+ "debugId": "D1ADCD561935AA0C64756E2164756E21",
23
26
  "names": []
24
27
  }