Commit Graph
51 Commits
Author SHA1 Message Date
07akioni 84edeadc2b feat(i18n): add Spanish French German Russian and Portuguese 2026-10-22 19:53:52 +08:00
07akioni 6238020202 fix(locale): type additional dictionaries and complete Japanese registration 2026-10-21 13:42:49 +08:00
07akioni 3f9f36e92d feat(locale): add Japanese client and desktop translations 2026-10-21 11:42:12 +08:00
Stevring 94ffdd2377 fix(client): align touch tooltips and hover affordances 2026-10-20 12:50:31 +08:00
ZiyaandZiyaZhang c7d61ecc11 fix(i18n): 补充内置插件中文文案并精简清单展示 (#5506)
* fix(i18n): add Chinese names and descriptions for built-in plugins

* fix(i18n): keep built-in plugin localization metadata-only

---------

Co-authored-by: ZiyaZhang <[email protected]>
2026-10-09 17:18:26 +00:00
ZiyaZhang e563bb4bbc fix(ui-settings-plugin-inventory): address review on card ids and loading
The visible id chip and the accessible name now share one check for whether
the entry id adds to the title, so an include: id that matches the title is
left out of both. The loading skeleton's status region carries visually
hidden text so screen readers announce it. The settings-chrome browser
scenario expects the preset group open and enabled rows without a tag, and
its two ARIA snapshots are refreshed. The row-partner CSS comment states its
two-column assumption.
2026-09-25 00:49:05 -07:00
ZiyaZhang 92690a5a3b fix(ui-settings-plugin-inventory): align and simplify plugin cards
Cards in one grid row now share a height, with title rows and descriptions
starting at the same offsets. The entry id shows only when it differs from
the title, as a code chip in the card's bottom-left corner; tags mark only
states other than plainly enabled; descriptions clamp to two lines until the
card expands; the preset group starts open; loading shows skeleton cards.
Group headers share one height, the subtitle separator is evenly spaced, the
title weight drops to 500, 12.5px text moves to 12px, and a container query
on the tab switches the grid to one column.
2026-09-25 00:14:40 -07:00
liukx0205 9827bcfb37 Merge master into fix/focus-ring-brand-primary 2026-09-24 15:38:51 +08:00
yixiangihsiang fdd14a0989 feat(web): unify UI materials and streamline file review 2026-09-24 14:58:54 +08:00
liukx0205 4f1a1289f5 fix(client): use blue focus rings in light and dark themes 2026-09-24 12:24:47 +08:00
mektpoy 9fd52295fc fix(client): finish the ring-colour sweep and name the tooltip/ring split
Two focus treatments still named a colour of their own: the TurnNavigator
mark's tick filled with `state-business-primary` under a comment that already
claimed the brand colour, and the plugin inventory search input drew its focus
border in `state-business-primary` while the shadow beside it read
`--dsw-focus-ring-color`. Both now read the same ring colour as the rest.

`Tooltip` states why it takes `pointerModality()`'s wide answer while focus
rings read the narrower `data-input-modality` attribute the module publishes.
2026-09-23 17:58:06 +08:00
mektpoy fae37cd705 Merge remote-tracking branch 'origin/master' into fix/focus-ring-brand-primary
Conflicts and how they were resolved:

- ui-agent-preset/AgentPresetSection.module.css: master replaced the icon-only
  tooltip actions (`.iconButton`, `.iconDanger`, `.revealedPath`) with
  `.cardHelp` + `.helpButton`, which deleted the one declaration this branch
  edited. Took master's structure and re-applied the branch's change to the two
  `.cardMain:focus-visible` rings, which master kept unchanged.
- ui-theme/README.md and README.zh.md: master documented the separately exported
  `brand-font.css`; this branch documented `focus.css`. Kept both, with the
  dynamic entry's sheet list at seven sheets including `focus.css`.
  `README.i18n.yaml` re-recorded with `verify-translation-pairing --write`.
2026-09-22 20:37:05 +08:00
mektpoy bca9cecc7d fix(client): keep pointer focus silent through descendant and editable rings
Pointer suppression previously cleared `outline-color` on the focused element
alone, so a ring painted by a descendant, a pseudo-element, or a `box-shadow`
stayed visible, and editable text controls lost the focus feedback they need on
click.

Ring colour now flows through `--dsw-focus-ring-color`, which component outlines
and focus-ring shadows read alongside the brand token. Every ring that inherits
the variable is suppressed together, and `body :focus-visible:not(:read-write)`
limits the suppression to rings while editable controls keep their own feedback.

Keyboard modality returns on Tab, Home, End, PageUp, or PageDown, and on focus
reaching a different control after a non-composing key. IME composition keys,
refocusing the same control, and window blur leave rings silent. The desktop
preload menubar suppresses its own ring inside its shadow root, where the
document-level attribute does not reach.
2026-09-22 20:28:10 +08:00
Turtle d1e22a7e24 feat(preset): declare Agent compositions in profile YAML (#4569)
* feat(preset): declare Agent compositions in profile YAML

* fix(preset): share scope binding cleanup and refresh module graph

* fix(preset): use host syntax colors in the YAML editor

* fix(preset): write new profile declarations as block YAML

* fix(preset): align eager activation with browser and worker surfaces

* fix(ui-agent-preset): retain the existing preset card layout

* fix(preset): keep rows waiting for a Host service mounted and re-audit after settlement

A preset row whose Host provider was still activating at declaration time
was reported as waiting for a missing service, and the registry recorded the
definition as broken for the rest of the process. Split the mount audit into
failed and pending rows: failures and root-realm leaks still reject the
mount, while pending rows stay mounted and every read and binding re-audits
them after the Host Loader tree settles.

Remove the accidental self-dependency of @deepseek-ai/dsh-web-app and its
lockfile self-link. Archive the copy-only preset authoring note, which the
declarative-preset note fully supersedes, and update the ralph note's
restore recipe to the profile-patch mechanism.

* chore(lint): re-key and prune the unknown-cast baseline after the master merge

* refactor(web-app): ship each Agent preset as its own bundle patch file

`dsh.bundle.patch` accepts an ordered file list, so the four shipped preset
declarations move out of the 1000-line web patch into
`presets/<id>.patch.yml`, one insert per file, applied after the host patch.
The host patch keeps the preset registry row. Gates and test scaffolds that
read the web layer resolve every patch file through `bundlePatchPaths`
instead of one hardcoded path.

* refactor(preset): drop the save notice injected into live Agents

The notice duplicated the save result the Web editor already shows, and
after the producer-owned message sources it would have needed its own
persisted source kind. Saving now only persists and reports the activation
diagnostic; the persistence catalog is unchanged from master.

* docs: regenerate the module graph after dropping the registry's llm dependency

* test(ui-agent-preset): cover the guide dialog's keyboard handling on the declarative section

* fix(preset): address the remaining review comments

Apply the lowercase id rule only when creating a declaration, so presets
declared with other ids stay editable. Export `isBuiltInPreset` from the
display fold and key the client card groups on it. Remove the dead `error`
and `retry` locale keys, the JSDoc orphaned by the `trust` removal, the
`trust` fields in the plugin-inventory test fixtures, and the stale
`dsh-agent-presets` package name in comments and READMEs.

* refactor(preset): make the Web preset page view-and-select only

Remove the child-plugin YAML editor, the `agent_preset` tool and the
registry's read/save Remote methods. Presets are declared and changed only by
bundle patches; the settings page keeps the roster, the new-task default and
the mode help, and its question icon explains that and offers to start a
Creator-mode task. The `editing-cordis-compositions` skill and the Creator
persona describe the bundle-based path, and the authored skill-load Session
and Web snapshots are refreshed for it.

* docs(skill): make the composition skill self-sufficient for preset authoring

State where the shipped declarations live, list every declaration field,
inline a complete minimal bundle and an override example, and name the
verification calls, so Creator mode no longer reads DSH package sources to
infer the format. Refresh the authored skill-load Session for the new text.

* test(tools): drop the removed agent_preset tool from the catalog expectation
2026-09-21 08:24:18 +00:00
mektpoy 65ba30ab4f refactor(client): name the standard focus-ring width
Every ring that used 2px now reads --dsw-focus-ring-width. The dense tables and
toolbars keep their 1px ring on purpose: at 2px they visibly outweigh the rows
they sit between, so the standard value and the dense exception stay distinct
rather than converging on a number nobody measured.
2026-09-20 18:47:45 +08:00
mektpoy 230d975a04 docs(client): explain the identity tiers and the detailName scope
The shared rule now states why the collapsed identity and the expanded value keep two label tiers, and the detailName comment names the row identity it also renders.
2026-09-20 16:18:56 +08:00
mektpoy 08b310b5a8 fix(client): paint every keyboard focus ring with the brand colour
Focus rings named eight different colours across 54 client stylesheets, and a
control that declared no ring fell back to the browser default, whose colour
follows the operating-system accent — so the same build showed orange on one
machine and blue on another.

Every keyboard focus ring now uses --dsw-alias-brand-primary. A global ui-theme
focus.css sheet reaches the controls that declare no ring of their own, and 49
declarations name the same token. Only the colour changed: each declaration
keeps its width, style and offset.
2026-09-20 15:59:12 +08:00
mektpoy 63190fc870 fix(client): unify the plugin identity colour on label-tertiary
Review feedback on this PR: keep one identity colour rather than raising the
card subtitle to label-secondary. The detail-page package name moves from
label-caption to label-tertiary; the settings card subtitle keeps its own
colour and shares only the 12px size with the row it expands into.
2026-09-20 12:19:13 +08:00
mektpoy 88ee6039c6 Merge remote-tracking branch 'origin/master' into fix/windows-plugin-list-type-size 2026-09-19 22:33:52 +08:00
mektpoy 3014457c60 fix(client): share one size for the plugin inventory entry identity
Keep the Loader entry id at one size in both places it appears - the card
subtitle and the row the card expands into - by moving the shared code-font
typography into a single rule. The subtitle keeps its own secondary label
colour against the expanded row's primary one.
2026-09-19 21:46:43 +08:00
imccyu 0d611ea151 feat(web): display plugin-owned locale metadata 2026-09-19 20:19:04 +08:00
mektpoy c85e1d7b72 fix(client): raise the plugin inventory package identity to 12px
The Plugins settings inventory drew the Loader entry identity (cardIdentity)
at 11px in the code font, one step below the 12px the same identifier gets in
the expanded card's entry row. On Windows the code stack resolves to Consolas,
where 11px reads thin. Raise it to 12px/18px so it matches the sibling
identifier row and the page's other small text.

Fixes #4496
2026-09-18 17:25:40 +08:00
yixiangihsiang 4937343a5e feat(web): unify the client visual language 2026-09-17 19:14:41 +08:00
Turtle f91d5e310d refactor(web): drop the plugin-list dot for an active fiber
A collapsed plugin card carried both an enablement tag and a green root-fiber
status dot; for the common `active` phase the two stated the same settled
state. The dot now renders only for `pending`, `loading` and `unloading`,
the phases the enablement tag cannot state, and the expanded card keeps the
phase fact.

Related to #4424
2026-09-17 15:41:58 +08:00
Yichen Jiang dc9256536b Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-4-web
Master now carries the final #4182 plugin manager and the live client
module graph of #4189, so the web management layer is re-ported onto
them:

- The manager keeps master's `ManagementError` codes, `ChangeResult`
  stages, `configure()` under `hmr.runExclusive`, `reload()` warnings
  and `writePluginEnabled` name matching, and adds back `inspect`,
  request-id installs with `plugin-manager/install-log` and
  `plugin-manager/install-state`, `cancelInstall`, `listBundles` titles,
  rows and overrides, `packageResult.kind`, `pnpmCommand` and
  `inspectTimeoutMs`, and `plugin-manager/changed` after each change and
  each `profile/reconciled`. A failed or cancelled installation restores
  the snapshotted manifest and lockfile instead of master's one-shot
  `pnpm remove` cleanup, so `cleanup` and `remainingDependencies` leave
  the result.
- App boot keeps master's reconciliation diagnostics and emits
  `profile/reconciled`; `watchUserPatches` goes with the launcher's
  watcher now that HMR owns profile reloads.
- The settings Plugin list tab stays read-only with #4189's page-local
  sync failures and retry; master's bundle form and row checkboxes are
  dropped again. The sidebar page words the Host's codes through its
  dictionary, and a client bundle change follows the live module graph
  without a page reload.
- The web e2e scaffold no longer chooses a reload policy: the base
  bundle's `hmr` row turns on with the profile context and application
  readiness, and `profile.hmr: false` disables it through an overlay for
  the startup-only scenario.
2026-09-15 17:28:08 +08:00
Yichen Jiang 4d1adb8541 feat(web): manage plugins over the #4182 manager from the sidebar page
The sidebar Plugins page now drives `ctx.pluginManager` from #4182 and the
settings Plugin list tab goes back to read-only: its bundle form and row
checkboxes are removed, and the page joins `listBundles` with
`listPlugins` into one view per bundle, decides availability from the
inventory's `managementAvailable`, switches bundles and rows through
`setBundleEnabled` and `setPluginEnabled`, and confirms uninstalls.

The manager gains what the guided install dialog needs: `inspect(spec)`
reads a spec through the registry or a directory before anything installs
and refuses specs without a bundle; `installBundle` takes a request id,
streams each pnpm run as `plugin-manager/install-log`, reports its phases
as `plugin-manager/install-state`, classifies a failed run into
`packageResult.kind`, names the bundle it added, and restores
`package.json` and `pnpm-lock.yaml` when the run fails, is cancelled, or
adds a package without a bundle patch; `cancelInstall(requestId)` answers
only after pnpm exited and the files are back; `listBundles` carries
titles, one-liners, declared rows with their live entries, and the
built-in rows a bundle overrides; every completed operation and every
patch generation applied outside the manager emits
`plugin-manager/changed`. The config gains `pnpmCommand` and
`inspectTimeoutMs`. App boot emits `profile/reconciled` after each applied
patch generation and finds a root Include mounted under its pinned id by
another copy of the module.

Row diagnostics, dependency checks, and the non-bundle dependency group
are not carried over; the web e2e scaffold mounts a launcher-style
managed profile instead of the removed profile runtime.
2026-09-15 16:36:31 +08:00
Yichen Jiang b3e964c340 Merge PR #4182 (turtle/plugin-manager) into feat/plugin-mgmt-4-web
The web plugin management layer now sits on the current-profile plugin
manager from #4182 instead of the boot and manager layers of #3593 and
#3594. This merge takes #4182's host side whole — `packages/boot/hmr`,
its `packages/boot/plugin-manager`, `profileContext` in app-boot, the
vendored loader change — and drops the replaced host packages and their
app-boot, inventory, Remote, CLI, and catalog edits. The web files of
#3596 are carried over unchanged: the sidebar page package, the
ui-primitives terminal changes, the settings-section tweaks, the e2e
scenarios and fixtures, and the two web Agent Notes. They do not build
against the new host until the following commit adapts them.
2026-09-15 16:36:31 +08:00
Turtle 311156b1c2 Merge master and preserve profile-managed HMR 2026-09-15 16:20:47 +08:00
Turtle 61665c3454 fix(plugin-manager): clean failed installs and address critical review findings 2026-09-15 15:15:49 +08:00
Turtle 5a9c159c27 fix: preserve manager failures and support worker preview imports 2026-09-14 23:26:43 +08:00
Turtle d06e6b5519 feat: coordinate profile management through dsh-hmr 2026-09-14 23:09:06 +08:00
Turtle 98b92b683c feat: add current-profile plugin manager service and Web controls 2026-09-14 23:09:05 +08:00
Yichen Jiang fb0fb48033 feat(web): apply client plugin changes without reloading 2026-09-14 21:47:38 +08:00
Yichen Jiang 2d660bf078 fix(web): list only installed packages on the sidebar Plugins page
The sidebar page no longer shows the profile template's own bundles
(dsh-base, dsh-web-app). The Settings Plugins section gets its read-only
Plugin list tab back for them, with both of its groups collapsed by
default. Restores @deepseek-ai/dsh-client-ui-settings-plugin-inventory
with its web bundle row, tsconfig entries, catalogs, and goldens, and
drops the built-in tag, locked switch, and source fact the page no
longer needs.
2026-09-14 16:45:13 +08:00
Turtle 2e2489b888 fix(web): trim composition marker from plugin subtitles 2026-09-09 15:41:02 +08:00
Turtle 1349af8e97 fix(web): give plugin identities a full row 2026-09-09 14:57:45 +08:00
Turtle c2a5540ddb fix(web): distinguish plugin configuration instances 2026-09-08 21:05:37 +08:00
Yichen Jiang a6ef8dc97a fix(client): animate the unloading phase dot and correct the catalog
`unloading` marks a teardown the Host is running, which an async disposer
can hold for a while, so the inventory's dot animates it like `loading`
instead of showing the static grey `idle` mark that means no activity.

Correct four documentation facts against the shipped code: StateDot's
render JSDoc still promised four states, the catalog claimed four Tooltip
sides where TooltipSide has three, the Agent Note's geometry audit counted
three matching rules where two match, and the migrated-site and shipped-
appearance counts had drifted.

Record two things the first pass left out: TerminalBlock renders its exit
status as a static Pill, which the Tag/Pill catalog entry now accounts for
by size rather than by interactivity alone, and the disabled inventory tag
changed fill token, which joins the visual-change list.

Pin Tag's eight tones with a stylesheet spec, for the same reason StateDot
has one: CSS Modules resolve to class-name maps in component suites, so a
missing or wrong tone rule passes every render assertion.
2026-09-05 14:54:42 +08:00
Yichen Jiang 452b2a816a refactor(client): share the capsule tag, switch, and idle state dot
Client feature plugins never import one another's components, so
ui-primitives is their only channel for sharing one. Nothing told an
author to look there first, and the package offered nothing to look
at: its README named six source files against forty-plus exports.

Add Tag (read-only capsule badge, eight tones) and Switch (36x20
toggle with a required accessible name), extend StateDotState with
idle for a tracked subject with no activity, and move ui-agent-preset,
ui-settings-plugins, and ui-settings-plugin-inventory onto them.

The plugin inventory's conditional tag referenced
--dsw-alias-state-warning-primary, which does not exist, so both
themes had been painting its hardcoded #b45309 fallback.

State the reuse rule as the first step of the new-component checklist,
and give the README a component catalog so the rule has something to
check. The rule is guidance, not a gate: a package may still write its
own control, and the Agent Note records the five that stay local.
2026-09-05 14:32:59 +08:00
Yichen Jiang a7302ee69e feat(web): simplify the plugin manager and drop the plugin list tab
The Manage plugins tab now speaks two nouns (plugin pack, plugin) and four
states (running, off, restart needed, problem). Cards carry a display name,
a one-liner, one kind tag, and their uninstall beside the switch; built-in
packs fold behind one line; the selected preset's composition renders as a
grid of cards named through the tab's own dictionary for harness modules
and through the manifest for third-party ones; entry ids, module names,
cordis copies, and probe times leave the page. The install dialog keeps
pnpm's output behind a fold that opens on failure and words each outcome;
confirmations name what still uses the package and no longer require an
acknowledgement. The client passes a preset row's declared id, not the
live tree's prefixed entry id, to the row actions.

The read-only Plugin list tab and its package, ui-settings-plugin-inventory,
are removed; the pluginInventory Remote stays as the manager's source of
preset compositions and host-tree module names.
2026-09-04 16:53:01 +08:00
Yichen Jiang 1570eeeaee feat(web): manage plugins and per-preset settings from the browser
Add the Manage plugins tab (ui-settings-plugin-manager): package cards
with enable/disable switches, retry and uninstall, an install dialog
streaming pnpm output, and the selected preset's composition with per-row
switches and removal; the read-only list gains provenance facts.

Settings cards edit one scope at a time: ui-settings keeps one describe
mirror per settings scope (SettingsMirrorRegistry) and binds
{ namespace, scope }; ui-settings-plugins stages forms per scope, marks
inherited fields, and adds the skill-filesystem roots card.

Fixes surfaced by driving the browser end to end: the client gateway now
lets a call omit trailing parameters that accept undefined (PR3's
optional scope arguments failed the strict arity check), the plugins
install verb is `add` because the client namespace service reserves
`install`/`remove` (guarded by remote-method-names.host.spec), a plugin
module offers its main export as an addable `.`, and describing a settings
scope no owner registered resolves over the global instance's base and
never throws.

The web e2e scaffold can mount a profile runtime over fixture packages;
plugin-manager.e2e drives the tab and writes one field under a preset
scope; plugin-config and settings-chrome goldens are refreshed.
2026-09-04 04:32:31 +08:00
yx.zhang 7020c7e122 feat(web): superellipse corners and hairline elevation strokes
Apply global visual polish across the web client: corner-shape:
superellipse(1.5) with corner-shape: round pairing for full circles,
elevation tokens that draw 0.5px stroke outlines inside box-shadow for
floating surfaces, 0.5px hairline borders and divider lines for
neutral-token strokes, and tuned stroke contrast plus larger radii for
menus, settings panels, and cards. Stylesheet-scan specs in ui-theme
reject unpaired circles, border+shadow mixes, and 1px neutral hairlines
repo-wide.

Closes #3287
2026-09-01 18:25:20 +08:00
Turtle b8e3b32fcf Merge master into codex/omit-unneeded-invariants 2026-08-31 14:38:55 +08:00
Yichen Jiang 8349cc6c73 fix(agent-presets): live-mount-first inventory, per-runtime mounts, localized shipped preset names
Review round on #3316: the composition inventory answers from a standing
mount before the broken verdict (a file corrupted after mounting no longer
hides the running composition), livePresetMounts filters by the caller's
root fiber so a second Cordis runtime in one process never answers for it,
compositions carry trust and the plugin list resolves shipped preset names
through the shared dsh-agent-presets/display fold over ui-agent-preset's
dictionaries (INLINE_SAFE inline import; no cross-plugin runtime import),
the condition detail label reads Disabled when/禁用条件, and the stale
four-surfaces comment says three.
2026-08-29 20:41:01 +08:00
Yichen Jiang cebd0a2031 refactor(plugin-inventory): match group title and switcher pill to the General-settings row idiom 2026-08-29 17:26:05 +08:00
Yichen Jiang 0f06f973c4 refactor(plugin-inventory): settings-row style group headers
Both scope groups drop their boxed chrome for the General-settings row
idiom: a title row (session-plugins title with the right-aligned preset
selector pill; global-plugins title), a grey subtitle line carrying the
count, a hairline divider between groups, and the cards grid below.
Counts ride the subtitle as text while the data attributes keep the raw
numbers for tests.
2026-08-29 17:13:45 +08:00
Yichen Jiang 5eb7195f9d refactor(plugin-inventory): menu-pill preset switcher, collapsible groups, inline preset-provided rows
Review-driven refinements to the scope-grouped plugin list:

- The preset switcher becomes the General-settings selector pill over the
  shared Menu primitive instead of a native select, and the preset group
  is collapsible like the global one (search still forces both open).
- The session-plugins drawer is removed: rows the presets took over sit
  inline in the global list with the preset-provided tag and per-preset
  details, since the preset group above already shows those compositions.
- The status dot renders only for a live root fiber, so file-state rows
  of an unmounted preset carry their enablement tag alone instead of a
  column of grey dots.
- PresetTree reclaims the owning entry's subtree slot: EntryTree's
  constructor filed the standing mount under the roster's own Loader row,
  so after the first session composed a preset the whole composition
  leaked into root loader.entries() as host rows (each preset overwriting
  the last). A regression test holds the root entry list identical across
  a mount.
2026-08-29 17:13:45 +08:00
Yichen Jiang e5f36cc70f feat(plugin-inventory): carry every agent preset's composition and group the settings plugin list by scope
The settings plugin list projected ctx.loader.entries() alone, hiding the
plugins sessions actually run and rendering the web overlay's deliberate
disabled tombstones (tool-bash, tool-fs, ...) as two dozen plainly disabled
rows while the same modules ran in every standard-preset session.

- dsh-agent-presets: compositionInventory() answers flattened rows per
  preset — newest live standing generation when mounted, composition file
  otherwise with !!js disabled gates evaluated against the Loader context;
  reading never mounts (regression-tested), refusal stays 'conditional',
  raced files report broken with the reason.
- dsh-host-plugin-inventory: list() gains an optional agentPresets block,
  resolving the roster as an optional peer and mapping fiber states to the
  public phase vocabulary.
- ui-settings-plugin-inventory: preset group first behind a display-only
  switcher opening on the default preset; global group collapsed with
  failures floated; host-disabled modules enabled by >=1 preset fold into a
  session-plugins drawer naming providers; search spans scopes and points
  at matches in unselected presets.
- ui-agent-preset: the General-settings default-preset row is deleted — the
  roster section's make-default and the new-session chip keep the field —
  and the settings store slims to the display roster the header label reads.

Docs, catalogs, module graph, settings-chrome goldens, and the bilingual
Agent Note ride along.
2026-08-29 17:13:45 +08:00
Turtle 15f2997bcb cleanup: omit unneeded invariant companions 2026-08-28 13:12:52 +08:00
imccyu be531688f3 refactor(client): migrate consumers and remove Runtime 2026-08-23 16:28:18 +08:00