Commit graph

70 commits

Author SHA1 Message Date
Fabio Scarsi
37083593d6 fix(search): content-addressed SkillRanker cache key
The embedding cache was keyed by skill_id alone, so any edit to a
SKILL.md body or description produced stale embeddings that
get_or_compute_embedding kept serving until a manual invalidate_cache
call or a file deletion. Previously this was mostly invisible because
select_skills_with_llm was the only caller exercising the cache; after
the preceding commit wires search_skills through the same path the
staleness becomes observable on every MCP query.

Use "{skill_id}:{sha256(embedding_text)[:16]}" as the cache key, so
any change to the text produced by _build_embedding_text (name +
description + body, truncated to SKILL_EMBEDDING_MAX_CHARS) causes
an automatic cache miss and a fresh embedding. Both
get_or_compute_embedding and _embedding_rank are updated.

Bounded growth: on each successful new compute, older entries with
the same "{skill_id}:" prefix are pruned in the same write. Net
result: at most one cached embedding per skill_id at any time, aside
from transient migration state.

Backward compatibility: existing pickle files keyed by skill_id alone
are migrated in place on first lookup (no API call needed); the old
key is dropped after migration.

invalidate_cache(skill_id) now removes every content-addressed entry
and any legacy entry for that skill_id, so historical versions do
not leak across evolutions.

Functional benchmark on a 28-skill local registry with
text-embedding-3-small via OpenRouter: top-1 match identity preserved
on all test queries, score drift below 0.001, warm latency
~260-400ms/query (unchanged from the previous commit).
2026-04-18 12:44:47 +02:00
Fabio Scarsi
fc9534876f fix(search): wire search_skills to SkillRanker embedding cache
Both paths in search_skills/hybrid_search_skills now go through a
shared SkillRanker singleton:

- SkillSearchEngine._bm25_phase: previously instantiated a fresh
  SkillRanker per call, reloading the pickle cache each time.
- hybrid_search_skills candidate loop: previously generated
  embeddings via generate_embedding on every query, ignoring the
  persistent cache entirely.

The persistent pickle at
.openspace/skill_embedding_cache/skill_embeddings_v1.pkl is
reused across invocations and survives process restarts.
Candidates without a stable skill_id are skipped to avoid cache
key collisions.

On a 28-skill local registry with text-embedding-3-small via
OpenRouter, query latency drops from 8-14s to ~300ms after
warm-up. Top-1 match identity is preserved on all test queries
(score drift <0.001).

Cloud candidates that already carry _embedding from the
server-side search endpoint are skipped and unchanged.
2026-04-18 11:52:15 +02:00
xlrrrr
d1e367d0ed feat: track evolution candidate processing lifecycle 2026-04-16 22:07:26 +08:00
xlrrrr
020a879944 feat: track evolution candidate processing lifecycle 2026-04-16 22:04:22 +08:00
Xu Lingrui
21fb98bb36 fix: resolve macOS dependency conflict (#78)
fix: resolve macOS dependency conflict in extras
2026-04-16 20:33:10 +08:00
xlrrrr
59095d52c2 fix: separate atomacos import from AppKit to avoid disabling all macOS features
The original change removed atomacos from dependencies but left it
bundled in the same try/except as AppKit.  Without atomacos installed,
the ImportError made MACOS_LIBS_AVAILABLE=False, silently disabling
every macOS feature (screenshots, window control, etc.) even though
they never use atomacos.

- Split import into independent try/except blocks
- Guard get_accessibility_tree() with ATOMACOS_AVAILABLE
- Condense redundant comments in requirements files
- Tighten README note into a blockquote
2026-04-16 20:31:26 +08:00
liyikradlee
22d6864df2 Ignore local virtualenv 2026-04-12 14:13:01 +08:00
liyikradlee
874badae69 Fix macOS dependency conflict 2026-04-12 14:12:16 +08:00
xlrrrr
79a98abda7 fix: CAPTURED skills write to correct host agent skill dir 2026-04-10 20:57:17 +08:00
Dennis-yxchen
8e6d49df74
Merge pull request #75 from HKUDS/codex/visibility-private-openspace-20260405
Fix cloud visibility compatibility
2026-04-09 22:37:12 +08:00
Dennis-yxchen
c49696ed7d Fix cloud visibility compatibility 2026-04-09 22:36:09 +08:00
spidercatfly
681c3a8b05 update readme 2026-04-09 22:16:06 +08:00
Xu Lingrui
f01d408ac4
feat: add communication adapters and agent refactoring (#74) 2026-04-09 22:06:38 +08:00
spidercatfly
4791133e11 update readme 2026-04-07 20:44:53 +08:00
Xu Lingrui
114f06bd41
feat: support SSE and streamable HTTP for OpenSpace MCP
* feat: add HTTP MCP startup modes

* feat: add HTTP MCP startup modes

* feat: add HTTP MCP startup modes
2026-04-07 20:06:01 +08:00
Dennis-yxchen
b0021b46bb
Merge pull request #61 from HKUDS/pr-60
Pr 60
2026-04-06 20:14:44 +08:00
Dennis-yxchen
a23792a66b fix: tighten pr-60 review follow-ups 2026-04-06 20:13:42 +08:00
Dennis-yxchen
a3a73406a5 fix: resolve pr-60 review regressions 2026-04-06 19:18:22 +08:00
yc111233
f3a064df1c fix: address 8 runtime bugs found during code review
1. Race condition on _addressed_degradations (evolver.py) — add asyncio.Lock
2. Silent exception swallowing in wait_background (evolver.py) — log failures
3. Workspace cleanup could delete user files (tool_layer.py) — add mtime guard
4. WAL cleanup without lock check (store.py) — probe for DB lock first
5. Edit distance threshold too loose (analyzer.py) — adaptive threshold + ambiguity rejection
6. Message truncation drops context (grounding_agent.py) — add truncation notice
7. Whitespace-only empty response not detected (grounding_agent.py) — strip before check
8. Tool name reverse parsing with __ (client.py, manager.py) — use rsplit
2026-04-06 01:02:35 +08:00
spidercatfly
1bd1a3d377 clean up LLM credential resolution 2026-04-05 15:13:07 +08:00
spidercatfly
81f375e8bc update readme 2026-04-04 00:05:18 +08:00
Dennis-yxchen
456184f6e1
Merge pull request #51 from HKUDS/review/xzq-batch-20260403
Review/xzq batch 20260403
2026-04-03 23:51:09 +08:00
Dennis-yxchen
34d82b735e fix: make tool fallback conservative
Co-authored-by: xzq.xu <zhiqiang.xu@nodeskai.com>
2026-04-03 23:44:38 +08:00
xzq.xu
af1eb5bbe6 fix(security): stop leaking Python tracebacks to MCP clients
Error handlers in execute_task, fix_skill, and upload_skill returned
traceback.format_exc() to MCP clients, exposing internal file paths,
code structure, and potentially sensitive details. The full traceback
is already logged server-side via logger.error(exc_info=True).

Remove the traceback field from client-facing error responses and
clean up the unused traceback import.

Closes #19

Made-with: Cursor
2026-04-03 23:10:28 +08:00
xzq.xu
f89ea89ffb fix: use resolved tool_obj for fallback tool execution
When the LLM returns a short tool name that doesn't match the deduped
key in tool_map, the fallback scan correctly resolves tool_obj via
schema.name. However the execution branch still checked
`tool_name not in tool_map` and passed `tool_map[tool_name]`, so
fallback-resolved tools were never executed.

Change the condition to check `tool_obj is None` and pass `tool_obj`
directly to _execute_tool_call.

Closes #15

Made-with: Cursor
2026-04-03 23:10:28 +08:00
xzq.xu
6f581f6de4 fix: add missing Logger.set_level() method
__main__.py calls Logger.set_level(args.log_level) when --log-level
is passed, but the method did not exist on Logger, causing an
AttributeError. Add set_level(level: str) that resolves the name
to a logging constant and reconfigures via configure(force=True).

Closes #13

Made-with: Cursor
2026-04-03 23:10:28 +08:00
xzq.xu
171c1b76f8 fix: replace ErrorCode enum calls with GroundingError raises
ErrorCode is a str Enum whose members are not callable. Calling
`raise ErrorCode.SESSION_NOT_FOUND(name)` produces a TypeError
instead of the intended session-not-found error. Replace all 5
occurrences with `raise GroundingError(..., code=ErrorCode.SESSION_NOT_FOUND)`.

Closes #11

Made-with: Cursor
2026-04-03 23:10:28 +08:00
Xu Lingrui
c15229a82a
fix(frontend): keep product proper nouns in English for zh locale (#50) 2026-04-03 23:09:53 +08:00
Xu Lingrui
e80c70e9c9
feat(frontend): add Chinese (zh) i18n support (#49) 2026-04-03 22:34:47 +08:00
Xu Lingrui
565f09f1c7
Merge pull request #44 from HKUDS/feat/cloud-search-api-upgrade
feat: migrate cloud search to server-side embedding endpoint
2026-04-02 23:22:46 +08:00
spidercatfly
e1a8524475 feat: migrate cloud search to server-side embedding endpoint 2026-04-02 23:17:44 +08:00
spidercatfly
f05514845d chore: remove outdated test files 2026-04-02 22:18:31 +08:00
Dennis-yxchen
2fb8024ff6 fix: pass max_iterations in no-skill path and unique workflow IDs
- Forward resolved max_iterations to grounding agent in no-skill execution path
- Use hash-based workflow ID to prevent collision across roots and separator ambiguity

Co-authored-by: wul48527-code <wul48527-code@users.noreply.github.com>
2026-03-31 19:08:56 +08:00
Dennis-yxchen
028c5b01f9 fix: use hash-based workflow ID to prevent separator collisions
The previous __-joined scheme was not injective: a directory named
a__b and a nested path a/b both mapped to the same ID. Use a sha256
hash suffix of the resolved path instead, which is collision-free
and keeps the dir name as a human-readable prefix.

Added regression test for separator collision case.
2026-03-31 17:38:39 +08:00
Dennis-yxchen
0f2dcb896b Merge workflow-id-collision into combined fix branch 2026-03-31 17:25:09 +08:00
Dennis-yxchen
4032fe682d test: add regression tests for max_iterations in no-skill path 2026-03-31 17:24:12 +08:00
Dennis-yxchen
e48e22afc8 fix: use unique workflow ID to prevent collision across roots
workflow_dir.name was used as the discovery key and API ID, so two
different WORKFLOW_ROOTS containing a leaf directory with the same
name would silently drop one. Use root name + relative path joined
with __ as a stable unique ID instead.

Co-authored-by: wul48527-code <wul48527-code@users.noreply.github.com>
2026-03-31 17:18:38 +08:00
xlrrrr
29a3869d49 fix: improve MiniMax compatibility 2026-03-31 17:18:13 +08:00
Dennis-yxchen
64a3076058 fix: pass max_iterations to grounding agent in no-skill execution path
Without this, the no-skill path ignores the resolved max_iterations
and uses whatever default the agent has, instead of the configured
grounding_max_iterations value.

Co-authored-by: wul48527-code <wul48527-code@users.noreply.github.com>
2026-03-31 17:03:00 +08:00
Dennis-yxchen
f845c5f7fb fix(security): harden zip extraction and import_skill against path traversal
- Add resolve() + is_relative_to() check in _extract_zip() to block
  nested traversal entries like nested/../../escape.txt
- Sanitize server-provided skill name in import_skill() to prevent
  directory escape via malicious record metadata
- Add 6 regression tests covering both attack vectors

Closes #17

Co-authored-by: LeftX <xzq-xu@users.noreply.github.com>
2026-03-31 16:23:56 +08:00
xlrrrr
63b01cfcef fix: CLI entry point now respects OPENSPACE_MODEL and OPENSPACE_LLM_* env vars 2026-03-31 15:36:13 +08:00
Dennis-yxchen
c494dcf12a Merge pull request #7 from who96/codex/pr2-issue3-startup-fix
mcp: keep local skill search lightweight and refreshable
2026-03-31 15:25:16 +08:00
Dennis-yxchen
1620261783 test: add edge case coverage for local skill search 2026-03-31 15:25:08 +08:00
who96
fb02862d44 Refresh local registry for local skill search 2026-03-31 15:20:23 +08:00
who96
f4451aa0ac mcp: keep local skill search lightweight 2026-03-31 15:20:23 +08:00
Dennis-yxchen
ccda314d34 Merge pull request #30 from voidborne-d/fix/fix-skill-already-registered
fix: register_skill_dir returns existing SkillMeta for already-registered skills
2026-03-31 15:01:26 +08:00
Dennis-yxchen
aa16419e46 docs: update register_skill_dir docstring to reflect idempotent return 2026-03-31 14:58:01 +08:00
Dennis-yxchen
90b2ffab6a
Merge pull request #32 from mvonrenteln/fix/pin-litellm-safe-version
fix: pin litellm to <1.82.7 to mitigate PYSEC-2026-2 supply-chain attack
2026-03-30 21:04:23 +08:00
Marc von Renteln
4f61cb2fa1 fix: pin litellm to <1.82.7 to avoid PYSEC-2026-2 supply-chain attack
Versions 1.82.7 and 1.82.8 of litellm were published on March 24, 2026
and contained malicious code that exfiltrated credentials (SSH keys,
cloud credentials, .env files, API keys) to an attacker-controlled domain.

Pin the dependency to >=1.70.0,<1.82.7 in both pyproject.toml and
requirements.txt as a stopgap until litellm can be replaced with direct
provider SDK calls.

See: https://github.com/HKUDS/OpenSpace/issues/31
Ref: PYSEC-2026-2, BerriAI/litellm#24521
2026-03-29 11:16:10 +02:00
chaohuang-ai
11bdf128d9
Update README.md 2026-03-29 10:44:38 +08:00