qwen-agent-server 0.11.1
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/README.md +211 -0
- package/dist/backends.js +444 -0
- package/dist/backends.js.map +1 -0
- package/dist/embed.js +92 -0
- package/dist/embed.js.map +1 -0
- package/dist/extensions.js +497 -0
- package/dist/extensions.js.map +1 -0
- package/dist/log.js +21 -0
- package/dist/log.js.map +1 -0
- package/dist/openai-compat.js +147 -0
- package/dist/openai-compat.js.map +1 -0
- package/dist/permissions.js +71 -0
- package/dist/permissions.js.map +1 -0
- package/dist/pool.js +155 -0
- package/dist/pool.js.map +1 -0
- package/dist/rerank.js +93 -0
- package/dist/rerank.js.map +1 -0
- package/dist/server.js +1050 -0
- package/dist/server.js.map +1 -0
- package/dist/session.js +649 -0
- package/dist/session.js.map +1 -0
- package/dist/shutdown.js +68 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/threads.js +218 -0
- package/dist/threads.js.map +1 -0
- package/dist/tokenize.js +90 -0
- package/dist/tokenize.js.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/dist/vision.js +293 -0
- package/dist/vision.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// openai-compat.ts — shared OpenAI-compatible dispatch primitives.
|
|
4
|
+
//
|
|
5
|
+
// All the direct-HTTP tools (qwen_oneshot_vision, qwen_embed, qwen_rerank,
|
|
6
|
+
// qwen_tokenize) bypass `@qwen-code/sdk` (which is Qwen-CLI/text-chat
|
|
7
|
+
// only) and POST directly to the backend. Before this module, each tool
|
|
8
|
+
// duplicated the fetch/abort/HTTP-error-classification/JSON-parse logic.
|
|
9
|
+
//
|
|
10
|
+
// This module centralises that pattern. Each module supplies:
|
|
11
|
+
// - the endpoint suffix to hit (relative to backend.url, with /v1
|
|
12
|
+
// handling per-endpoint as needed)
|
|
13
|
+
// - the request body
|
|
14
|
+
// - per-module response normalization and specialized error codes
|
|
15
|
+
// (no_data / no_results / no_tokens / wrong_modality / etc.)
|
|
16
|
+
//
|
|
17
|
+
// What's centralised here:
|
|
18
|
+
// - auth header resolution (api_key literal / api_key_env / extra headers)
|
|
19
|
+
// - timeout via AbortController
|
|
20
|
+
// - HTTP error envelope { timeout | backend_error }
|
|
21
|
+
// - JSON parse error envelope
|
|
22
|
+
// - status code + raw response text passthrough so callers can
|
|
23
|
+
// classify specific provider error shapes (e.g. vision's "image
|
|
24
|
+
// input is not supported" -> backend_no_mmproj)
|
|
25
|
+
//
|
|
26
|
+
// What's NOT centralised:
|
|
27
|
+
// - response normalization (each endpoint has its own shape)
|
|
28
|
+
// - module-specific error codes (kept in each caller for type-safety
|
|
29
|
+
// of the public error union)
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the Authorization + extra headers to send to this backend.
|
|
32
|
+
*
|
|
33
|
+
* - If `backend.api_key` is set, use it directly.
|
|
34
|
+
* - Else if `backend.api_key_env` is set, read `process.env[that]` at
|
|
35
|
+
* request time (rotations apply on next call, no supervisor reload).
|
|
36
|
+
* - Then merge `backend.headers` (caller overrides built-ins).
|
|
37
|
+
*
|
|
38
|
+
* Returns an empty object for backends with no auth (the common local
|
|
39
|
+
* llama-server case).
|
|
40
|
+
*/
|
|
41
|
+
export function resolveAuthHeaders(backend) {
|
|
42
|
+
const headers = {};
|
|
43
|
+
let key;
|
|
44
|
+
if (backend.api_key !== undefined && backend.api_key !== "") {
|
|
45
|
+
key = backend.api_key;
|
|
46
|
+
}
|
|
47
|
+
else if (backend.api_key_env !== undefined && backend.api_key_env !== "") {
|
|
48
|
+
key = process.env[backend.api_key_env];
|
|
49
|
+
}
|
|
50
|
+
if (key !== undefined && key !== "") {
|
|
51
|
+
headers["Authorization"] = `Bearer ${key}`;
|
|
52
|
+
}
|
|
53
|
+
if (backend.headers !== undefined) {
|
|
54
|
+
Object.assign(headers, backend.headers);
|
|
55
|
+
}
|
|
56
|
+
return headers;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Compose a request URL from a backend's base + an endpoint suffix.
|
|
60
|
+
*
|
|
61
|
+
* Three cases:
|
|
62
|
+
* - `endpoint` starts with `/v1/` and backend.url ends in `/v1` →
|
|
63
|
+
* trim one /v1 to avoid duplication.
|
|
64
|
+
* - `endpoint` starts with `/` and is non-/v1 (e.g. `/tokenize`) →
|
|
65
|
+
* strip the `/v1` suffix from backend.url so the request lands at
|
|
66
|
+
* the server root.
|
|
67
|
+
* - Otherwise just join.
|
|
68
|
+
*
|
|
69
|
+
* Trailing slashes on backend.url are normalised away.
|
|
70
|
+
*/
|
|
71
|
+
export function buildRequestUrl(backendUrl, endpoint) {
|
|
72
|
+
const base = backendUrl.replace(/\/$/, "");
|
|
73
|
+
if (endpoint.startsWith("/v1/")) {
|
|
74
|
+
// Backend URL likely ends in /v1; strip it so we don't double up.
|
|
75
|
+
return `${base.replace(/\/v1$/, "")}${endpoint}`;
|
|
76
|
+
}
|
|
77
|
+
if (endpoint.startsWith("/") && !endpoint.startsWith("/v1")) {
|
|
78
|
+
// Root-relative non-v1 (e.g. /tokenize) — strip /v1 from base.
|
|
79
|
+
return `${base.replace(/\/v1$/, "")}${endpoint}`;
|
|
80
|
+
}
|
|
81
|
+
// Default: append as a path under the configured base.
|
|
82
|
+
return `${base}/${endpoint.replace(/^\//, "")}`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* POST a JSON body to an OpenAI-compatible endpoint on a backend.
|
|
86
|
+
*
|
|
87
|
+
* Resolves auth + custom headers, manages the AbortController timeout,
|
|
88
|
+
* classifies network / HTTP failures into the shared envelope, and
|
|
89
|
+
* returns the raw response text on success so each caller can do its
|
|
90
|
+
* own typed parse (the JSON shape is endpoint-specific).
|
|
91
|
+
*
|
|
92
|
+
* Never throws.
|
|
93
|
+
*/
|
|
94
|
+
export async function dispatchOpenAIPost(backend, endpoint, body, opts) {
|
|
95
|
+
const start = Date.now();
|
|
96
|
+
const url = buildRequestUrl(backend.url, endpoint);
|
|
97
|
+
const headers = {
|
|
98
|
+
"Content-Type": "application/json",
|
|
99
|
+
...resolveAuthHeaders(backend),
|
|
100
|
+
};
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
const timer = setTimeout(() => controller.abort(), opts.timeout_ms);
|
|
103
|
+
let resp;
|
|
104
|
+
try {
|
|
105
|
+
resp = await fetch(url, {
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers,
|
|
108
|
+
body: JSON.stringify(body),
|
|
109
|
+
signal: controller.signal,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
const aborted = err?.name === "AbortError";
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
elapsed_ms: Date.now() - start,
|
|
118
|
+
error: aborted
|
|
119
|
+
? { code: "timeout", message: `request aborted after ${opts.timeout_ms}ms` }
|
|
120
|
+
: {
|
|
121
|
+
code: "backend_error",
|
|
122
|
+
message: err instanceof Error ? err.message : String(err),
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
const text = await resp.text();
|
|
128
|
+
if (!resp.ok) {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
elapsed_ms: Date.now() - start,
|
|
132
|
+
status: resp.status,
|
|
133
|
+
body_text: text,
|
|
134
|
+
error: {
|
|
135
|
+
code: "backend_error",
|
|
136
|
+
message: `HTTP ${resp.status}: ${text.slice(0, 300)}`,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
ok: true,
|
|
142
|
+
status: resp.status,
|
|
143
|
+
body_text: text,
|
|
144
|
+
elapsed_ms: Date.now() - start,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=openai-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compat.js","sourceRoot":"","sources":["../src/openai-compat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// makeCanUseTool — factory for the CanUseTool callback injected into the
|
|
4
|
+
// @qwen-code/sdk QueryOptions.
|
|
5
|
+
//
|
|
6
|
+
// Scope (post-2026-05-04 spike): canUseTool is responsible ONLY for
|
|
7
|
+
// write-tool permission gating. The original RDR §Q1 design also had
|
|
8
|
+
// canUseTool intercept ask_user_question to deliver answers via the
|
|
9
|
+
// deny-message field; that mechanism was empirically confirmed to fail
|
|
10
|
+
// (probe-tool-result.mjs, 2026-05-04 — the model treats the deny as
|
|
11
|
+
// "user cancelled with reason X", not "user answered X"). The
|
|
12
|
+
// supervisor now excludes ask_user_question from the inner Qwen's
|
|
13
|
+
// tool surface entirely (see session.ts DEFAULT_EXCLUDED_TOOLS); the
|
|
14
|
+
// model is told to ask in plain text and the user replies via
|
|
15
|
+
// streamInput-driven multi-turn input.
|
|
16
|
+
//
|
|
17
|
+
// Critical pins (RDR-001):
|
|
18
|
+
// §S4 Write tools when write_authority=false: emit a synthetic
|
|
19
|
+
// permission_denied event AND return deny. The event is
|
|
20
|
+
// important — without it, denials are silently swallowed by
|
|
21
|
+
// the SDK and the supervisor has no visibility into what the
|
|
22
|
+
// inner Qwen tried to do.
|
|
23
|
+
// §S4 Write tools when write_authority=true: this callback isn't
|
|
24
|
+
// invoked — permissionMode='yolo' bypasses canUseTool entirely.
|
|
25
|
+
// ─────────────────────────────────────────────────────────────────
|
|
26
|
+
// Write-tool set
|
|
27
|
+
//
|
|
28
|
+
// These tool names require write_authority===true to execute. Must be
|
|
29
|
+
// revisited if Qwen adds new write tools (names sourced from Qwen Code
|
|
30
|
+
// core tool registry as of SDK 0.1.7).
|
|
31
|
+
export const WRITE_TOOLS = new Set([
|
|
32
|
+
"write_file",
|
|
33
|
+
"edit",
|
|
34
|
+
"run_shell_command",
|
|
35
|
+
"replace",
|
|
36
|
+
"multi_edit",
|
|
37
|
+
]);
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────
|
|
39
|
+
// Factory
|
|
40
|
+
/**
|
|
41
|
+
* Returns a CanUseTool callback for use with permissionMode='default'.
|
|
42
|
+
*
|
|
43
|
+
* Routing (in order):
|
|
44
|
+
* - `ask_user_question` → emit permission_denied event + return deny
|
|
45
|
+
* with a hint message. Defense-in-depth: this tool is in the SDK
|
|
46
|
+
* excludeTools list and should never reach the callback. If it does
|
|
47
|
+
* (future SDK change, model bypass), denying is the safe choice —
|
|
48
|
+
* the SDK can't execute ask_user_question in headless mode anyway.
|
|
49
|
+
* - write tool → emit permission_denied event + return deny.
|
|
50
|
+
* - everything else → return allow (read tools, search, web_fetch, etc.).
|
|
51
|
+
*/
|
|
52
|
+
export function makeCanUseTool(session) {
|
|
53
|
+
return async (toolName, input, _opts) => {
|
|
54
|
+
// Defense-in-depth: ask_user_question shouldn't reach us (excluded
|
|
55
|
+
// at the SDK level); if it does, deny with a clear hint.
|
|
56
|
+
if (toolName === "ask_user_question") {
|
|
57
|
+
session.pushEvent("permission_denied", `ask_user_question reached canUseTool — should be excluded`, { tool_name: toolName, input });
|
|
58
|
+
return {
|
|
59
|
+
behavior: "deny",
|
|
60
|
+
message: "ask_user_question is not available; ask in plain text in your response and the user will reply.",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (WRITE_TOOLS.has(toolName)) {
|
|
64
|
+
session.pushEvent("permission_denied", `write_authority not granted for ${toolName}`, { tool_name: toolName, input });
|
|
65
|
+
return { behavior: "deny", message: "write_authority not granted" };
|
|
66
|
+
}
|
|
67
|
+
// Read tools / search tools / web_fetch / etc. — auto-allow.
|
|
68
|
+
return { behavior: "allow", updatedInput: input };
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,EAAE;AACF,yEAAyE;AACzE,+BAA+B;AAC/B,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,oEAAoE;AACpE,uEAAuE;AACvE,oEAAoE;AACpE,8DAA8D;AAC9D,kEAAkE;AAClE,qEAAqE;AACrE,8DAA8D;AAC9D,uCAAuC;AACvC,EAAE;AACF,2BAA2B;AAC3B,kEAAkE;AAClE,+DAA+D;AAC/D,mEAAmE;AACnE,oEAAoE;AACpE,iCAAiC;AACjC,oEAAoE;AACpE,uEAAuE;AAKvE,oEAAoE;AACpE,iBAAiB;AACjB,EAAE;AACF,sEAAsE;AACtE,uEAAuE;AACvE,uCAAuC;AAEvC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS;IACzC,YAAY;IACZ,MAAM;IACN,mBAAmB;IACnB,SAAS;IACT,YAAY;CACb,CAAC,CAAC;AAEH,oEAAoE;AACpE,UAAU;AAEV;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB;IACjD,OAAO,KAAK,EACV,QAAgB,EAChB,KAAgB,EAChB,KAA8B,EACH,EAAE;QAC7B,mEAAmE;QACnE,yDAAyD;QACzD,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YACrC,OAAO,CAAC,SAAS,CACf,mBAAmB,EACnB,2DAA2D,EAC3D,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAC/B,CAAC;YACF,OAAO;gBACL,QAAQ,EAAE,MAAM;gBAChB,OAAO,EACL,iGAAiG;aACpG,CAAC;QACJ,CAAC;QAED,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,SAAS,CACf,mBAAmB,EACnB,mCAAmC,QAAQ,EAAE,EAC7C,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAC/B,CAAC;YACF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC;QACtE,CAAC;QAED,6DAA6D;QAC7D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/pool.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// Session pool: cap enforcement, LRU eviction, idle reaper.
|
|
4
|
+
//
|
|
5
|
+
// Pool semantics (per RDR-001 §Q4):
|
|
6
|
+
// - Hard cap: QWEN_SUPERVISOR_MAX_SESSIONS (default 3)
|
|
7
|
+
// - Idle TTL: QWEN_SUPERVISOR_IDLE_TTL_MS (default 30 min)
|
|
8
|
+
// - Eviction pass 1: terminal (complete/error) sessions first
|
|
9
|
+
// - Eviction pass 2: least-recently-polled by last_polled_at
|
|
10
|
+
// - Reaper: sweeps idle sessions every 5 min (interval.unref()d)
|
|
11
|
+
import { createLogger } from "./log.js";
|
|
12
|
+
import { QwenSession } from "./session.js";
|
|
13
|
+
import { chooseBackend, getSessionBudgetDefaults, loadBackends } from "./backends.js";
|
|
14
|
+
const log = createLogger("qwen-pool");
|
|
15
|
+
// ─────────────────────────────────────────────────────────────────
|
|
16
|
+
// Factory
|
|
17
|
+
export function createPool(opts = {}) {
|
|
18
|
+
const maxSessions = parseInt(process.env["QWEN_SUPERVISOR_MAX_SESSIONS"] ?? "", 10) || 3;
|
|
19
|
+
const idleTtlMs = parseInt(process.env["QWEN_SUPERVISOR_IDLE_TTL_MS"] ?? "", 10) || 30 * 60 * 1000;
|
|
20
|
+
const backends = loadBackends();
|
|
21
|
+
return {
|
|
22
|
+
sessions: new Map(),
|
|
23
|
+
maxSessions,
|
|
24
|
+
idleTtlMs,
|
|
25
|
+
backends,
|
|
26
|
+
qwenRealBin: opts.qwenRealBin ?? "",
|
|
27
|
+
wrapperPath: opts.wrapperPath ?? "",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// ─────────────────────────────────────────────────────────────────
|
|
31
|
+
// LRU eviction
|
|
32
|
+
/**
|
|
33
|
+
* Evict one session when the pool is at or above cap.
|
|
34
|
+
*
|
|
35
|
+
* Pass 1: drop any complete/error session (they're done; cheap to evict).
|
|
36
|
+
* Pass 2: evict the session with the smallest last_polled_at.
|
|
37
|
+
*/
|
|
38
|
+
export function lruEvict(pool) {
|
|
39
|
+
if (pool.sessions.size < pool.maxSessions)
|
|
40
|
+
return;
|
|
41
|
+
// Pass 1: terminal sessions
|
|
42
|
+
for (const [id, session] of pool.sessions) {
|
|
43
|
+
if (session.state === "complete" || session.state === "error") {
|
|
44
|
+
session.stop();
|
|
45
|
+
pool.sessions.delete(id);
|
|
46
|
+
log.info({ task_id: id, state: session.state, event_type: "evict" }, "evicted terminal session at cap");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Pass 2: oldest by last_polled_at
|
|
51
|
+
let oldest;
|
|
52
|
+
let oldestId;
|
|
53
|
+
for (const [id, session] of pool.sessions) {
|
|
54
|
+
if (!oldest || session.last_polled_at < oldest.last_polled_at) {
|
|
55
|
+
oldest = session;
|
|
56
|
+
oldestId = id;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (oldest && oldestId !== undefined) {
|
|
60
|
+
oldest.stop();
|
|
61
|
+
pool.sessions.delete(oldestId);
|
|
62
|
+
log.info({ task_id: oldestId, event_type: "evict" }, "evicted LRU session at cap");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ─────────────────────────────────────────────────────────────────
|
|
66
|
+
// Reaper
|
|
67
|
+
/**
|
|
68
|
+
* Sweep sessions idle beyond idleTtlMs. Called periodically by the
|
|
69
|
+
* server's setInterval reaper (every 5 min).
|
|
70
|
+
*
|
|
71
|
+
* Reaps `idle`, `complete`, and `error` sessions that haven't been
|
|
72
|
+
* polled within idleTtlMs. Sessions in the `running` state are SKIPPED
|
|
73
|
+
* regardless of poll age — the inner Qwen may be processing a long
|
|
74
|
+
* tool call (codebase scan, web fetch, etc.) and killing it because
|
|
75
|
+
* the caller hasn't polled would terminate active work. The cap
|
|
76
|
+
* (lruEvict) is the backstop for runaway running sessions.
|
|
77
|
+
*/
|
|
78
|
+
export function reapSweep(pool) {
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
const toReap = [];
|
|
81
|
+
for (const [id, session] of pool.sessions) {
|
|
82
|
+
if (session.state === "running")
|
|
83
|
+
continue;
|
|
84
|
+
if (now - session.last_polled_at > pool.idleTtlMs) {
|
|
85
|
+
toReap.push(id);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const id of toReap) {
|
|
89
|
+
const session = pool.sessions.get(id);
|
|
90
|
+
if (session) {
|
|
91
|
+
session.stop();
|
|
92
|
+
pool.sessions.delete(id);
|
|
93
|
+
log.info({ task_id: id, state: session.state, event_type: "reap" }, "reaped idle session");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ─────────────────────────────────────────────────────────────────
|
|
98
|
+
// Spawn
|
|
99
|
+
/**
|
|
100
|
+
* Spawn a new session, applying LRU eviction if at cap first.
|
|
101
|
+
* Returns the new QwenSession.
|
|
102
|
+
*
|
|
103
|
+
* `resolvedExtensions` is the output of `resolveExtensions()` from the
|
|
104
|
+
* qwen_spawn handler — pre-validated; spawnSession does not re-validate.
|
|
105
|
+
* Pass undefined for code paths (notably tests) that don't supply a
|
|
106
|
+
* resolution; the session will fall through to default SDK behaviour.
|
|
107
|
+
*/
|
|
108
|
+
export async function spawnSession(pool, task, opts, resolvedExtensions) {
|
|
109
|
+
const spawnOpts = {
|
|
110
|
+
write_authority: opts.write_authority ?? false,
|
|
111
|
+
allow_subagents: opts.allow_subagents ?? false,
|
|
112
|
+
...opts,
|
|
113
|
+
};
|
|
114
|
+
// Evict before adding — ensures we never exceed cap
|
|
115
|
+
while (pool.sessions.size >= pool.maxSessions) {
|
|
116
|
+
lruEvict(pool);
|
|
117
|
+
}
|
|
118
|
+
const backend = await chooseBackend(pool.backends, spawnOpts, task);
|
|
119
|
+
if (!backend) {
|
|
120
|
+
throw new Error("no backend available");
|
|
121
|
+
}
|
|
122
|
+
// Fill in budget defaults now that the backend is known. Caller-set
|
|
123
|
+
// opts win; otherwise env / config / floor(0.85 * backend.ctx_size) /
|
|
124
|
+
// hardcoded fall through (RDR-002 v0.7 amendment). Done here rather
|
|
125
|
+
// than in qwen_spawn so the resolution can reflect the chosen
|
|
126
|
+
// backend's declared context window.
|
|
127
|
+
if (spawnOpts.max_context_tokens === undefined || spawnOpts.max_tool_calls === undefined) {
|
|
128
|
+
const defaults = getSessionBudgetDefaults(process.env, backend);
|
|
129
|
+
if (spawnOpts.max_context_tokens === undefined) {
|
|
130
|
+
spawnOpts.max_context_tokens = defaults.max_context_tokens;
|
|
131
|
+
}
|
|
132
|
+
if (spawnOpts.max_tool_calls === undefined) {
|
|
133
|
+
spawnOpts.max_tool_calls = defaults.max_tool_calls;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const session = new QwenSession(backend, task, spawnOpts, {
|
|
137
|
+
qwenRealBin: pool.qwenRealBin,
|
|
138
|
+
wrapperPath: pool.wrapperPath,
|
|
139
|
+
}, resolvedExtensions);
|
|
140
|
+
const pooledSession = Object.assign(session, { last_polled_at: Date.now() });
|
|
141
|
+
pool.sessions.set(session.task_id, pooledSession);
|
|
142
|
+
log.info({
|
|
143
|
+
task_id: session.task_id,
|
|
144
|
+
backend_id: backend.id,
|
|
145
|
+
event_type: "spawn",
|
|
146
|
+
state: "running",
|
|
147
|
+
}, "session spawned");
|
|
148
|
+
return pooledSession;
|
|
149
|
+
}
|
|
150
|
+
// ─────────────────────────────────────────────────────────────────
|
|
151
|
+
// Remove
|
|
152
|
+
export function removeSession(pool, task_id) {
|
|
153
|
+
pool.sessions.delete(task_id);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=pool.js.map
|
package/dist/pool.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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"}
|
package/dist/rerank.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// rerank.ts — direct-HTTP dispatch for `qwen_rerank`.
|
|
4
|
+
//
|
|
5
|
+
// llama-server exposes /v1/rerank (with aliases /rerank, /reranking,
|
|
6
|
+
// /v1/reranking) when started with `--reranking` and a reranker model
|
|
7
|
+
// (e.g. qwen3-reranker, bge-reranker). Returns relevance scores for
|
|
8
|
+
// each document against the query.
|
|
9
|
+
import { createLogger } from "./log.js";
|
|
10
|
+
import { dispatchOpenAIPost } from "./openai-compat.js";
|
|
11
|
+
const log = createLogger("qwen-rerank");
|
|
12
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
13
|
+
export async function dispatchRerank(backend, query, documents, opts = {}) {
|
|
14
|
+
const timeout_ms = opts.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
15
|
+
const body = {
|
|
16
|
+
model: backend.model,
|
|
17
|
+
query,
|
|
18
|
+
documents,
|
|
19
|
+
};
|
|
20
|
+
if (opts.top_n !== undefined)
|
|
21
|
+
body.top_n = opts.top_n;
|
|
22
|
+
if (opts.return_documents !== undefined) {
|
|
23
|
+
body.return_documents = opts.return_documents;
|
|
24
|
+
}
|
|
25
|
+
const outcome = await dispatchOpenAIPost(backend, "/v1/rerank", body, {
|
|
26
|
+
timeout_ms,
|
|
27
|
+
});
|
|
28
|
+
if (!outcome.ok) {
|
|
29
|
+
if (outcome.status !== undefined) {
|
|
30
|
+
log.warn({
|
|
31
|
+
backend_id: backend.id,
|
|
32
|
+
status: outcome.status,
|
|
33
|
+
body_excerpt: outcome.body_text?.slice(0, 200),
|
|
34
|
+
}, "rerank dispatch HTTP failure");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
ok: false,
|
|
38
|
+
elapsed_ms: outcome.elapsed_ms,
|
|
39
|
+
backend_id: backend.id,
|
|
40
|
+
error: outcome.error,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
let parsed;
|
|
44
|
+
try {
|
|
45
|
+
parsed = JSON.parse(outcome.body_text);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
elapsed_ms: outcome.elapsed_ms,
|
|
51
|
+
backend_id: backend.id,
|
|
52
|
+
error: {
|
|
53
|
+
code: "backend_error",
|
|
54
|
+
message: `non-JSON response: ${err.message}`,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (!Array.isArray(parsed.results) || parsed.results.length === 0) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
elapsed_ms: outcome.elapsed_ms,
|
|
62
|
+
backend_id: backend.id,
|
|
63
|
+
error: { code: "no_results", message: "backend returned empty results" },
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Normalize: ensure index + relevance_score present; flatten
|
|
67
|
+
// document.{text} shape that some servers emit.
|
|
68
|
+
const results = parsed.results
|
|
69
|
+
.filter((r) => typeof r.index === "number" && typeof r.relevance_score === "number")
|
|
70
|
+
.map((r) => {
|
|
71
|
+
const out = {
|
|
72
|
+
index: r.index,
|
|
73
|
+
relevance_score: r.relevance_score,
|
|
74
|
+
};
|
|
75
|
+
if (typeof r.document === "string") {
|
|
76
|
+
out.document = r.document;
|
|
77
|
+
}
|
|
78
|
+
else if (r.document && typeof r.document === "object" && typeof r.document.text === "string") {
|
|
79
|
+
out.document = r.document.text;
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
})
|
|
83
|
+
.sort((a, b) => b.relevance_score - a.relevance_score);
|
|
84
|
+
return {
|
|
85
|
+
ok: true,
|
|
86
|
+
results,
|
|
87
|
+
...(parsed.usage !== undefined ? { usage: parsed.usage } : {}),
|
|
88
|
+
...(parsed.model !== undefined ? { model: parsed.model } : {}),
|
|
89
|
+
elapsed_ms: outcome.elapsed_ms,
|
|
90
|
+
backend_id: backend.id,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=rerank.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rerank.js","sourceRoot":"","sources":["../src/rerank.ts"],"names":[],"mappings":"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"}
|