# 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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "9router-app",
|
||||
"version": "0.5.2",
|
||||
"version": "0.5.3",
|
||||
"description": "9Router web dashboard",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function RootLayout({ children }) {
|
||||
{children}
|
||||
</RuntimeI18nProvider>
|
||||
</ThemeProvider>
|
||||
{gaId && <GoogleAnalytics gaId={"G-LC959F603F"} />}
|
||||
<GoogleAnalytics gaId={"G-LC959F603F"} />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -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"));
|
||||
|
||||
Reference in New Issue
Block a user