Add { fatal: true } to TextDecoder in readHostedCatalogResponseText so
invalid UTF-8 bytes throw a TypeError before the text is JSON.parsed,
instead of silently becoming U+FFFD inside field values.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Route pattern, dependency, and active conditional schemas through the real plugin config validator while keeping standalone conditional annotations on the empty-config path.
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Allow before_agent_reply plugins to declare host-enforced trigger eligibility so scheduled-only hooks do not block interrupted user-turn recovery. Keep omitted and malformed scopes fail-closed, scope both memory-core maintenance hooks, and cover three runner reload cycles through the public registration contract.
Refs: #111442
Source: #114836
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Fixes#115524 by keeping path canonicalization scoped to each manifest and persisted registry build.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(active-memory): share one recall per run across retries
Register in-flight recalls per ctx.runId so overlapping or changed-prompt
attempts join a single execution, and gate replacement recalls on settled
timeout cleanup. Entries clear on agent_end. Fixes#106957.
* fix(active-memory): evict rejected recall entries
* test(active-memory): clarify run result retention
* test(active-memory): complete recall result fixture
* feat(talk): emit realtime models and voices in talk.catalog and mirror create-time readiness
* feat(ui): add curated Talk settings page with catalog-driven pickers
* docs(talk): correct stale claims and add one-page GPT-Live setup path
* fix(ui): refresh Talk catalog on config-hash advance and neutralize GPT-Live badge
* fix(ui): provider-aware Talk selection, atomic provider switch, focus refresh
* fix(ui): resolve Talk provider fallbacks via catalog and make Default a true reset
* fix(ui): provider-compatible transports and race-free Talk catalog loads
* fix(ui): never resolve an unknown explicit Talk provider to the active one
* docs(talk): note Android relay readiness caveat for browser-only models
* fix(ui): keep the relay transport when switching Talk provider to Auto
* fix(ui): align section-ownership test and drop unused export after rebase
Aggregators republish first-party models under a namespaced id and varying
case, so the shared-model check could not group novita/moonshotai/kimi-k3 with
moonshot/kimi-k3. Matching now ignores one leading namespace segment and case,
which catches that whole class automatically instead of needing an
upstreamModel marker per row.
Declares the tier on the 18 rows this surfaces across baseten, deepinfra, gmi,
novita, nvidia, and together. All are "capable", matching what the runtime
already applied for an absent flag, so behavior is unchanged.
* feat(plugins): catch code-mode drift between catalogs sharing one model
Adds a contract test that groups bundled catalog rows by shared upstream
model and requires every row in a group to declare compat.codeMode once any
sibling does. Rows sharing a model id group automatically; rows under
different ids opt in with the new manifest-only `upstreamModel` marker.
Moves the kimi catalog into its manifest so the scan can see it, and records
the tier reseller catalogs were silently missing as explicit "capable".
* docs: regenerate docs map for the shared-model code-mode section
* fix(plugins): deep-clone registry snapshot values for transactional rollback isolation
Shallow spread / new Map() copies nested objects by reference, so
in-place mutations on PluginRecord fields and Map values inside
arrays leak through rollback() — violating transactional isolation.
Wrap array items, Map values, and object properties in a recursive
deep-clone helper that preserves function references so handlers
and resolvers are not lost. Fixes#106647.
* fix(plugins): replace generic deep-clone with targeted shallow record cloning
Replace the recursive deepCloneRegistryValue with cloneRegistryEntry that
shallow-clones registration records to isolate primitive metadata fields
while preserving opaque plugin-owned instances (providers, services,
channels, harnesses, resolvers) by reference. A generic deep-clone was
too broad: it converted every plugin-owned object into a plain object,
losing prototypes, internal slots, and shared identity.
Add a class-instance regression test proving that providers survive
snapshot/rollback with their prototype chain intact and methods callable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(plugins): add curly braces and fix TS type assertions for CI
- Add curly braces to single-line if statements in cloneRegistryEntry
to satisfy eslint curly rule
- Use `as unknown as ProviderPlugin` double cast for test class instance
- Call test methods on original variable instead of through registry type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add loader-scenario rollback proof for two sequential plugin transactions (#106647)
Simulate the real loader pattern from loader-runtime-candidate L492-531:
transaction 1 registers a class-backed provider and commits, transaction 2
mutates registry state and rolls back. Prove the first plugin's metadata is
restored and its class-backed provider instance, prototype, and methods
survive the rollback.
* fix(plugins): snapshot active PluginRecord in registration transactions (#106647)
Add activeRecord parameter to createPluginRegistrationTransaction so
the active record's array fields (toolNames, hookNames, providerIds, etc.)
are snapshotted at transaction creation and restored on rollback.
Without this, the loader's recordPluginError path re-pushes the record
with stale id arrays from the failed register() call.
Also replace flat container copies in snapshotPluginRegistry with
cloneRegistryEntry that shallow-clones individual registration records
while preserving opaque plugin-owned objects by reference.
Update all three production callers (loader-runtime-candidate,
loader-channel-runtime, loader-cli-registry) to pass activeRecord.
* fix(plugins): snapshot all mutable PluginRecord metadata in transactions (#106647)
Expand activeRecord snapshot from array-only to full cloneRegistryEntry
so scalars (httpRoutes, hookCount), flags (configSchema, enabled,
memorySlotSelected), and Dates are also restored on rollback. Runtime
objects (configUiHints, configJsonSchema, contracts) stay by reference.
Also update the activeRecord JSDoc to reflect the broader contract.
* fix(plugins): restore exact rollback record shape
Co-authored-by: 詹幸心0668001037 <zhan.xingxin@xydigit.com>
* test(plugins): cover date rollback isolation
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: 詹幸心0668001037 <zhan.xingxin@xydigit.com>