Release Notes¶
This page provides release notes for the Zelos App and the Zelos SDK.
26.0.10
Summary¶
Zelos AI reads any file you attach, takes dictation and fixes a crashed extension for you. Live plots load up to 10 times faster. A new title bar keeps Home, Ask Zelos, Help and updates one click away, and panels can now come from extensions in the marketplace.
Added¶
- Attach Files to Zelos AI: Attach images, PDFs or any other file to a message. Select the paperclip, or paste or drop the file on the chat box. Drop in a file such as a CAN database, and Zelos AI can set up an extension with it. Learn more →
- Dictate to Zelos AI: Select the microphone, or hold
Spacein the chat box, and speak. Your words appear where the cursor is. - Zelos AI Fixes Extensions: When an extension crashes, Ask AI on the alert opens Zelos AI with the extension's log attached. After an install, Ask AI asks Zelos AI to set it up. Zelos AI changes the configuration and restarts the extension itself, then tells you what it changed. It can also update, reinstall and uninstall extensions, and read their README. Learn more →
- New Title Bar: Home, the workspace name, Undo, Redo, Ask Zelos (
Cmd/Ctrl+L) and Help sit in the title bar. The workspace name opens Rename, Pin to Home and your recent workspaces. Help holds the documentation, how-to guides, release notes, the guided tour and Report a problem. Learn more → - Updates in the Background: Zelos downloads updates while you work. When one is ready, choose Restart to update in the title bar. The restart waits for any trace save or upload to finish. On Linux, Update appears when a newer version is out. Learn more →
- Notifications: While Zelos is in the background, it notifies you when Zelos AI replies or needs your approval, a trace finishes saving or uploading, an extension crashes or an agent drops. Turn them off in Settings > Notifications. Zelos also says when a remote agent stops answering, and when it comes back. Learn more →
- Change a Panel's View: Change to, in a panel's menu, switches a panel to another view, such as a Plot to a State panel, and keeps its signals, size and title. Open as, on a right-click in the signal tree, opens the panel you choose. Learn more →
- Y Axis Number Format: Plot panels have a Y axis number format setting: Auto, Decimal or Scientific. Auto switches to scientific notation for very small values, so a 378 ns rise time reads
3.778e-7instead of0.00000038. Learn more → - Panels from Extensions: An extension from the marketplace can add its own panels. They appear in Add Panel like any other panel: drop signals on one, resize it, export its data and save it in a layout. Zelos AI can add them and set their options. A saved layout that holds a panel from an extension you have not installed shows a button that opens the extension, so you can install it. Learn more →
- Install Only What You Want: When an extension ships more than one part, the arrow on Install offers Choose what to install…, so you can pick only the parts you need. Change what's installed…, in the Uninstall menu, changes the choice later, and updates keep it. Learn more →
- Choose Extras: Some extensions offer extras, optional add-ons such as support for one kind of adapter. Choose what to install… lists them under Agent runtime, unticked, each with a line on what it enables. Updates keep the ones you chose. Zelos AI knows what each extra enables, so it can offer the one you need. Learn more →
- Set Up on First Launch: A new user picks what they're working with, and Zelos AI sets it up while they take the guided tour. Learn more →
- Offer Extras in Your Extension: Developers can declare extras in
extension.toml, each with a one-line description of what it enables. Learn how → - Build Your Own Panels: Developers can add panels to their own extensions. Create Extension offers Agent, Tab and Panel, in any combination. Learn how →
- System Title Bar on Linux: Settings > Appearance > Use the system title bar uses your desktop's own window frame. Toggle Full Screen is in the command palette on every platform. Learn more →
Changed¶
- Opens Faster: Zelos opens about half a second sooner and is ready for live data in a third of the time.
- Faster Plots: Live plots load up to 10 times faster and no longer slow down as a session grows. Plots of recorded traces load about twice as fast.
- Smoother Live Views: Live views use up to 43% less CPU, and 16 live plots draw about 50% more frames a second. Dense live plots scroll smoothly, and zooming a Log panel over a trace no longer stutters.
- Panels Follow the Data: Dropping or double-clicking a signal opens the panel its type calls for. Log lines open a Log panel, numbers a Plot, states a State panel, and text a Raw panel. While you drag, the preview says which panels a drop will create, or why a panel can't take it. Learn more →
- Guided Tour: The tour runs on its own, so your workspace stays exactly as you left it. It takes fewer clicks, and you start it from Help > Take the tour. Learn more →
- Back Where You Left Off: Reopen one of the last 10 workspaces you left, and its undo history, hidden plot series and table searches are as you left them. On first launch, the window fills the screen.
- Log Panel: The Source column shows which device each line came from, such as
Serial/dut/dcdc. A message with several lines, such as a stack trace, shows every line. Learn more → - Action Panels: Fields fill columns with Execute beside them, and results show in a table you can export. Each run shows Passed, Failed or Error and when it finished. Learn more →
- Layout Search: Search finds a layout by its tags and by who created or last edited it. The layout list opens faster when your team has many layouts. Learn more →
- Extension Settings: Lists in an extension's settings are easier to manage: drag an item to reorder it. Settings ask before they close with unsaved changes, and Uninstall asks first. Learn more →
- Panels Moved to Extensions: The CAN and Packet panels now come from the CAN and Packet extensions in the marketplace, as CAN Bus Monitor and Packet List. A saved layout that holds one shows a button that opens the extension until you install it. Its signals and options are kept. Learn more →
Fixed¶
- Zelos runs on Windows without the Microsoft Visual C++ Redistributable. A new Windows machine used to show Something Went Wrong on first launch until you installed it.
- During playback at the live edge, plots keep drawing new data. They used to empty from the right as playback went on.
- Zelos uses less memory during long live sessions.
- If the window runs out of memory, Zelos reloads it instead of leaving it blank.
- On Windows, if an update can't restart Zelos, Zelos stays open and says so.
- After an update, What's New waits until you sign in, and shows each release's own date.
- Zelos starts on machines where it can't write its log files.
- On Linux with Wayland, double-clicking a
.trzfile opens it. - Extensions stop cleanly when you quit. On Windows, a stopped extension gets time to shut down, and a leftover extension no longer keeps Zelos from starting again.
- Extensions can use
sshwith keys from an SSH agent, such as 1Password or Secretive. On Windows,sshstarted by an extension runs. - Long-running extension actions, such as a device scan, no longer stop after 30 seconds.
- An install or update that is cut off no longer deletes the installed version and its settings.
- Installing an extension that needs a newer Zelos says to update.
- Links in an extension's README go where they point.
- Create Extension asks for a name that starts with a letter and uses single hyphens, so the new extension's code runs.
- After you restart an extension with an updated DBC file, panels show the new value names at once.
- Plot hover reaches every sample on a steep edge, including the peak.
- Colored log output shows correctly in the Log panel, including 256-color and truecolor, and stray terminal codes no longer show as text.
- The Log panel ranks and colors Zephyr and ESP-IDF log levels, such as
inf,dbgandE, like their long forms. - Log panel search highlights matches in the Level column and across a change of color, and keeps the spaces around a match.
- The Time column in Log and Raw panels shows the whole timestamp, and the newest row no longer hides behind the scrollbar.
- Table, Log and Raw panels that follow the newest row no longer stop following on their own.
- Closing a layout's last tab closes the layout. It used to leave an unsaved change that replaced the layout with one empty tab.
- Fit all includes history recorded before a source connected.
- Pressing
Escto close a dialog no longer returns a paused tab to live. - Double-clicking a signal tree row left of its name adds the signal once, instead of three times.
- In the command palette, items with the same name select one at a time, and each page opens with its first item highlighted.
- Exporting a large panel no longer runs out of memory. A cancelled or failed export leaves an existing file as it was.
- Editing a panel with over a thousand signals no longer freezes Zelos.
- Extension settings show only the errors that apply to your choices, and a failed Save takes you to the field to fix.
- Action pickers show each choice's full name, and search finds a choice by the name it shows.
- Zelos AI can read long stretches of busy CAN traffic instead of failing.
- On the Free plan, Add agent says when no Zelos agent answered at an address, instead of asking you to upgrade.
- A feature that needs a Team or Enterprise plan tells you to join your team's organization when you're not in one, instead of to upgrade.
- When sign-in can't reach Zelos, it says why and what to do.
- Renaming in place saves when you click or tab away.
- Closing a dialog returns focus to where it was.
- Secondary text in the light theme is easier to read.
- Opening or closing a sidebar section moves only its neighbor, and a search opens a collapsed section it filters.
- Home's lists scroll past five rows instead of cutting off.
- Layout tabs follow a quick trackpad flick smoothly.
- In notebooks, editing a parameter marks cells out of date, and a decimal parameter such as
3.0stays a decimal. - In dark mode, notebook charts use the app's colors, and an HTML export's tables and charts stay readable.
- Zelos AI's notebook charts work without installing extra packages.
A much more capable Zelos AI that moves a whole layout to another data source in one step, and faster plots, especially with hundreds of signals.26.0.9
Summary¶
Added¶
Changed¶
Option / Alt to scroll the panel instead; a hint shows the key the first time. Layouts that fit the window work as before. Learn more →Fixed¶
Counter signals.04e0_BMU00_InfoMessage.SERIAL instead of SERIAL, and sorting by Message places it right after its message.tcp, udp, icmp and ports keep matching traffic labeled V2GTP, SDP or HomePlug AV.
AI debugging your extension(s), dedicated CAN and Packet panels.26.0.8
Summary¶
Added¶
Fixed¶
Smoother Action panels, clearer legend chips, cleaner saved layouts, a signed Windows installer, and a fix for a launch error some accounts saw after updating.26.0.7
Summary¶
Changed¶
Fixed¶
Trace sharing is here. Save a recording to Zelos Cloud, send your team a link, and explore it together in Zelos. No more passing large trace files around. New Notebooks turn investigations into repeatable analyses you can publish through Zelos Cloud. A new Cloud library, a new Home, and a much more capable Zelos AI bring everything together.26.0.6
Summary¶
Added¶
.trz files into Zelos to open them together.Changed¶
Cmd+\ / Ctrl+\, and open AI Chat with Cmd+L / Ctrl+L. They used to be Cmd+B and Cmd+I, which are bold and italic in the notebook editor. App shortcuts now work inside notebooks, Python cells, and app extensions; Cmd+K / Ctrl+K opens the command palette from any tab, even while typing. Keyboard shortcuts →Fixed¶
true / false in plot tooltips and measurements instead of an empty value.
This is one of our biggest updates yet: Zelos AI, redesigned sidebars, layout version history, new State and Raw panels, richer Plot readouts, and many more panel controls.26.0.5
Summary¶
Added¶
Cmd+I / Ctrl+I. Zelos understands your agents, traces, panels, time range, and cursor. It can find signals, inspect values, summarize ranges, detect crossings, and evaluate checks across live or recorded data. It can also build panels and tabs, control the workspace, and run enabled actions with confirmation. Conversations are saved for later. Zelos AI is rolling out in phases to select users first, then everyone, so it may not appear immediately after updating. Open AI Chat →Changed¶
Fixed¶
This release introduces App Extensions, a new extension surface for building rich, custom workflows directly inside the Zelos desktop app. Extensions can now provide full APP tabs for dashboards and purpose-built tools, alongside major improvements to workspace history, panel display controls, layout editing, search, and large-workspace performance.26.0.4
Summary¶
Added¶
Cmd+Z / Ctrl+Z and Cmd+Shift+Z / Ctrl+Shift+Z. The command palette shows the next undo/redo action when history is available. Learn more →Changed¶
signal_2 appears before signal_10.Fixed¶
This release adds a Command Palette for instant access to any action in the app, along with trace re-export, multi-file open, and automatic segment expansion. It also includes a redesigned plot tooltip, improved measurement tool, and various panel sizing and UI refinements.26.0.2
Summary¶
Added¶
Cmd+K / Ctrl+K to quickly search and run any action across the app — playback controls, workspace management, layouts, settings, extensions, and more. Includes keyboard shortcut hints and fuzzy search. Learn more →.trz file. Supports time-range selection and merging multiple open traces into a single output..trz files at once.Changed¶
Fixed¶
This release introduces a brand-new timeline and playback experience for live and trace workflows. You can now navigate with a shared cursor across any panel, compare traces more easily with 26.0.1
Summary¶
ABS/REL modes, and inspect data faster in any workflow.Added¶
Esc shortcut)ABS/REL):
REL mode aligns traces at t=0 for side-by-side run comparisonABS mode preserves wall-clock timestamps for real-world event correlationChanged¶
Fixed¶
This release introduces multi-trace and multi-agent support. You can now open multiple trace files simultaneously, connect to multiple live agents, and compare data across them in the same panels.26.0.0
Summary¶
Added¶
flight_test_001:agent::motor/status.rpm)
Changed¶
Fixed¶
This release introduces a major redesign of the application with a new Extension Marketplace, improved navigation with redesigned sidebars, and enhanced plot panel capabilities. Key highlights include the ability to browse and install extensions directly from the app, multi-select signals for easier plot creation, and improved user feedback throughout. The layout has been completely reimagined with dedicated sections for connections and layouts, making it easier to manage your workspace.25.0.22
Summary¶
Added¶
Changed¶
Fixed¶
25.0.21
Added¶
Settings -> General -> Memory Limit to enforce a particular limitChanged¶
Fixed¶
25.0.20
Added¶
Changed¶
Fixed¶
25.0.19
Added¶
Changed¶
Fixed¶
25.0.17
Added¶
25.0.16
Fixed¶
25.0.15
Added¶
25.0.14
Added¶
Fixed¶
25.0.13
Added¶
25.0.12
Fixed¶
25.0.11
Fixed¶
25.0.9
Added¶
Fixed¶
25.0.8
Fixed¶
25.0.7
Added¶
Changed¶
25.0.6
Fixed¶
25.0.5
Changed¶
25.0.4
Fixed¶
25.0.2
Fixed¶
25.0.1
Fixed¶
25.0.0
Changed¶
Fixed¶
24.1.11
Added¶
Changed¶
Fixed¶
24.1.10
Added¶
ctrl-t new tabctrl-w close tabctrl-[1-9] switch to tabctrl-shift-[ previous tabctrl-shift-] next tabalt-left-arrow previous tabalt-right-arrow next tab
24.1.9
Fixed¶
0.0.13
Added¶
hidden=Truekeeps an action out of the app's action list while it stays a Zelos AI tool and runs by name:@action("Auto Configure", standalone=True, hidden=True). For actions a config form calls through its schema, or ones only the AI should reach for.agent.query()can wait for data. Passmin_samplesandtimeout: the query repeats until every signal has at leastmin_samplessamples sincestart, then returns. Pasttimeoutit raisesQueryTimeout, naming each signal still short.- On macOS, an extension stops when its agent exits, as it already did on Linux and Windows. An agent that crashed or was force-quit used to leave its extensions running and holding their hardware.
Changed¶
@action(...)rejects a keyword it does not know with aTypeError, instead of dropping it. A misspelt declaration, or one from a newer SDK than the one installed, used to pass silently and the action simply kept its default behavior.- Live
within_durationandfor_durationwaits judge every sample logged during the wait, from the wait's start to its deadline. Awithin_durationused to pass at once on a sample logged before it started, and either wait could miss a spike between two polls. A wait that sees no samples fails withno_data. Start the wait before the action whose effect it checks. - Python log records reach Zelos whole, at their level.
TraceLoggingHandlerwrites the formatted record, sologger.exception()keeps its traceback andstack_infoits stack. A custom level lands on the standard level at or below it.
Fixed¶
init(url="host:port")connects. A target without a scheme, from the argument orZELOS_AGENT_URL, gets one, asconnect()and the CLI already gave it; the raw string used to go to the gRPC client, which never connected and never said so. A target that cannot be parsed raisesConnectionTargetErrorfrominit().TraceSet.series(frame, path)works again. It read column metadata offframe.columns, which 0.0.12 made the column labels; it readsframe.metanow.agent.export()with a relative path writes where you expect. The agent resolved it in its own working directory and left a.tmpthere while the SDK reported success. With a local agent the SDK now resolves it against your script's working directory, and with a remote one it asks for an absolute path.- Two unnamed
init(actions=True)processes no longer collide silently. The agent refuses the second stream withALREADY_EXISTS, and the SDK warns once (RuntimeWarning) that its actions are not registered, naminginit(name=...)as the fix. - A
Nonein the firstlog()no longer raises. The inferred schema leaves aNonefield out, since it has no type to infer, and aNonefor a field the schema lacks is skipped. A later value for that field still needsadd_event(). zelos-sdk[notebook]installstzdata, soto_pandas()builds its zone-aware index on a machine with no OS zone database, such as a slim container or Windows.- Names that silently lost trace data are refused.
add_event()rejects a field namedtime_ns, the time column's name, and two event or field names that differ only in case, which the trace store matches as one and then drops the whole batch for. The 128-byte name limit is gone: a name of any length is accepted, andsanitize_name()returns it at full length. The limit came from a store that keyed Parquet paths on names, which the id-addressed store replaced. 0.0.13a0 shipped an interim that cut a long name to a prefix plus a digest; this supersedes it. The legacy trace writer also drops a refused batch's cache entries, so the batches after it still land. TraceReader.query()returns exact times, and all the rows. Atime_nscolumn (integer epoch nanoseconds) followstime_s, and rows come back intime_nsorder. The legacy engine deduplicated on float seconds, which merged rows 1 ns apart whose values matched: a console log written one line per nanosecond read back as a fraction of its rows.time_range()returnsNoneon a trace with no rows instead of raising, andTraceSourceCache.get_value(),get_time_ns(),has_event()andevent_field_names()exist on the Python class as the stub said.load_config()readsdependenciesbranches. A schema with no$schemavalidates as Draft 7, so a branch'srequiredfields hold; the branch a present property selects gets its defaults; and an array is never padded up tominItemsfrom itsitemsschema, so{"ports": []}loads as no ports.- A standalone action returns as soon as its result is written. A thread it leaves running, such as a pool worker or a blocked read, no longer holds the caller until the action's timeout. Its
atexithandlers still run. - Actions: declared defaults reach the callable, a mismatched name warns, and a failed action logs at debug. A caller that omits an optional field runs with its
default=, validated like a supplied value.init(name=..., actions=True)warns once whenACTION_PREFIXor the manifest'snamespell the name differently, since config-form actions resolve by the manifest name. A failed action logs at debug underzelos_sdk.actions.core; the caller already receives the error. - Live reads cover every segment of a path that spans a restart.
latest()no longer raisesNoDatabeside a recent sample from before the restart, andquery()returns one column per signal, soframe[path]works.at()andwindow()read every segment too. - An extension whose agent is gone exits at once, instead of up to 5 seconds later.
zelos_sdk.validate_suiteexists, andfrom zelos_sdk.actions import *works. Both used to raise. The pytest plugin registerscheck_config, so--strict-markersaccepts it.
Notebook code is pandas code. A Units convert, and a unit never lies: where the SDK cannot know a result's unit, the result has none, and the numbers are always pandas' numbers. On our notebook coding eval, production gpt-6-luna's first-attempt cells went from 73% correct to 95 of 95. Most 0.0.11 code runs unchanged. Three spellings change meaning:0.0.12
SignalFrame and a SignalSeries now answer to pandas' name for everything they do natively, and mean what pandas means by it, so a cell written the way you would write it for a DataFrame runs. A pandas name they don't have raises an error naming the .to_pandas() call that does.Added¶
gt/lt/eq/…, isin, astype, fillna, replace, where, clip, shift (also freq=), rolling("1s"), resample("1s").mean(), describe(), quantile, idxmax, value_counts, reindex, asof, corr (spearman without scipy), and add/sub/mul/div with fill_value=. Masks combine with &, |, ^ and ~, and a series slices by time: speed["+10s":"+20s"]. Read more.frame[label] = series and assign() add a column that keeps its unit. frame[mask], iloc and loc select rows, and frame.iloc[-1] is one row. groupby, corr, index, dtypes, shape, to_numpy(), fillna(), rename(columns=) and SignalFrame.from_pandas() round out the hand-off. Read more.power.to("kW"), energy.to("Wh"), current.integrate().to("Ah"), SI prefixes, and the units vehicle and battery catalogs use. V + mV reads in V. A degC reading converts to degF with its offset, and a difference of readings is a ΔdegC that converts by scale alone.runs() turns a boolean series into one row per event: start, end, duration, samples, and whether both ends were recorded. min_samples= and min_duration= keep the long ones: (speed == 0).runs(min_duration="2s").rate() is the change per second between neighboring samples, in unit/s.frame["pack_voltage"], catalog["motor_torque"], and catalog.match("torque") all name what you meant.np.sqrt(series), np.isfinite(series) and np.cumsum(series) return series on the same time axis, with the unit they imply.submit_text= relabels an action's Execute button: @action("Flash Firmware", submit_text="Flash").read_only=True marks an action that changes nothing, such as one that lists adapters. Zelos AI runs it without asking first: @action("Detect Adapters", read_only=True).zelos_sdk.agent_url() returns the agent URL init() settled on, or None before init().TraceLoggingHandler takes an existing TraceSource, so log records land on the source an extension already owns. source_name= still works.TraceReader reports each event's event_type.schemas.CanFrame, the zelos.can.frame.v1 schema for undecoded CAN frames.Changed¶
frame.signals is a SignalCatalog, the same object agent.signals() returns, with keys(), values() and items(). Iteration, len(), and int and slice indexing are unchanged.frame.columns is the column labels, as in pandas, and iterating a frame yields labels. The column metadata is frame.meta.T * 2, -T, abs(T) and T.sum() of a temperature reading keep their numbers and drop the unit, and so does multiplying or dividing by a list or array. A number keeps the unit: power * 0.001 is still in W, so use .to("kW").v × 1000, torque < 0), and diff, abs, cumsum, isna, notna and negation name themselves.f"{v:.2f}" formats the bare number; f"{v}" and print(v) still show the unit.sum() is an int, and series == "RUN" compares sample by sample.plot() fits the y-axis to the data, as the app's plot panels do; zero=True restores the baseline. The legend sits on top and wraps long names.ffill(), dropna(), resample()) evaluates the samples the frame holds, not the stored ones it was reshaped from.schema_version 3, and either loads back as a suite.Deprecated¶
frame.column_names — use frame.columns.Fixed¶
series == "RUN" returned False, Python's identity fallback, instead of comparing samples.integrate() and derivative() computed in float epoch seconds, about 1 µs of resolution; they now work in nanosecond offsets.t - t.mean() of a temperature read degC; it is a ΔdegC.frame[signal] raised for its own signals.Timestamp in US/Eastern, raised "time must be a datetime".Upgrade notes¶
# 1. frame.columns is labels now; the metadata moved.
[c.signal for c in frame.columns] # before
[c.signal for c in frame.meta] # after
# 2. Iterating a frame yields labels; the Signals are in frame.signals.
for signal in frame: ... # before
for signal in frame.signals: ... # after
# 3. Units come back from pandas only when you name them.
SignalFrame.from_pandas(df, units=frame.signals)
The read side of the SDK — everything you do after the data is recorded — is now one surface. Everything you already wrote keeps working: every old spelling is kept as a deprecated alias that warns once. The behavior changes below are the exceptions, and each one replaces a result that was quietly wrong. Each of these still works and raises one Kept without a warning: the Three one-line fixes cover almost every migration: If you combine columns from different messages, add 0.0.11
connect() returns a handle that browses the catalog, queries live and recorded data, computes on unit-carrying series, charts, checks invariants, and re-opens .trz files, with one glob grammar and one time grammar across every call. It is the surface Zelos Notebooks run on.Added¶
connect() — one entry point for a running agent. It verifies the connection before returning, reads ZELOS_AGENT_URL when given no argument, and works as a context manager. Read more.SignalFrame — agent.query(paths, start=…) returns a frame that is one row per distinct timestamp, one column per signal, and null wherever a signal had no sample. ffill(), dropna(), between(), resample(), head(), rename(), short_names() and describe() operate on it directly. Read more.SignalSeries carries its unit through arithmetic. voltage * current arrives as W, .integrate() over time gives J, and power / current cancels back to V. Adding mismatched units raises instead of lying, and reductions return a NamedScalar that prints 3.629 V.plot() on a frame or a series emits Vega-Lite. It renders inline in the app, offline in an exported HTML page, and in any Jupyter viewer — with nothing added to dependencies.* and ? expand against the catalog everywhere a path is accepted: match(), query(), latest(), at(), window() and export()."-30s" is a point on the clock, "30s" is a length. ISO 8601 strings, datetime and timedelta are accepted wherever they fit.agent.check.that(lhs, op, rhs) reports a verdict instead of raising, so a suite always runs to completion. Every result carries its evidence — the first violating sample on a failure, the closest approach on a pass — with a timestamp. agent.check.count() measures without judging. Read more.CheckResults.raise_if_failed() raises AssertionError listing every check that did not pass, each with its predicate, window and evidence. For a single check, assert agent.check.that(...) — a result is truthy when it passed.agent.window() returns a ReplayWindow — the opening snapshot plus one entry per change — for states and events, where a query would return thousands of rows repeating one string.agent.watch() streams live values on an interval, with a deadline.agent.export() saves a window to a .trz file, and .open() re-reads it with the same calls you used against the agent.Agent, SignalCatalog, SignalFrame, SignalSeries, Snapshot, ReplayWindow, Trace and CheckResult all print a useful summary and render as a rich table in a notebook. to_pandas() is for handing data to pandas, not for looking at it.Changed¶
int passed where a time belongs raises below 1015 instead of being read as an epoch in nanoseconds. A number that small is nearly always seconds by mistake — write "-30s".datetime is accepted and read as UTC instead of being rejected.query() expand against the query window rather than a fixed 60-second catalog, so a glob over a long window matches what the window actually contains.latest() takes a wildcard. agent.latest("bus0/BMS_message/cells.*") returns a Snapshot of every match; one literal path still returns a single LatestValue.Trace.latest() / Trace.at() and the TraceSet pair return the live shapes — a LatestValue for one literal path, a Snapshot otherwise — and ReplayWindow.snapshot is a Snapshot rather than a list.TraceSet.query() on offset bounds puts the runs on one grid. Every sample is numbered by how many sample periods into its own run it sits, and the runs join on that number at the coarsest run's rate, so two runs recorded at different sub-second phases share rows instead of leaving each other's columns null. Only the edge of the window can leave a row unshared, when it holds one more sample of one run than of the other. to_pandas() on such a frame indexes by offset, not by a 1970 date.Trace.signals() and TraceSet.signals() come back sorted by path, and so do the columns of a Trace.query() frame.where() masks out values as nulls instead of NaN.to_pandas().count() returns a CheckResult whose .count is None on error, instead of 0 — a failed measurement no longer reads as a real zero.to_pandas() returns a timezone-aware UTC DatetimeIndex. Pass index=False for time as an ordinary column.producers= on query(), latest(), at() and window() defaults to every connected producer instead of localhost only. On check.that() / check.count() it stays the local store; a check reports one verdict per target.temporal="for_duration" / "within_duration") anchors at the end of the recording — its last N seconds — instead of the start.trace.check accepts lookback= for signature parity with agent.check and ignores it.zelos.check.result.v1 events.std() uses ddof=1 — the sample standard deviation, matching pandas.median() is exact instead of approximate.DataType.Int32 == "int32".voltage * current is voltage × current, and ÷, +, − follow; a chart legend never reads null.NamedScalar prints as a measurement: four significant digits and the unit (3.629 V), with f"{peak:.2f}" keeping the unit too. float(peak) is still the exact value.ExportResult and TraceSet.series() render themselves — one row per producer, one column per run.from zelos_sdk import * binds the agent TimeRange.window(duration=…) with a plain number means seconds, not nanoseconds.TraceSet.time_range is a TimeRange.watch() yields a Snapshot — a Mapping that renders itself — instead of a plain dict.AssertionError fails the notebook run (exit code 1); any other exception errors it.--param names must be ASCII Python identifiers — no keywords and no dunders — so a parameter is always usable as params.<name> in a cell. A bad name is refused before the run starts.dependencies: list when the notebook declares none.jsonschema and pyarrow. pytest, rich and colorama are no longer installed by default; pip install "zelos-sdk[test]" restores pytest and rich, and [notebook] adds the analysis stack (pandas, numpy).Deprecated¶
DeprecationWarning naming its replacement. Nothing is removed.
Old
New
Agent.connect()zelos_sdk.connect(target, timeout=…)
Agent.health_check()Agent.health()
Agent.resolve_paths()agent.signals().match(pattern)
SignalCatalog.by_path(path)catalog[path]
SignalCatalog.to_list()list(catalog)
SignalSeries.derive()SignalSeries.from_arrow(values, name=…, unit=…)
SignalSeries.get()SignalSeries.to_pandas()
SignalSeries.time_arrow()the
SignalSeries.time attribute
sort_order=sort="asc" / sort="desc"
relative_start= / relative_end=start="+30s" / end="+30s"
time_mode=nothing — the bounds pick the axis
export(paths=…)export(signals=…)
lookback= on query()nothing — wildcards resolve against the query window
[analysis] extra is an alias of [notebook];
TraceSet.traces and TraceSet.max_duration remain as properties beside the new
TraceSet.time_range; and every alphabetic and
natural-language operator spelling (gt, is greater than, is not equal to,
in, …) still parses to the same canonical operator as its symbol.Fixed¶
integrate() and derivative() refuse a series with nulls instead of guessing across a gap, and name ffill() / dropna() as the fix.Upgrade notes¶
# 1. to_pandas() already indexes by time.
frame.to_pandas().set_index("time") # before
frame.to_pandas() # after — or to_pandas(index=False) to keep the column
# 2. Look a signal up by path with an index.
catalog.by_path("bus0/BMS_message/status.pack_current") # before
catalog["bus0/BMS_message/status.pack_current"] # after
# 3. A relative time is a signed string, not a number.
agent.query(paths, start=-30) # before
agent.query(paths, start="-30s") # after
.ffill().dropna() — a frame is joined on time and sparse by construction, and integrate() / derivative() refuse a series with nulls rather than guessing across a gap.
0.0.10
Added¶
zelos_sdk.agent): Connect to a running Zelos Agent from Python and query live or recorded data through one handle — browse the signal catalog, query and downsample time-series into Arrow/pandas, read latest values, watch for live updates, run actions, manage extensions, and open .trz trace files. Read more.agent.layouts CRUD (list/show/create/update/delete) plus full version history — list a layout's versions, restore a previous version, or label one. Read more.agent.check.that(lhs, op, rhs) asserts a predicate against a live signal or .trz trace, with temporal quantifiers such as always/eventually evaluated server-side; agent.check.suite(...) runs a JSON suite of checks in one round-trip. Read more.zelos_sdk.schemas.Log — a predefined schema for typed log events (zelos.log.v1); pass a schema class directly to add_event(name, schema) instead of a field list. Read more.TraceSource.log_batch() — log a pyarrow.RecordBatch or Table directly for zero-copy, high-throughput ingestion.TraceSource.log_many() — log a list of (time_ns, event_name, data) tuples in a single call, cutting Python↔Rust overhead for high-frequency sources like CAN decoders.TraceSource(name, strict=True) — opt into strict type coercion; rejects lossy float→int narrowing instead of silently truncating it.TraceNamespace.drain() — flush every source and block until all queued events reach subscribers, for deterministic teardown ahead of closing a TraceWriter.Changed¶
ActionExecuteResult (value + status) with PASS/FAIL/ERROR/DONE states instead of a bare value; the old ActionResult/ExecuteStatus names remain as deprecated aliases.@action declaration order end-to-end instead of being alphabetized, so generated forms render fields in the order they were declared.Fixed¶
SignalFrame now resolves columns correctly when the same signal name appears across multiple producers or segments, raising AmbiguousSignal on a genuine tie instead of matching the wrong column.TraceReader no longer drops a trace's last row when its timestamp has sub-microsecond precision.TraceWriter now captures every event logged before its with block exits, without needing a sleep before close to avoid losing in-flight data.TraceSourceCache now stores a Python None as a null value instead of raising an error.
0.0.9
Added¶
FolderPickerWidget for Actions, enabling folder selection in extension UIspyarrow as a direct dependency — no longer needs to be installed separately for TraceReaderFixed¶
None instead of causing serialization errors
0.0.8
Added¶
.trz trace files for offline analysis, debugging, and post-processing. Read more.
0.0.6
Added¶
field_type, enabling richer, type-aware
rendering in the Zelos App without custom widgets.required=True, surfacing missing inputs during
validation instead of at execution time.Improved¶
0.0.5
Added¶
object.Changed¶
setuptools dependency.Fixed¶
TraceSegmentStart message was missed.TracePublishClient.