agentlas 0.9.6 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.7 — 2026-07-25
4
+
5
+ - Fix: the resident judge now reaches API/Ollama/BYOK runtimes, not only CLI
6
+ subprocess runtimes. Previously, when your connected runtime was Ollama or a
7
+ BYOK API model, every route, intent, and classification silently used the
8
+ deterministic wordlist fallback because the judge was wired to null — so a
9
+ non-English request the keyword lists could not read never got a model
10
+ verdict. The judge now runs on whatever runtime you actually have connected,
11
+ and its timeout signal aborts the underlying request cleanly.
12
+ - Fix: the judge is installed at startup, before the first routing decision.
13
+ It was previously wired only inside the run turn, which happens after routing,
14
+ so the very first auto-route in a one-shot always fell back.
15
+ - Routing gives the model a more generous deadline (a one-shot pre-run gate), so
16
+ a slower local model is judged rather than frequently falling back. When it
17
+ still cannot answer in time, the route receipt says so explicitly.
18
+
3
19
  ## 0.9.6 — 2026-07-25
4
20
 
5
21
  - Agent and App Builder routing is now decided by the connected model: lexical
@@ -640,6 +640,7 @@ const APP_BUILDER_ROUTE_SLUG = "agentlas-app-builder";
640
640
  async function resolveAutoRoute(db, prompt, lang) {
641
641
  const resolvedLang = lang || prefsLang();
642
642
  const prefilter = autoRouteAgent(db, prompt, resolvedLang);
643
+ ensureJudgmentRunnerInstalled(db);
643
644
  let judgment;
644
645
  try {
645
646
  judgment = require("./agentlas-judgment.cjs");
@@ -700,6 +701,11 @@ async function resolveAutoRoute(db, prompt, lang) {
700
701
  ].join("\n"),
701
702
  multi: false,
702
703
  fallback: [],
704
+ // Routing is a one-shot pre-run gate: correctness matters more than latency,
705
+ // and a local 30B model with a full roster can need well over the 20s default.
706
+ // The judge's abort signal is threaded into the request, so a genuinely hung
707
+ // model still aborts cleanly at this deadline rather than hanging forever.
708
+ timeoutMs: 40000,
703
709
  });
704
710
  if (verdict.source !== "llm" || !verdict.labels.length) return { ...prefilter, routeSource: "deterministic" };
705
711
  const picked = verdict.labels[0];
@@ -8627,32 +8633,83 @@ function installJudgmentRunner(db, rt) {
8627
8633
  } catch {
8628
8634
  return;
8629
8635
  }
8630
- if (!rt || rt.mode !== "cli" || !RUNTIME_BIN[rt.kind]) {
8631
- judgment.setJudgmentRunner(null);
8636
+ // CLI runtime (claude-code/codex/gemini): the judge runs a silent native turn.
8637
+ if (rt && rt.mode === "cli" && RUNTIME_BIN[rt.kind]) {
8638
+ judgment.setJudgmentRunner(async ({ system, prompt, signal }) => {
8639
+ const { runNativeTurn } = require("./agentlas-native-host.cjs");
8640
+ const { Ui } = require("./agentlas-ui.cjs");
8641
+ const silent = new Ui({ lang: prefsLang(), quiet: true });
8642
+ for (const method of ["write", "warn", "info", "tool", "result", "status", "line"]) {
8643
+ if (typeof silent[method] === "function") silent[method] = () => {};
8644
+ }
8645
+ const res = await runNativeTurn({
8646
+ kind: rt.kind,
8647
+ bin: RUNTIME_BIN[rt.kind],
8648
+ prompt,
8649
+ systemPrompt: system,
8650
+ cwd: projectCwd(),
8651
+ permission: "read",
8652
+ session: {},
8653
+ ui: silent,
8654
+ env: process.env,
8655
+ signal,
8656
+ });
8657
+ if (res && res.error) return "";
8658
+ return (res && res.text) || "";
8659
+ });
8632
8660
  return;
8633
8661
  }
8634
- judgment.setJudgmentRunner(async ({ system, prompt, signal }) => {
8635
- const { runNativeTurn } = require("./agentlas-native-host.cjs");
8636
- const { Ui } = require("./agentlas-ui.cjs");
8637
- const silent = new Ui({ lang: prefsLang(), quiet: true });
8638
- for (const method of ["write", "warn", "info", "tool", "result", "status", "line"]) {
8639
- if (typeof silent[method] === "function") silent[method] = () => {};
8640
- }
8641
- const res = await runNativeTurn({
8642
- kind: rt.kind,
8643
- bin: RUNTIME_BIN[rt.kind],
8644
- prompt,
8645
- systemPrompt: system,
8646
- cwd: projectCwd(),
8647
- permission: "read",
8648
- session: {},
8649
- ui: silent,
8650
- env: process.env,
8651
- signal,
8662
+
8663
+ // API runtime (BYOK / Ollama): the judge uses the same one-shot API path the
8664
+ // rest of the terminal uses, so "the connected model decides" holds for the
8665
+ // user's actual runtime not only CLI subprocess runtimes. Without this, an
8666
+ // Ollama/BYOK user silently gets the deterministic wordlist fallback for every
8667
+ // route, intent, and classification decision.
8668
+ if (rt && rt.mode === "api" && rt.backend) {
8669
+ judgment.setJudgmentRunner(async ({ system, prompt, signal }) => {
8670
+ // Thread the judge's timeout signal into the actual HTTP request so a slow
8671
+ // model aborts the fetch instead of hanging past the deadline.
8672
+ const baseFetch = globalThis.fetch;
8673
+ const fetchImpl = typeof baseFetch === "function" && signal
8674
+ ? (url, init) => baseFetch(url, { ...(init || {}), signal })
8675
+ : baseFetch;
8676
+ try {
8677
+ return await runApi(rt.backend, rt.model, system, prompt, { fetch: fetchImpl });
8678
+ } catch {
8679
+ return "";
8680
+ }
8652
8681
  });
8653
- if (res && res.error) return "";
8654
- return (res && res.text) || "";
8655
- });
8682
+ return;
8683
+ }
8684
+
8685
+ judgment.setJudgmentRunner(null);
8686
+ }
8687
+
8688
+ // Make sure the resident judge can reach the connected model BEFORE the first
8689
+ // judged decision (routing, image capability, task class). The only other
8690
+ // install site is inside executeOnce, which runs AFTER routing — so a one-shot
8691
+ // `run`/auto-route would always fall to the deterministic label without this.
8692
+ // Uses the active runtime (CLI or API/Ollama/BYOK); a pinned override still
8693
+ // reinstalls in executeOnce for the actual task turn.
8694
+ function ensureJudgmentRunnerInstalled(db) {
8695
+ let judgment;
8696
+ try {
8697
+ judgment = require("./agentlas-judgment.cjs");
8698
+ } catch {
8699
+ return;
8700
+ }
8701
+ if (judgment.hasJudgmentRunner()) return;
8702
+ try {
8703
+ const ar = activeRuntime(db);
8704
+ let rt = null;
8705
+ if (ar && RUNTIME_BIN[ar.kind]) rt = { mode: "cli", kind: ar.kind, model: ar.model || null };
8706
+ else if (ar && ar.kind === "byok" && ar.backend) rt = { mode: "api", backend: ar.backend, model: ar.model };
8707
+ else if (ar && ar.kind === "ollama") rt = { mode: "api", backend: "ollama", model: ar.model };
8708
+ if (rt) installJudgmentRunner(db, rt);
8709
+ } catch {
8710
+ // No resolvable runtime → leave the runner unset; judged sites use their
8711
+ // labeled deterministic fallback rather than crashing.
8712
+ }
8656
8713
  }
8657
8714
 
8658
8715
  function resolveRuntime(db, override) {
@@ -11878,6 +11935,12 @@ async function main() {
11878
11935
  // Agentlas 아키텍처 빌트인 에이전트를 보장(앱과 동일, 멱등·버전 게이팅). 스키마가 준비됐을 때만.
11879
11936
  try { seedBuiltins(db); } catch { /* best-effort */ }
11880
11937
 
11938
+ // Wire the resident judge to the connected runtime up front, so the FIRST
11939
+ // routing / image-capability / task-class decision is judged by the model —
11940
+ // in the REPL and in one-shot commands alike — instead of silently falling to
11941
+ // the deterministic label until executeOnce eventually installs it.
11942
+ ensureJudgmentRunnerInstalled(db);
11943
+
11881
11944
  // 인자 없이 `agentlas` → 에이전트 1개면 바로 대화형, 아니면 목록 + 사용법
11882
11945
  if (cmd === "") {
11883
11946
  const agents = listAgents(db);
@@ -12140,6 +12203,9 @@ module.exports = {
12140
12203
  autoRouteNote,
12141
12204
  autoRoutePreamble,
12142
12205
  directSystemPrompt,
12206
+ // Test bridge: prove the resident judge is wired to API/Ollama/BYOK runtimes,
12207
+ // not only CLI subprocess runtimes.
12208
+ installJudgmentRunner,
12143
12209
  // Hub 플러그인 설치 회귀 테스트 표면 — 레포 URL을 MCP 서버로 등록하지 않는 규칙 검증용.
12144
12210
  pluginMcpRowCli,
12145
12211
  planPluginMcpInstallCli,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlas",
3
- "version": "0.9.6",
3
+ "version": "0.9.7",
4
4
  "description": "Agentlas agent terminal — chat with your installed AI agents and teams from the terminal, Claude Code style. Standalone: no desktop app required.",
5
5
  "bin": {
6
6
  "agentlas": "bin/agentlas.cjs"