From 7354c5e5f4d0e53d8de9d6edf1773dce74144fec Mon Sep 17 00:00:00 2001 From: decolua Date: Thu, 18 Jun 2026 17:36:08 +0700 Subject: [PATCH] # v0.5.3 (2026-06-18) ## Fixes - **Kiro**: honor thinking effort budgets - **AG/Kiro/Xiaomi**: provider fixes - **Combo/Fusion**: flatten tool history in panel calls to prevent 503 - **LLM selector**: show custom vision models in selector and model list - **Image**: prevent compatible nodes from shadowing provider aliases --- CHANGELOG.md | 9 +++++++++ cli/package.json | 2 +- cli/scripts/build-cli.js | 1 - open-sse/providers/registry/qoder.js | 22 +++++++++++----------- open-sse/utils/sessionManager.js | 2 +- package.json | 2 +- src/app/layout.js | 2 +- tests/unit/session-manager.test.js | 15 ++++++++++++++- 8 files changed, 38 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6b75301..821e6432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# v0.5.3 (2026-06-18) + +## Fixes +- **Kiro**: honor thinking effort budgets +- **AG/Kiro/Xiaomi**: provider fixes +- **Combo/Fusion**: flatten tool history in panel calls to prevent 503 +- **LLM selector**: show custom vision models in selector and model list +- **Image**: prevent compatible nodes from shadowing provider aliases + # v0.5.2 (2026-06-17) ## Features diff --git a/cli/package.json b/cli/package.json index d75e5125..9bbcaaf7 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "9router", - "version": "0.5.2", + "version": "0.5.3", "description": "9Router CLI - Start and manage 9Router server", "bin": { "9router": "./cli.js" diff --git a/cli/scripts/build-cli.js b/cli/scripts/build-cli.js index be2e97c3..48dd0910 100644 --- a/cli/scripts/build-cli.js +++ b/cli/scripts/build-cli.js @@ -17,7 +17,6 @@ const EXCLUDE_PATTERNS = [ "@img", // Sharp image processing (not needed with unoptimized images) "sharp", // Sharp core lib (not needed with unoptimized images) "detect-libc", // Sharp dependency - "logs", // Runtime logs ".env", // Environment files ".env.local", ".env.*.local", diff --git a/open-sse/providers/registry/qoder.js b/open-sse/providers/registry/qoder.js index c150e3a6..4ee2b52f 100644 --- a/open-sse/providers/registry/qoder.js +++ b/open-sse/providers/registry/qoder.js @@ -25,18 +25,18 @@ export default { }, }, models: [ - { id: "auto", name: "Qoder Auto" }, - { id: "ultimate", name: "Qoder Ultimate" }, - { id: "performance", name: "Qoder Performance" }, - { id: "efficient", name: "Qoder Efficient" }, - { id: "lite", name: "Qoder Lite" }, - { id: "qmodel", name: "Qwen 3.6 Plus (Qoder)" }, + // { id: "auto", name: "Qoder Auto" }, + // { id: "ultimate", name: "Qoder Ultimate" }, + // { id: "performance", name: "Qoder Performance" }, + // { id: "efficient", name: "Qoder Efficient" }, + // { id: "lite", name: "Qoder Lite" }, + // { id: "qmodel", name: "Qwen 3.6 Plus (Qoder)" }, { id: "qmodel_latest", name: "Qoder Qwen 3.7 Max" }, - { id: "dmodel", name: "DeepSeek V4 Pro (Qoder)" }, - { id: "dfmodel", name: "DeepSeek V4 Flash (Qoder)" }, - { id: "gm51model", name: "GLM 5.1 (Qoder)" }, - { id: "kmodel", name: "Kimi K2.6 (Qoder)" }, - { id: "mmodel", name: "MiniMax M2.7 (Qoder)" }, + // { id: "dmodel", name: "DeepSeek V4 Pro (Qoder)" }, + // { id: "dfmodel", name: "DeepSeek V4 Flash (Qoder)" }, + // { id: "gm51model", name: "GLM 5.1 (Qoder)" }, + // { id: "kmodel", name: "Kimi K2.6 (Qoder)" }, + // { id: "mmodel", name: "MiniMax M2.7 (Qoder)" }, ], oauth: { openApiBaseUrl: "https://openapi.qoder.sh", diff --git a/open-sse/utils/sessionManager.js b/open-sse/utils/sessionManager.js index 73af1a6b..05f90896 100644 --- a/open-sse/utils/sessionManager.js +++ b/open-sse/utils/sessionManager.js @@ -85,7 +85,7 @@ export function clearSessionStore() { // Conversation-stable session store: Key = hash(scope+assistant text), Value = { sessionId, lastUsed } const assistantSessionStore = new Map(); const ASSISTANT_MIN_LEN = 50; -const ASSISTANT_CAP_LEN = 200; +const ASSISTANT_CAP_LEN = 50; const MAX_ASSISTANT_SESSIONS = 5000; // Client headers/body fields that carry an upstream session id (priority order) diff --git a/package.json b/package.json index a70f66fe..325caad4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "9router-app", - "version": "0.5.2", + "version": "0.5.3", "description": "9Router web dashboard", "private": true, "scripts": { diff --git a/src/app/layout.js b/src/app/layout.js index f86cca69..5ea6c11d 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -44,7 +44,7 @@ export default function RootLayout({ children }) { {children} - {gaId && } + ); diff --git a/tests/unit/session-manager.test.js b/tests/unit/session-manager.test.js index c8249657..37474813 100644 --- a/tests/unit/session-manager.test.js +++ b/tests/unit/session-manager.test.js @@ -2,9 +2,10 @@ import { describe, it, expect, beforeEach } from "vitest"; import { resolveSessionId, deriveSessionId, clearSessionStore } from "../../open-sse/utils/sessionManager.js"; -// Assistant text must exceed ASSISTANT_MIN_LEN (50) to trigger sticky hash path. +// Assistant text must reach ASSISTANT_MIN_LEN (80) to use assistant anchor; else first user message. const longAssistant = "x".repeat(80); const bodyWithAssistant = { messages: [{ role: "assistant", content: longAssistant }] }; +const bodyWithUserOnly = { messages: [{ role: "user", content: "hello from first user message anchor" }] }; beforeEach(() => clearSessionStore()); @@ -26,6 +27,18 @@ describe("resolveSessionId", () => { expect(a).not.toBe(b); }); + it("first user message anchor when assistant text below cap", () => { + const opts = { body: bodyWithUserOnly, connectionId: "conn1", scope: "codex" }; + expect(resolveSessionId(opts)).toBe(resolveSessionId(opts)); + }); + + it("assistant anchor wins once assistant text reaches cap", () => { + const shortAssistant = { messages: [{ role: "user", content: "same user" }, { role: "assistant", content: "y".repeat(80) }] }; + const a = resolveSessionId({ body: shortAssistant, connectionId: "conn1", scope: "codex" }); + const b = resolveSessionId({ body: shortAssistant, connectionId: "conn1", scope: "codex" }); + expect(a).toBe(b); + }); + it("fallback: empty body+no header+no workspaceId -> deriveSessionId(connectionId)", () => { const got = resolveSessionId({ body: {}, connectionId: "connFallback" }); expect(got).toBe(deriveSessionId("connFallback"));