* fix(agent_wrapper): release Codex threads after each turn
Loaded Codex threads and their per-thread MCP server subprocesses were
never unloaded from the app-server, growing file descriptors and child
processes monotonically until the wrapper was closed (fd exhaustion,
os error 24). Reply, streaming reply, and compact_session now
unsubscribe the thread in a turn-scoped finally block by default; the
new release_threads=False option restores the previous behavior.
Unsubscribe failures are logged and never break the turn, and threads
remain resumable after being unloaded.
Closesagentscope-ai/ReMe#609
* fix(agent_wrapper): keep tool-context guard on failed release and cover stream startup
A failed thread/unsubscribe left the thread loaded in the app-server
but dropped its tool-context entry, so a later resume with changed
tool_context_id or injected_job_kwargs would silently bypass the
constraint check. Keep the guard entry unless the unsubscribe request
succeeds.
reply_stream now releases the thread from an outer try/finally scoped
right after _open_thread, so threads are also unloaded when turn/start
raises or the caller is cancelled while awaiting it.
* fix(search): accept CLI queries that look like numbers
The CLI parses key=value arguments into typed values, so query=404 reached the search steps as an int and failed on .strip(), and query=NaN or query=Infinity became non-finite floats that the HTTP client cannot encode as JSON and the MCP client sends as null.
Read the query as text in the four search steps, as ChatStep already does, and keep values that float() reads as NaN or infinity as strings.
* fix(search): treat only a missing query as empty
str(query or "") turned query=0 and query=0.0 into an empty string, so those searches still failed with "query cannot be empty". Check for None before converting instead.
The BEAM and LME plugins replace the default search job with their own SearchV2Step, which still called .strip() on the raw value, so query=404 raised AttributeError when either plugin was enabled. Read the query the same way there.
The numeric-query test is now parametrized over the six steps and passes 404, 0 and 0.0 through parse_kwargs first.
* docs(operations): explain that reindex cannot refresh stale chunks
#524 reports that persisted chunks survive a chunker change and are never
re-chunked. Maintainers closed#528 with the position that automatic
invalidation stays out of scope and the recovery path is to clear derived
state and let the watchers rescan, but that path was only described in the
issue thread. The operations guide already warned that reindex does not
rechunk; add the missing half: reindex reuses stored chunks as-is, so a
chunker change requires the re-chunk recovery instead.
* docs(operations): narrow recovery scope and stop the service before cleanup
Review on #585: moving the whole metadata/ tree makes the resource
watcher treat existing resources as newly added, which can update daily
notes - so 'source files are never modified' was too broad, and the
cleanup should target only the affected store's derived state while
preserving unrelated catalogs. The recovery sequence now also stops the
service before moving anything, so shutdown persistence cannot write the
old in-memory state back over the cleanup.
The reindex paragraph drops the repeated 'does not rechunk' explanation
and focuses on when a rebuild from source is needed. English and
Chinese pages stay symmetric.
* docs(operations): simplify rechunk recovery guidance
---------
Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
* fix(stat): put mtime in the answer where the job description promises it
The ``stat`` job is advertised to agents as "Stat path (size, mtime, exists,
is_dir, is_file)", but the answer only ever carried the path, type and size —
``mtime`` lived solely in metadata, and MCP returns only ``response.answer``.
So an agent asking how fresh a file is got no answer, even though the tool
description told it the field was there.
Render mtime in both branches of the answer:
stat: topics/n.md (file, 20 bytes, mtime 2026-09-21T15:50:52.880316)
stat: topics (dir, mtime 2026-09-21T15:50:52.880316)
The value is hoisted into a local so the answer and ``metadata["mtime"]`` are
guaranteed to come from the same ``stat()`` call rather than two reads. The
module docstring claimed the agent receives "size, mtime, mime type, and ...
frontmatter"; it now states that size and mtime are in the answer while mime
and frontmatter stay in metadata, matching reality.
Metadata is unchanged, so programmatic consumers see no difference. This is
the same answer-completeness class as #564, found while auditing which
advertised job fields actually reach the LLM.
* docs(stat): say which consumers actually see mime and frontmatter
Review feedback on #566: the module docstring told the agent it gets
"mime type and ... the parsed frontmatter alongside in metadata", which
reads as though an agent can use those fields to decide whether to
download or parse a file. It cannot: the MCP service returns only
`response.answer` (`mcp_tools.py` -> `return response.answer`), so
`metadata["mime"]` and `metadata["frontmatter"]` reach direct `Response`
consumers but never an MCP caller.
Spell the split out instead of implying one audience: the answer carries
path, type, size and mtime, and an agent that needs the frontmatter has
to read the file rather than stat it. The envelope description below is
unchanged, since it already lists the full metadata shape.
* fix(reindex): return a readable summary so Studio stops showing a placeholder
`ReindexStep` assigned the store's report dict straight to
`response.answer`. ReMe Studio's settings panel already anticipates a string
answer:
typeof result.answer === "string" && result.answer ? result.answer : t("indexRebuilt")
(`reme_studio/app/settings-center.tsx`), so with a dict answer that branch was
unreachable and every rebuild reported the generic "index rebuilt" text. The
operator never saw which scopes ran or how many entries each indexed.
Render the report as one summary line — `Reindexed scope=all: bm25=7,
embedding=5, tag=2` for the composite scope and `Reindexed scope=bm25: 3
indexed` for a single one. The report itself still lands in metadata, so
programmatic consumers are unaffected, and Studio needs no change because its
string branch now fires.
`reindex` is the only answer-carrying consumer of this step; no test asserted
the answer content, only metadata, so nothing else moved.
* chore(reindex): tighten the renderer and deduplicate the summary test
Review on #565: the helper's docstring carried the Studio background
that already lives in the PR description; the intermediate per_scope
dict collapses into the join generator; and the all-scope delegation
test now uses distinct counts (7, 5, 2) so it alone pins both the exact
summary answer and the full metadata report, replacing the overlapping
summary test.
* refactor(reindex): share summary return formatting
---------
Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
* feat(integrations): add native Claude Code and Codex memory plugins
* docs(integrations): make plugin installation the coding agent entry point
* feat(integrations): configure plugin connections from user settings
* refactor(codex): use MCP tools and native plugin settings
* fix(codex): restore plugin hooks on current runtimes
* docs(codex): expand setup guide and reserve screenshot slots
* feat(codex): add configurable memory consolidation and status
* feat(codex): merge connection checks into a tabbed status app
* docs(codex): diagnose blocked status panel sandbox loading
* fix(codex): simplify status panel layout for narrow cards
* docs(codex): focus guides on connecting and using ReMe
* docs(codex): specify validated CLI and desktop version requirements
* feat(codex): add ReMe branding to plugin icons
* docs(codex): prepare manual screenshot workflow
* fix(codex): simplify ReMe status layout and activity
* docs(codex): explain Hook loading and local project context
* fix(codex): keep status refresh clear of host close control
* fix(codex): retain status resources for active MCP connections
* docs(codex): add real desktop screenshots to usage guides
* fix(integrations): address memory capture and consolidation review
* fix(codex): preserve capture endpoint during background delivery
* docs(skills): include image suffixes in the resource watcher list
The default resource_watch_loop has watched image suffixes since #526 and
auto_resource renders them into caption cards, but the skill still listed
only the seven text types. An agent reading the skill would conclude that
images dropped under resource/ are never processed.
* docs(skills): clarify image captioning requirements
---------
Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
benchmark.yaml's python_execute job advertised a `timeout` parameter, but
`timeout` is one of the CLI's client-selection kwargs (reme/reme.py pops it
before the payload is sent), so `reme python_execute code=... timeout=300`
never delivered the timeout to the job. The value silently became the HTTP
client's request timeout while the subprocess kept the 60s default, so
benchmark code that needs longer was killed at 60s with no hint why. HTTP
and MCP callers were unaffected.
Rename the parameter to `python_timeout`, mirroring how the shell job
already avoids the same collision with `shell_timeout`. The step prefers
the new name and still accepts the legacy `timeout` context key so
existing benchmark configs keep working. A new guard test fails if any
job in reme/config/*.yaml or a plugin plugin.yaml declares a
client-reserved parameter name again.
* fix(docs): publish OpenClaw and Hermes integration figures
The generated /en/integrations/openclaw, /zh/integrations/openclaw and
/en/integrations/hermes pages are built from the plugin READMEs, which
reference local figures/. Only the dsh and Studio READMEs had their
./figures/ links rewritten to site paths and their figure directories
copied into the build, so every screenshot on those three pages resolved
to /<language>/integrations/figures/*.png and 404'd. verify-build.mjs
only checks <a> links, never <img> sources, so the build stayed green.
Mirror the dsh pattern: rewrite the figure links to /figures/openclaw/
and /figures/hermes/, copy both figure directories into public/figures/,
add the missing language-cross link for the Hermes page, and cover all of
it in the generated-content tests.
* ci(docs): watch the new integration figure directories
The figures this PR adds under integrations/hermes_agent/figures/ and
integrations/openclaw/figures/ were not in either docs workflow's path
filter, so a follow-up commit that only touches a PNG would skip the docs
build and the broken-reference tests. Add both globs to the pull_request
filter in ci-docs.yml and the push filter in deploy-docs.yml, matching how
integrations/dsh/figures/** and reme_studio/figures/** are already listed.
Requested in review on #586.
* test(docs): validate all integration screenshot references
---------
Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
* feat(docker): add container deployment and multi-platform release workflow
* fix(llm): initialize providers on model access and preserve runtime injection
* test(llm): keep rejected model updates independent of credentials
* refactor(plugins): move BaseAgenticAnswerStep into lme/beam plugins
Move the shared benchmark answer base class from the core
reme.steps.benchmark package into each plugin's own src tree
(reme_lme.base_agentic_answer / reme_beam.base_agentic_answer) with
absolute imports, drop the core benchmark steps package, and update
plugin READMEs accordingly.
* refactor(plugins): simplify benchmark answer steps
* docs(plugins): clarify benchmark answer step migration
---------
Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
* docs: show ReMe ecosystem on homepage
* fix(docs): prevent hero title from overlapping ecosystem column
At 1366x768 the English headline used white-space: pre inside a
left column squeezed to ~538px by the 650px right column, so it
overflowed onto the ecosystem map (review comment on #568).
- use white-space: pre-wrap so the headline wraps within its column
- stack the hero to a single column below 1680px (benchmark/traffic
sections keep their original 1320px breakpoint)
- pin the ecosystem column to 650px and cap the headline at 76px so
the two-line headline fits beside it at 1681px and wider
Co-Authored-By: Claude Code <noreply@anthropic.com>
---------
Co-authored-by: Claude Code <noreply@anthropic.com>
* feat(scripts): plot cumulative star growth over a configurable period
github_star_growth.py only reported daily new stars. Reconstruct the running
star total from the repository's current count and the daily increments, and
render it as an SVG line chart so the growth trend is readable at a glance.
- add --period (default 90d) accepting d/w/m/y units, keep --days as an alias
- crop the vertical axis near the data instead of anchoring it at zero
- label the chart with the plotted date range and the final star count
- report the star count at the start of the window on stderr
Co-Authored-By: Claude <noreply@anthropic.com>
* style(scripts): add trailing comma expected by pre-commit
The add-trailing-comma hook rewrites this call, so CI failed on the first
push of #562. No behaviour change.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>