Commit Graph
659 Commits
Author SHA1 Message Date
Andrew Park d83ae02c6b hybrid: wire Advisors + ToolOrchestra workers through mini-SWE-agent
Same 'swe_use_agent_loop' opt-in flag as Conductor/SkillOrchestra.

Advisors (swe mode):
- Initial executor pass = full mini-SWE-agent run on a fresh workdir.
- Advisor (local) critiques the produced patch (sees summary + diff).
- Final executor pass = SECOND mini-SWE-agent run on ANOTHER fresh
  workdir, with the initial summary + advisor feedback folded into the
  prompt. Don't reuse the initial workdir — that would smuggle the
  bad-fix into the new attempt; the final pass should incorporate only
  the parts of the advisor feedback that hold up.

ToolOrchestra (swe mode):
- One SHARED workdir created at start of run, cloned from the SWE-bench
  repo at base_commit.
- Each call_worker action whose worker is a solver (vllm/anthropic)
  runs as a mini-SWE-agent subloop on the shared workdir. Web-search
  workers stay one-shot (search isn't an agent loop). OpenAI workers
  fall back to one-shot too (loop tool format isn't wired for OpenAI).
- After loop ends, the framed final answer wraps the working-tree
  git diff so the swebench scorer picks it up.
2026-05-15 13:42:10 -07:00
Andrew Park e71342b502 hybrid: wire Conductor + SkillOrchestra workers through mini-SWE-agent
Add 'swe_use_agent_loop' cfg flag to both paradigms. When on AND the
task is SWE-bench-shaped (has repo + base_commit + problem_statement),
the worker call is replaced by a run_swe_agent_loop subloop.

Conductor: one shared workdir across all plan steps so step N+1 builds
on step N's edits. Each step's subtask becomes the initial_prompt; the
worker's model + endpoint determines the agent-loop backbone
(vllm → local, anthropic → cloud, openai workers fall back to one-shot
since the agent-loop tool format isn't wired for OpenAI today). After
the last step, the framed final answer is the working-tree git diff.

SkillOrchestra: same flag, no workdir sharing (just one worker invoked).
Whichever of local-qwen / cloud-opus the router picks runs as
run_swe_agent_loop instead of a single completion.

Cells stay one-shot by default — set method_cfg.swe_use_agent_loop=true
to opt in. Smoke imports clean; behavior on non-SWE benches unchanged.
2026-05-15 13:39:22 -07:00
Andrew Park db70ab56d1 hybrid: extract run_swe_agent_loop() for reuse across paradigms
Refactor MiniSWEAgent so the workdir setup + multi-turn bash loop +
diff extraction live in a top-level function. Paradigms can now call
run_swe_agent_loop(task, backbone, model, ...) to replace their
one-shot worker call with a real agent loop on SWE-bench tasks.

MiniSWEAgent itself becomes a thin LocalCloudAgent wrapper around the
function (~30 lines). Behavior unchanged for the standalone agent;
trace event kinds still use 'mini_swe_*' prefix (paradigms pass
trace_prefix= to namespace their subloops in the log).
2026-05-15 13:37:14 -07:00
Andrew Park c349fa1316 hybrid: vendor mini-SWE-agent v2 (~330-line single-model bash-loop agent)
Adds `MiniSWEAgent` — the environment-interaction loop the paradigms
were missing for SWE-bench. Every existing paradigm (Minions, Conductor,
Archon, Advisors, etc.) is an *orchestration* loop but the worker
ultimately runs one-shot "predict the patch from the issue text." No
shell, no repo browsing, no test execution. That's why every paradigm
caps near 0.30 on SWE-bench-Verified — the model literally cannot look
at the code.

mini-SWE-agent fills the gap: one bash tool, a per-task git clone, and
a multi-turn loop that lets the model grep / cat / sed / pytest its way
to a real fix. Upstream (https://github.com/swe-agent/mini-swe-agent)
gets ~0.77 on SWE-bench-Verified with a frontier backbone.

This is the vendored option (a) from the plan — no Docker, no upstream
dependency, ~330 lines total:

- `MiniSWEAgent._run_paradigm`: clone the SWE-bench repo into a tempdir,
  run the loop, extract the final diff via `git diff`, wrap it in a
  ```diff fence so the existing swebench scorer reads it.
- Two backbone modes (`cfg["backbone"]`): `cloud` (Anthropic, multi-turn
  with `tools=[bash]`), `local` (vLLM OpenAI-compatible with the same).
  Both routes integrate with the LocalCloudAgent trace buffer — every
  bash invocation lands as a `mini_swe_bash` event with full command,
  stdout, stderr, exit code, latency.
- Each `bash` command runs as a fresh subshell in the workdir with a
  configurable timeout and 10K-char output cap.
- No `submit` tool — the loop ends when the model produces a turn with
  no tool_calls, or `max_turns` hits.

Safety: model can `rm -rf` its own workdir. Workdir is disposable.
Network is available (pip etc.). Don't run on a host with secrets in
$CWD. Docker sandboxing is a follow-up.

Registry: `registry/mini_swe_agent.toml` ships three cells (n=3 cloud,
n=30 cloud, n=3 local-backbone). Smoke (n=1, max_turns=10): the agent
explored the django repo, edited `django/contrib/auth/forms.py`, ran
the relevant tests, produced an 829-char patch. ~$0.25 / 75s per task
with Opus 4.7 at max_turns=10. Cost+time will scale roughly linearly
with max_turns; production cells use max_turns=30-50.

Follow-up: wrap Minions/Conductor workers in this loop so the
orchestration paradigms get the same 0.30 → ~0.77 jump (task #13).
2026-05-15 13:09:56 -07:00
Andrew Park 15564b4b38 engine: capture server_tool_use + web_search_tool_result in cloud Anthropic path
Same gap as the hybrid agents had: `_generate_anthropic` walked `resp.content`
and only matched `type == "tool_use"` for tool calls. Anthropic server-side
tools (web_search) emit `server_tool_use` blocks for the model's actual
query and `web_search_tool_result` blocks for the result payload — both
were silently dropped. So every OpenJarvis agent using Anthropic web_search
had its search queries and results invisible in traces.db.

Fix:

- Add `_serialize_anthropic_block(block)` — recursive JSON-safe converter
  that handles text / tool_use / server_tool_use / web_search_tool_result
  / tool_result / thinking blocks, preserving nested citation content.
- `_generate_anthropic` now returns a full `content_blocks` list (every
  block in order) plus extended `tool_calls` (tool_use + server_tool_use,
  with a `server_side` flag) and a new `tool_results` field
  (web_search_tool_result + tool_result).
- `instrumented_engine` propagates these into the INFERENCE_END event.
- `TraceCollector._on_inference_end` records them on the generate step.

Backward compat: existing callers that only read `result["tool_calls"]`
still see the same shape; new fields are additive.

Confirmed against a real Opus web_search call: serializer captures the
`server_tool_use` block with the actual query (`{"query": "when did
SpaceX first launch Starship"}`), the `web_search_tool_result` block
with 10 nested citation entries, and the synthesizing text block.
2026-05-15 12:17:30 -07:00
Andrew Park 2f1a3671ce hybrid: capture tool calls + tool results + structured content in trace events
Previous trace events only stored the joined `text` blocks from Anthropic
responses and `message.content` from OpenAI/vLLM — every tool_use block,
server_tool_use block, web_search_tool_result, and OpenAI-style tool_calls
list was being thrown away.

Now each call event includes:

Anthropic events:
- `content_blocks`: full list of every block the model emitted, with all
  fields preserved (text / tool_use / server_tool_use /
  web_search_tool_result / thinking). Nested content (e.g. search-result
  citations) recurses.
- `tool_calls`: filtered subset (tool_use + server_tool_use).
- `tool_results`: filtered subset (web_search_tool_result + tool_result).
- `tools_declared`, `tool_choice`, `output_config`, `stop_reason`.

OpenAI / vLLM events:
- `tool_calls`: serialized `message.tool_calls` (id, function name, args).
- `reasoning_content`: thinking-model intermediate reasoning if present.
- `tools_declared`, `tool_choice`, `finish_reason`.

Confirmed against a real Anthropic call with `tools=[web_search]`,
`tool_choice={"type":"any"}`: the resulting event contains the
`server_tool_use` block with the actual search query, the
`web_search_tool_result` with 10 nested citation blocks, and all
subsequent text blocks the model emitted to synthesize the answer.
2026-05-15 12:08:57 -07:00
Andrew Park 850062d715 hybrid: full per-task trace logging to experiments/<cell>/logs/<task_id>.json
Previously the runner created the `logs/` directory but never wrote
anything. Wire a thread-local trace buffer through the SDK helpers so
every cloud/local call is captured automatically, plus paradigm hooks
for the events that bypass the helpers (Minions's library protocol,
Archon's layer pipeline, conductor's plan + step dispatch, ToolOrchestra
action turns, SkillOrchestra routing decision).

Mechanics:
- `_TRACE_STATE` is a `threading.local()` — `run()` opens a fresh trace
  per task and writes a digested JSON to `<log_dir>/<task_id>.json` in
  the `finally` block (so we get a record even on hard failures).
- `_call_anthropic` / `_call_openai` / `_call_vllm` append full events
  (system, user, response, token counts, latency, model, schema config)
  to the active trace.
- `LocalCloudAgent.record_trace_event(...)` is the public hook for
  paradigms with library-side execution.
- Nothing is truncated — full prompts, responses, and tool-call payloads
  land in the JSON.
- Runner threads `log_dir` through `context.metadata["log_dir"]`.

Verified: re-running `advisors-gaia-qwen9b-opus-3` produces three
`logs/gaia-*.json` files, each ~13KB with all 3 turns (cloud executor →
local advisor → cloud final) and the full text of each prompt/response.
2026-05-15 12:04:25 -07:00
Andrew Park e21e1bbad6 evals: expose raw question / problem_statement in dataset metadata
GAIADataset and SWEBenchDataset both build a formatted prompt (`rec.problem`)
and discard the raw input text. The hybrid paradigm runner needs the raw
text so it can apply the GAIA / SWE-bench answer-format instructions from
`agents.hybrid._prompts.format_prompt(task)` — otherwise paradigms see a
double-wrapped prompt and the GAIA "FINAL ANSWER: <x>" rule is missing.

Additive change — adds `metadata["question"]` for GAIA and
`metadata["problem_statement"]` for SWE-bench. No existing consumer
breaks; the runner now picks up the raw text correctly.

Verified end-to-end with `python -m openjarvis.agents.hybrid.runner
--cell advisors-gaia-qwen9b-opus-3`: 3/3 tasks, acc=0.667, $0.04 — matches
the hybrid harness's cell exactly.
2026-05-13 15:27:48 -07:00
Andrew Park a03e659bc9 hybrid: ship CLI runner + registry + new_experiment.sh + README
Final piece — make the ported paradigms runnable end-to-end through the
same flow as the hybrid harness:

- `runner.py`: `python -m openjarvis.agents.hybrid.runner --cell <name>`.
  Loads cells from packaged registry TOMLs, constructs the registered
  agent via AgentRegistry, iterates tasks from OpenJarvis's existing
  GAIADataset / SWEBenchDataset, scores via gaia exact-match or the new
  Modal-backed SWE-bench harness scorer, writes
  `results.jsonl`+`summary.json` in the same shape as the hybrid harness
  so existing rescore / dashboard scripts work unmodified. Supports
  resume (drops errored rows), per-cell flock, ThreadPoolExecutor
  concurrency, and the same per-row heartbeat format.

- `registry/{advisors,archon,conductor,minions,skillorchestra,toolorchestra}.toml`:
  35 cells ported verbatim from the hybrid harness — same models, same N,
  same `method_cfg` — so OpenJarvis runs should reproduce the numbers in
  `hybrid-local-cloud-compute/docs/results.md`. ToolOrchestra cells
  rewritten from the original NotImplementedError stubs to point at the
  prompted port (cloud-as-orchestrator, no Nemotron-Orchestrator-8B).

- `scripts/new_experiment.sh`: mirror of hybrid's scaffolder. Maps
  shortnames (`qwen3.5-27b`, `claude-opus-4-7`, …) to full HF ids +
  endpoints, picks method-appropriate `method_cfg` defaults, appends a
  `[cells.<name>]` block to the right registry TOML.

- `README.md`: quickstart, paradigm taxonomy, reproducibility table
  pointing at the hybrid results for headline numbers.

End-to-end smoke: `python -m openjarvis.agents.hybrid.runner --help` works,
all 6 agents register, all 35 cells load.
2026-05-13 15:21:45 -07:00
Andrew Park 7418cf5736 hybrid: port Modal-backed SWE-bench-Verified harness scorer
Adds `SWEBenchHarnessScorer` alongside the existing structural-only
scorer. Hands one prediction at a time to `python -m swebench.harness.
run_evaluation`, parses the report JSON it writes, returns the resolved
bool. Backend selectable via `SWEBENCH_BACKEND` env var
(modal default, docker fallback).

Carries forward the two upstream-swebench patches from the hybrid
harness, both idempotent and lazy:

1. **Modal cgroup-v2 fix** — `swebench/harness/modal_eval/run_evaluation_modal.py`
   writes to `/sys/fs/cgroup/cpu/cpu.shares` (cgroup v1). Modal v2 sandboxes
   are cgroup v2 — the path doesn't exist and every sandbox died on the
   write. This was the root cause of "Modal harness failing 100%"; wrapping
   `set_cpu_quota` in try/except fixes it.

2. **Rescore `*_ids` fix** — older swebench wrote `resolved_instances` as
   a list; current swebench puts the count there and the actual ids in
   `resolved_ids`. Reading `*_ids` first; falling back to the list-typed
   legacy field if the user is on an older install.

Patch extraction supports the same three formats as the hybrid harness:
fenced `\`\`\`diff`, fenced raw (`\`\`\`\ndiff --git`), and unfenced
`diff --git`.
2026-05-13 15:18:03 -07:00
Andrew Park 9e253cac27 hybrid: port ToolOrchestraAgent (prompted, no RL)
Inference-only port of NVlabs ToolOrchestra (arXiv:2511.21689). The
paper's RL-trained Nemotron-Orchestrator-8B is NOT in the loop — the
hybrid harness adapter is a documented stub for exactly that reason
(needs a separate vLLM srun for the 8B checkpoint, a FAISS wiki
retriever, a Tavily key, and an upstream refactor).

This port keeps the same scope discipline: a cloud model plays the
orchestrator role and dispatches to a mixed pool of workers (local
Qwen for cheap extraction, Anthropic web_search for unknowns, Opus
4.7 / gpt-5-mini for hard reasoning or final synthesis). Reactive
multi-turn loop emitting JSON action objects per turn; forces a
final answer at the budget cap; hard fallback to the strongest worker
on persistent parse failure.

Treat results as preliminary until a real Orchestrator-8B deployment
exists — included here so OpenJarvis has registry entries for all six
paradigms and so the distillation pipeline can slot ToolOrchestra in
alongside the rest.

Registered as `toolorchestra`. The hybrid harness `toolorchestra_adapter.py`
remains a NotImplementedError stub; this is the first runnable version.
2026-05-13 15:16:41 -07:00
Andrew Park 1dc73d7b86 hybrid: port SkillOrchestraAgent (router-only deployment phase)
Inference-time skill-aware router from arXiv:2602.19672. The paper's
4-phase explore/learn/select pipeline is out of scope (needs multi-model
serving + FRAMES wiki retriever + a multi-hour learning loop) — the
hybrid harness reproduced only the deployment-time `select_agent()`
path with a hand-curated skill taxonomy + per-agent competence priors
calibrated to Qwen3.5-27B-FP8 vs Opus 4.7. This port keeps that scope.

Per task: Opus reads the question, picks skill weights from a 7-skill
catalog (factual_recall, multi_step_reasoning, arithmetic, web_grounding,
long_text_extraction, format_compliance, code_or_logic), scores each
agent under `score = weighted_competence - 0.5 * avg_cost`, routes to
the winner. JSON schema enforced via Anthropic `output_config`; balanced-
brace fallback if the SDK ignores the schema. Soft-fail row on
unparseable JSON to match hybrid's `err=1` on n=30.

Hybrid harness result: `skillorchestra-gaia-qwen27b-opus-30` = 0.500 acc,
$0.02/task — 30× cheaper than baseline-cloud (0.567 / $0.66) at ~7pp
lower accuracy. Best cost-efficient GAIA paradigm.

Registered as `skillorchestra`. Ported from
`hybrid-local-cloud-compute/adapters/skillorchestra_adapter.py`.
2026-05-13 15:15:29 -07:00
Andrew Park 628bc9dbdd hybrid: port ArchonAgent (ScalingIntelligence/Archon inference-time search)
Layered (generator → ranker → fuser) sampling: K local generators propose
candidates, cloud ranker scores them, cloud fuser synthesizes the final
answer. Paper: arXiv:2409.15254. Two presets: `ensemble_rank_fuse` (the
full layered pipeline) and `single_local` (debug shim).

Carries the same patch story as the hybrid adapter:
- Eager-import stubs for groq/google/litellm so Archon's `utils.py` loads
  in the OpenJarvis venv without those deps.
- Custom `vllm_local` model_type wired into Archon's GENERATE_MAP via a
  per-run closure (endpoint can vary per cell).
- OpenAI / Anthropic generators replaced with token-tallying wrappers so
  we can charge cost — Archon ignores `usage` by default.
- Opus 4.7 temperature stripping at the SDK level.

Archon library is lazy-imported. The hybrid clone at
`hybrid-local-cloud-compute/external/Archon/src` is the default
location; override with `ARCHON_SRC` env var.

Hybrid harness results: `archon-gaia-qwen27b-opus-ensemble-K5-30` =
0.333 acc, $0.20/task; `archon-gaia-qwen27b-singlelocal-30` = 0.033 acc.
Underperforms baseline-cloud on GAIA — included for completeness, not as
a recommended paradigm.

Registered as `archon`. Ported from
`hybrid-local-cloud-compute/adapters/archon_adapter.py`.
2026-05-13 15:14:30 -07:00
Andrew Park 3178ce10a9 hybrid: port MinionsAgent (HazyResearch Minions protocol)
Cloud supervisor decomposes + reads back; local worker(s) do bulk
reading. Two modes: `minion` (single worker, default) / `minions`
(parallel workers + aggregator).

Carries forward every compatibility patch from the hybrid adapter so the
n=500 numbers transfer:
- Strip `temperature` for Opus 4.7+ (rejected with 400).
- Inject server-side `output_config` JSON schema per supervisor turn
  (first-turn `{reasoning, message}` vs conversation-turn anyOf
  `{decision, message|answer}`), picked by sniffing the prompt for
  `"decision": "provide_final_answer"`.
- Replace `minions._extract_json` with a JSON-first wrapper.
- Inject `timeout=600`/`max_retries=5` into `anthropic.Anthropic()` so
  Minions's bare-client construction doesn't 60s-timeout under SWE-bench
  concurrency=8.
- GAIA-only `web_search` prefetch so the worker has a real doc to read.

Soft-fail row on JSONDecodeError/BadRequestError/prompt-too-long — same
deterministic-failure handling that produced the n=165 GAIA `err=6` rows
in the hybrid harness without crashing the cell.

`minions` library import is lazy; install via
`uv pip install -e /matx/u/aspark/hybrid-local-cloud-compute/external/minions`.

Hybrid harness results being reproduced:
- `minions-swebenchverified-qwen27b-opus-500` = 0.274 acc, $0.09/task
  (+3.8pp vs baseline-cloud at 10× cheaper — cleanest paradigm-validation
  result in the harness).
- `minions-gaia-qwen27b-opus-165` = 0.576 acc, $0.67/task
  (~tied with baseline-cloud at 1.6× cheaper).

Registered as `minions`. Ported from
`hybrid-local-cloud-compute/adapters/minions_adapter.py`.
2026-05-13 15:13:29 -07:00
Andrew Park 915dbbf746 hybrid: port ConductorAgent (Sakana arXiv 2512.04388)
Inference-only Stage-1 repro: zero-shot cloud planner substitutes for the
paper's RL-trained Qwen2.5-7B conductor. Emits 3 JSON lists
(model_id/subtasks/access_list), executor runs ≤5 steps over a worker pool.

Two-tier parse fallback: JSON → Python-literal regex → single call to the
strongest worker. Worker pool defaults to {local Qwen if vLLM up, Opus 4.7,
gpt-5-mini}; override via `cfg["workers"]`.

Hybrid harness result: `conductor-swebenchverified-opusplan-30` = 0.367 acc
($0.22/task) vs baseline-cloud 0.267 ($3.36/task) — +10pp at ~15× cheaper.

Registered as `conductor`. Ported from
`hybrid-local-cloud-compute/adapters/conductor_adapter.py`.
2026-05-13 15:12:07 -07:00
Andrew Park 5ca9dd506c hybrid: port AdvisorsAgent (inference-only advisor-models)
Three-step executor (cloud) → advisor (local) → executor (cloud) loop from
arXiv:2510.02453. Inference-only: the paper's RL-trained advisor would
land higher; this matches the hybrid harness's `advisors-gaia-qwen9b-opus-30`
cell at 0.533 acc / $0.02 per task.

Registered as `advisors`. Local model id auto-resolves against vLLM's
`/v1/models` so cell configs naming Qwen3.5-9B don't 404 when the server
is actually serving 27B-FP8.

Ported from `hybrid-local-cloud-compute/adapters/advisors_adapter.py`.
2026-05-13 15:11:07 -07:00
Andrew Park afb6981271 hybrid: scaffold LocalCloudAgent base + bench prompt helpers
Add `openjarvis.agents.hybrid` — the home for the local+cloud paradigms
being ported from `/matx/u/aspark/hybrid-local-cloud-compute`. This commit
ships only the shared base (no paradigm yet):

- `_base.LocalCloudAgent`: ABC over `BaseAgent` with `_call_anthropic`,
  `_call_openai`, `_call_vllm` SDK helpers; standardized AgentResult
  metadata shape (tokens_local/tokens_cloud/cost_usd/latency_s/traces);
  Opus 4.7 temperature stripping; GPT-5 family `max_completion_tokens`;
  soft-fail row helper for deterministic adapter failures.
- `_prices.py`: ported verbatim from hybrid's `prices.py` so the n=500
  cost numbers stay aligned with `hybrid-local-cloud-compute/docs/results.md`.
- `_prompts.py`: GAIA + SWE-bench-Verified answer-format instructions,
  same `format_prompt(task)` dispatch as `benches/__init__.py`.
- `agents/__init__.py`: wire the new subpackage so its sub-modules
  register on package import.

Hybrid harness stays untouched — this is the OpenJarvis-native port.
2026-05-13 15:10:23 -07:00
github-actions[bot] eb097062b0 chore: update clone traffic data [skip ci] 2026-05-13 07:05:38 +00:00
github-actions[bot] d7888caf7a chore: update clone traffic data [skip ci] 2026-05-12 07:01:40 +00:00
Tanvir BhathalandGitHub 5044cf2bc8 Small gitignore for opt-in mining (#338) 2026-05-11 14:37:45 -07:00
github-actions[bot] 797ee6b761 chore: update clone traffic data [skip ci] 2026-05-11 07:16:28 +00:00
github-actions[bot] fec270eecf chore: update clone traffic data [skip ci] 2026-05-10 06:57:30 +00:00
github-actions[bot] d314f3ea8c chore: update clone traffic data [skip ci] 2026-05-09 06:46:02 +00:00
Jon Saad-FalconandGitHub 57151327b3 feat: LLM-guided spec search building blocks (split-aware sampling, external corpora, agent-trace adapter) (#332) 2026-05-08 20:18:40 -07:00
github-actions[bot] 37f4942b07 chore: update clone traffic data [skip ci] 2026-05-08 06:39:07 +00:00
Jon Saad-FalconandGitHub b8245136db fix(security): block IPv4-mapped IPv6 addresses in SSRF check (#327) 2026-05-07 14:55:52 -07:00
Jon Saad-FalconandGitHub ab46c89660 Delete CLAUDE.md 2026-05-07 12:14:45 -07:00
github-actions[bot] f705a46b39 chore: update clone traffic data [skip ci] 2026-05-07 08:31:07 +00:00
f0ab045cad fix(tools): correct Python-fallback bugs in calculator, file tools, and git tool (#236)
- calculator: add `ln` alias for `math.log`, replace `^` with `**` before
  AST parsing so caret-as-power works, convert SyntaxError → ValueError for
  consistent error handling, and return `math.inf` on division by zero
  (matching the documented meval behaviour) instead of raising an exception
- file_read / file_write: replace the hardcoded `str(path).startswith(str(d) + "/")
  guard with `Path.is_relative_to()` so allowed-directory checks work on
  Windows (and any OS whose separator is not `/`)
- git_tool: catch `NotADirectoryError` raised by `subprocess.run` on Windows
  when `cwd` points to a non-existent path, returning a proper error result

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Robby Manihani <manihani@stanford.edu>
2026-05-07 00:41:58 -07:00
Jack HamiltonandGitHub 9e7366fc05 Close KnowledgeStore connections in connectors_router endpoints (#209)
* fix: close KnowledgeStore connections in connectors_router endpoints

KnowledgeStore opens a persistent SQLite connection in __init__ but was
never closed at the three instantiation sites in connectors_router.py,
leaking one file descriptor (plus its WAL handle) per call. The worst
offender is _connector_summary(), which is invoked per-connector on
every GET /connectors poll from the frontend — after ~100 polls the
backend hits the default macOS per-process FD limit (256) and asyncio's
accept() starts failing with OSError: [Errno 24] Too many open files.

Add __enter__/__exit__ to KnowledgeStore (close() already existed) and
wrap all three instantiation sites in `with` blocks so the connection
is released deterministically when the scope exits.

- connectors/store.py: add context manager protocol
- server/connectors_router.py: use `with KnowledgeStore() as store:`
  in _connector_summary, _ingest, and _run_sync

* test: cover KnowledgeStore context manager + connectors_router close leak

- test_store.py: add two tests for the new __enter__/__exit__ protocol
  verifying the connection closes on normal exit and on exceptions.
- test_connectors_router.py: add a regression test that monkeypatches
  KnowledgeStore.close to count invocations and asserts every store
  opened by GET /v1/connectors is paired with a close.

Also fix a pre-existing bug in the test_connectors_router fixture: the
router is created with prefix="/v1/connectors" internally (line 92 of
connectors_router.py), and the fixture was wrapping it again with
prefix="/v1", producing "/v1/v1/connectors". All 6 existing router
tests were failing with 404 before this fix. 5 of them now pass; the
remaining failure (test_trigger_sync) is an unrelated KeyError on a
missing response field and is out of scope for this PR.

* test: drop connectors_router regression test — skipped in CI anyway

The regression test added in the previous commit relies on FastAPI
being importable, but CI's dev-extra install does not include fastapi
(it lives in the `server` optional group). All tests in
test_connectors_router.py silently skip on CI with "fastapi not
installed", so the regression test would never actually execute there.

Revert test_connectors_router.py to the upstream main version. The
fixture bug I fixed (double prefix) and the connection-leak regression
test both deserve a separate PR scoped to test infrastructure — that
PR should either add fastapi to dev deps, split server tests into
their own CI job, or both.

The KnowledgeStore context manager tests in test_store.py are kept
because they have no fastapi dependency and will run in CI.
2026-05-06 23:44:43 -07:00
4935053ac7 feat(mining): register ScalingIntelligence Pearl models (#324)
Co-authored-by: krypticmouse <herumbshandilya123@gmail.com>
2026-05-06 22:20:18 -07:00
8fb9d5ece3 feat(mining): add Pearl model conversion workflow (#323)
* feat(mining): add Pearl model conversion workflow

* test(mining): tolerate missing Docker device request type

* docs(mining): record Gemma and Qwen conversion evidence

* docs(mining): record Qwen local validation evidence

---------

Co-authored-by: krypticmouse <herumbshandilya123@gmail.com>
2026-05-06 16:20:27 -07:00
Avanika NarayanandGitHub daaa5577f0 feat(mining): inspect Pearl model artifacts before launch
Add jarvis mine inspect-model to fail fast on missing Pearl/Hugging Face artifact metadata before GPU startup.
2026-05-05 21:21:33 -07:00
Avanika NarayanandGitHub d74fb68b68 docs(mining): record Gemma/Qwen Pearl validation blockers
Record H100 validation findings for planned Gemma/Qwen Pearl models and keep them planned until public artifacts pass runtime validation.
2026-05-05 20:29:55 -07:00
a689be0c69 fix(evals): clean up AI stack runtime harness (#320)
Co-authored-by: krypticmouse <herumbshandilya123@gmail.com>
2026-05-05 19:28:50 -07:00
Jon Saad-FalconandGitHub f41cf420be feat(mining): Pearl mining integration
Consolidates NVIDIA vLLM, Apple Silicon, CPU Pearl mining support, CLI/docs, and live H100 validation.
2026-05-05 19:11:15 -07:00
Avanika NarayanandGitHub e79bc1e196 Add cold-start CLI installer (#313) 2026-05-05 14:42:48 -07:00
Avanika NarayanandGitHub a3ba63d148 AI_stack_support: subprocess-based external framework harness (#311) 2026-05-05 13:37:33 -07:00
github-actions[bot] ac2deb9d9d chore: update clone traffic data [skip ci] 2026-05-05 08:06:09 +00:00
github-actions[bot] 5a97e1197c chore: update clone traffic data [skip ci] 2026-05-04 08:26:37 +00:00
Avanika NarayanandGitHub d7624510bb Eval framework: silent-failure detection, surgical reruns, continuous-score reporting (#303) 2026-05-03 21:07:44 -07:00
github-actions[bot] aaaf00a951 chore: update clone traffic data [skip ci] 2026-05-03 07:59:20 +00:00
github-actions[bot] bd1e87373f chore: update clone traffic data [skip ci] 2026-05-02 07:41:02 +00:00
github-actions[bot] 5e0123ffd7 chore: update clone traffic data [skip ci] 2026-05-01 08:09:11 +00:00
github-actions[bot] 363cb637cd chore: update clone traffic data [skip ci] 2026-04-30 08:18:16 +00:00
Ali ShahkarandGitHub 2d3e5ad8b6 fix: correct import path for build_routing_context in executor (#214)
routing.types appears to have been an in-progress module that was
consolidated into routing.router before it was created. The lazy
import inside the router policy block was silently caught by the
surrounding try/except, causing the policy to never activate and
the executor to always fall back to the configured model regardless
of any router_policy setting.

Corrects the import to openjarvis.learning.routing.router where
build_routing_context is defined and exported.
2026-04-29 14:24:48 -07:00
Robby ManihaniandGitHub 259f97b81c fix(server): allow Tauri 2 webview origins on every platform (#292)
The desktop app's chat-completions stream relies on a raw browser
fetch from the Tauri webview to the FastAPI backend, so it is
subject to CORS. The default allowlist only contained
`tauri://localhost`, which is the production webview origin on
macOS, Linux, and iOS. On Windows and Android, Tauri 2 serves the
app from `http://tauri.localhost` (or `https://tauri.localhost`
when `windows.useHttpsScheme` is enabled), so the preflight for
`POST /v1/chat/completions` was rejected and the streaming fetch
threw `TypeError: Failed to fetch` before any byte was read.

Symptom users reported: in the Logs tab the request appears to
succeed up to "Request sent", followed immediately by
"Stream error: Failed to fetch" and "Response: 22 chars" -- which
is exactly the length of the synthesized fallback string
`Error: Failed to fetch` written by InputArea.tsx when streamChat
throws.

Add `http://tauri.localhost` and `https://tauri.localhost` to both
default origin lists (`ServerConfig.cors_origins` and the
`create_app` fallback), and add a regression test that drives a
real preflight against `/v1/chat/completions` for each of the
three Tauri origin schemes.

Browser model loading kept working because it is routed through
the Rust `tauriInvoke('fetch_models')` command, which is a
server-to-server HTTP call not subject to browser CORS -- only
streaming chat goes through the webview's fetch.
2026-04-29 12:55:25 -07:00
github-actions[bot] cdb04cdecb chore: update clone traffic data [skip ci] 2026-04-29 08:13:18 +00:00
Jon Saad-Falcon f16bf734cf Merge branch 'main' of https://github.com/open-jarvis/OpenJarvis 2026-04-28 20:26:44 -07:00
Jon Saad-FalconandClaude Opus 4.7 3f2f46e406 ci: stop auto-running Claude PR review on every pull request
Removes the pull_request trigger so the workflow only runs on explicit
@claude mentions or manual workflow_dispatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 20:23:24 -07:00