Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/codelogician-skill/codelogician
4 changes: 4 additions & 0 deletions packages/imandrax-api-models/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Versioning scheme: <IMANDRAX_API_VERSION>.<MINOR>.<PATCH>

## [Unreleased]

## [20.5.1] - 26-07-30
- FEAT(yaml-utils): add general to-yaml-str dump function (upstream)

## [20.5.0] - 26-07-27
- add `TasksRepr` for task widget serialization
- add unify task repr (upstream from `imandrax_tools.widget`)
Expand Down
2 changes: 1 addition & 1 deletion packages/imandrax-api-models/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "imandrax-api-models"
version = "20.5.0"
version = "20.5.1"
description = "Pydantic model definitions for imandrax-api. Also provides a client wrapper with built-in validation and utility methods."
readme = "README.md"
authors = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class TasksRepr(BaseModel):
tasks: list[TaskEntry]
other: JSONObject = Field(default_factory=dict)

@property
def is_nil(self) -> bool:
return len(self.tasks) == 0

def to_json(self, skip_task_without_artifacts: bool = False) -> JSONObject:
res: JSONObject = {}
for task in self.tasks:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# pyright: reportUnknownMemberType=false, reportUnknownVariableType=false

from enum import Enum
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any

import yaml
from pydantic import BaseModel

if TYPE_CHECKING:
Expand Down Expand Up @@ -59,3 +60,26 @@ def basemodel_representer(dumper: Dumper, data: BaseModel):
ImandraXAPIModelDumper.add_representer(str, str_representer)
ImandraXAPIModelDumper.add_multi_representer(Enum, enum_representer)
ImandraXAPIModelDumper.add_multi_representer(BaseModel, basemodel_representer)


# ====================


class _YDumper(Dumper):
pass


_YDumper.yaml_representers = {**ImandraXAPIModelDumper.yaml_representers}
_YDumper.yaml_multi_representers = {**ImandraXAPIModelDumper.yaml_multi_representers}
# Emit tuples as plain sequences instead of `!!python/tuple`.
_YDumper.add_representer(
tuple,
lambda dumper, data: dumper.represent_sequence('tag:yaml.org,2002:seq', list(data)),
)


def to_yaml_str(v: Any, **kwargs: Any) -> str:
if isinstance(v, str):
return v

return yaml.dump(v, Dumper=_YDumper, sort_keys=False, allow_unicode=True, **kwargs)
5 changes: 5 additions & 0 deletions packages/imandrax-tools/.gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# Built anywidget JS bundles (source of truth: widget-js/src, built via `make build-widget-js`).
src/imandrax_tools/widget/static/*.js linguist-generated=true -diff

# TS widget types generated from the pydantic models by `make gen-widget-types-py2ts`.
# Kept diffable, unlike the bundles: the change is readable and worth reviewing when
# a model changes.
widget-js/src/generated/*.ts linguist-generated=true
4 changes: 4 additions & 0 deletions packages/imandrax-tools/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Versioning scheme: <IMANDRAX_API_VERSION>.<MINOR>.<PATCH>

## [Unreleased]

## [20.5.0] - 2026-07-30
- widget: add jsonable general widget
- widget: replace plain text fallback with new pre/post slots in existing widgets

## [20.4.0] - 2026-07-27
- REFA!(widget/tasks): switch to unified task repr type and constructor
- widget/decomp: add constructor for unified decomp res type (`DecomposeRes_`)
Expand Down
4 changes: 4 additions & 0 deletions packages/imandrax-tools/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
default:
just --list

mod js "widget-js/justfile"
2 changes: 1 addition & 1 deletion packages/imandrax-tools/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "imandrax-tools"
version = "20.4.0"
version = "20.5.0"
description = "Umbralla package bundling imandrax-api-models and iml-query. Also provides miscellaneous utilities (goal state formatting, rec knowledge base)."
readme = "README.md"
authors = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

from .embed import render_anywidget
from .nb_hooks import register_widgets
from .widgets import IDFWidget, RegionDecompWidget, TasksWidget
from .widgets import IDFWidget, JsonableWidget, RegionDecompWidget, TasksWidget

__all__ = (
'TasksWidget',
'RegionDecompWidget',
'IDFWidget',
'JsonableWidget',
'register_widgets',
'render_anywidget',
)
36 changes: 34 additions & 2 deletions packages/imandrax-tools/src/imandrax_tools/widget/nb_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

from __future__ import annotations

from typing import Any
from typing import Any, cast

from imandrax_api_models import CodeSnippetEvalResult, DecomposeRes, EvalRes
from imandrax_api_models.client import ImandraXAsyncClient, ImandraXClient
from imandrax_api_models.context_utils import FormattableModel, jsonable_of_model
from imandrax_api_models.region_decomp import EnrichedDecomposeRes
from imandrax_api_models.yaml_utils import to_yaml_str

from imandrax_tools.idf.viz_view import View as IDFView
from imandrax_tools.widget_types import HasTasks
Expand All @@ -16,17 +18,33 @@
_client: ImandraXClient | ImandraXAsyncClient | None = None


def _yaml_of(model: FormattableModel) -> str:
"""The whole result as YAML, for a widget's `pre` panel."""
return to_yaml_str(jsonable_of_model(model))


def register_tasks_widget(c: ImandraXClient | ImandraXAsyncClient) -> None:
"""
Make `EvalRes` and `CodeSnippetEvalResult` render as a `TasksWidget`.

With no tasks to show -- an eval that errored out -- the whole result goes
into the widget's `pre` panel as YAML, so the failure stays visible instead
of rendering as an empty tasks view.
"""
global _client
_client = c

def repr_mimebundle(self: HasTasks, **kwargs: Any) -> Any:
assert _client is not None
widget = TasksWidget.from_has_tasks(self, _client)
# Delegate to the widget's own hook so its text fallback still applies.
# Keyed off the entries rather than `self.tasks`: a task whose artifacts
# were all excluded yields no entry, and an empty panel either way. The
# panel is dropped (not left to say "No tasks.") because the YAML now in
# `pre` reports the task list along with everything else.
if not widget.task_entries:
# `allow_none=True` on the traitlet, which the stubs do not model.
widget.task_entries = None # type: ignore
widget.pre = _yaml_of(cast(FormattableModel, self))
return widget._repr_mimebundle_(**kwargs)

setattr(EvalRes, '_repr_mimebundle_', repr_mimebundle)
Expand All @@ -36,12 +54,26 @@ def repr_mimebundle(self: HasTasks, **kwargs: Any) -> Any:
def register_region_decomp_widget() -> None:
"""
Make `EnrichedDecomposeRes` / `DecomposeRes` render as a `RegionDecompWidget`.

An errored decomposition has no region groups to lay out, so the whole result
goes into the widget's `pre` panel as YAML -- what the `text/plain` fallback
used to cover.
"""

def repr_mimebundle(
self: DecomposeRes | EnrichedDecomposeRes, **kwargs: Any
) -> Any:
widget = RegionDecompWidget.from_decomp_res(self)
has_regions = bool(widget.data)
if not has_regions:
# Nothing to lay out: drop the panel, the YAML carries the whole result.
# `allow_none=True` on the traitlet, which the stubs do not model.
widget.data = None # type: ignore
# `pre` is keyed off the errors too, not just off the panel: a result can
# report errors *and* still lay out region groups, and those errors would
# otherwise go unreported -- the `text/plain` fallback used to show them.
if self.errors or not has_regions:
widget.pre = _yaml_of(self)
return widget._repr_mimebundle_(**kwargs)

setattr(EnrichedDecomposeRes, '_repr_mimebundle_', repr_mimebundle)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Loading
Loading