@map-audio/pam-mcp-server 1.27.0 → 1.28.0
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 +31 -10
- package/dist/bridge.d.ts +5 -1
- package/dist/bridge.js +41 -40
- package/dist/bridge.js.map +1 -1
- package/dist/daemon.d.ts +32 -0
- package/dist/daemon.js +871 -0
- package/dist/daemon.js.map +7 -0
- package/dist/drumSynth.d.ts +12 -0
- package/dist/drumSynth.js +14 -2
- package/dist/drumSynth.js.map +1 -1
- package/dist/drumSynthEngines.json +9 -1
- package/dist/{fgemma-format.d.ts → functiongemma-format.d.ts} +25 -7
- package/dist/{fgemma-format.js → functiongemma-format.js} +34 -11
- package/dist/functiongemma-format.js.map +1 -0
- package/dist/functiongemma-grammar.d.ts +14 -0
- package/dist/functiongemma-grammar.js +140 -0
- package/dist/functiongemma-grammar.js.map +1 -0
- package/dist/functiongemma-params.d.ts +33 -0
- package/dist/functiongemma-params.js +128 -0
- package/dist/functiongemma-params.js.map +1 -0
- package/dist/{fgemma-runner.d.ts → functiongemma-runner.d.ts} +8 -5
- package/dist/{fgemma-runner.js → functiongemma-runner.js} +87 -21
- package/dist/functiongemma-runner.js.map +1 -0
- package/dist/generativePlayerPresets.json +9 -0
- package/dist/generativePlayers.json +14 -0
- package/dist/launcher.d.ts +2 -0
- package/dist/launcher.js +36 -0
- package/dist/launcher.js.map +1 -0
- package/dist/manifest-mfx.json +12920 -277
- package/dist/manifest-msq.json +1989 -107
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +7 -27
- package/dist/manifest.js.map +1 -1
- package/dist/manifest.json +24194 -345
- package/dist/mfxCombos.d.ts +2 -0
- package/dist/mfxCombos.js +179 -56
- package/dist/mfxCombos.js.map +1 -1
- package/dist/midiFile.d.ts +19 -5
- package/dist/midiFile.js +21 -13
- package/dist/midiFile.js.map +1 -1
- package/dist/mixAssist.js +3 -2
- package/dist/mixAssist.js.map +1 -1
- package/dist/players.d.ts +22 -0
- package/dist/players.js +70 -0
- package/dist/players.js.map +1 -1
- package/dist/productProfile.d.ts +4 -4
- package/dist/productProfile.js +10 -1
- package/dist/productProfile.js.map +1 -1
- package/dist/qwen-format.d.ts +85 -0
- package/dist/qwen-format.js +355 -0
- package/dist/qwen-format.js.map +1 -0
- package/dist/registration.mjs +41 -0
- package/dist/server.js +1309 -187
- package/dist/server.js.map +1 -1
- package/dist/variationSessionKeys.json +6 -4
- package/package.json +13 -7
- package/dist/fgemma-format.js.map +0 -1
- package/dist/fgemma-runner.js.map +0 -1
- package/dist/manifest-cell1.json +0 -12968
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | JsonObject;
|
|
2
|
+
export interface JsonObject {
|
|
3
|
+
[key: string]: JsonValue;
|
|
4
|
+
}
|
|
5
|
+
/** A tool declaration exactly as its JSON was authored: its key order is part of the prompt. */
|
|
6
|
+
export type QwenToolDef = JsonObject & {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
parameters: JsonObject;
|
|
10
|
+
};
|
|
11
|
+
export interface QwenFunctionCall {
|
|
12
|
+
name: string;
|
|
13
|
+
arguments: JsonObject;
|
|
14
|
+
}
|
|
15
|
+
export type QwenToolCall = QwenFunctionCall | {
|
|
16
|
+
function: QwenFunctionCall;
|
|
17
|
+
};
|
|
18
|
+
export interface QwenTextMessage {
|
|
19
|
+
role: "system" | "developer" | "user";
|
|
20
|
+
content: string;
|
|
21
|
+
}
|
|
22
|
+
export interface QwenAssistantMessage {
|
|
23
|
+
role: "assistant";
|
|
24
|
+
content?: string;
|
|
25
|
+
tool_calls?: QwenToolCall[];
|
|
26
|
+
}
|
|
27
|
+
/** `content` is `{name, response}` as in the dataset rows, or text that is already rendered. */
|
|
28
|
+
export interface QwenToolMessage {
|
|
29
|
+
role: "tool";
|
|
30
|
+
content: JsonValue;
|
|
31
|
+
}
|
|
32
|
+
export type QwenMessage = QwenTextMessage | QwenAssistantMessage | QwenToolMessage;
|
|
33
|
+
export interface QwenHistoryExchange {
|
|
34
|
+
/** RAW user text of the past exchange (history turns carry no ctx line). */
|
|
35
|
+
user: string;
|
|
36
|
+
/** `renderQwenExchange` of the assistant and tool turns that answered it. */
|
|
37
|
+
model: string;
|
|
38
|
+
}
|
|
39
|
+
export declare const QWEN_SYSTEM_TEXT = "You are a model that can do function calling with the following functions";
|
|
40
|
+
/** Non-thinking generation prompt: the template pre-fills an empty think block. */
|
|
41
|
+
export declare const QWEN_GENERATION_PROMPT = "<|im_start|>assistant\n<think>\n\n</think>\n\n";
|
|
42
|
+
export declare const QWEN_STOP_SEQUENCES: string[];
|
|
43
|
+
/** The benchmark's cap; observed completions stay under 300 tokens. */
|
|
44
|
+
export declare const QWEN_MAX_NEW_TOKENS = 1024;
|
|
45
|
+
export declare function pyStrip(text: string): string;
|
|
46
|
+
/** Python `str()` of a number (`json` selects json.dumps spelling for non-finite values). An integral
|
|
47
|
+
* value renders as an int: JS cannot tell `1.0` from `1`. */
|
|
48
|
+
export declare function pyNumber(n: number, json?: boolean): string;
|
|
49
|
+
/** `json.dumps(value, ensure_ascii=False, sort_keys=sortKeys)`: `, ` and `: ` separators, Python floats. */
|
|
50
|
+
export declare function pyJson(value: JsonValue, sortKeys?: boolean): string;
|
|
51
|
+
export declare function renderQwenSystemTurn(tools: QwenToolDef[], systemText?: string | null): string;
|
|
52
|
+
export declare function renderQwenUserTurn(text: string): string;
|
|
53
|
+
export declare function renderQwenToolCall(call: QwenToolCall): string;
|
|
54
|
+
/** Port of the chat template: assistant turns after the last user query carry a think block. */
|
|
55
|
+
export declare function renderQwenChat(tools: QwenToolDef[], messages: QwenMessage[], generation?: boolean): string;
|
|
56
|
+
/** The assistant and tool turns of one COMPLETED exchange, as they render before a later user turn. */
|
|
57
|
+
export declare function renderQwenExchange(messages: QwenMessage[]): string;
|
|
58
|
+
export interface QwenPromptParts {
|
|
59
|
+
history?: QwenHistoryExchange[];
|
|
60
|
+
/** Assistant and tool turns this command has already taken: after the last user turn, so with think blocks. */
|
|
61
|
+
rounds?: QwenMessage[];
|
|
62
|
+
systemText?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Generation prompt: declarations, completed history exchanges, the user turn, this command's rounds. */
|
|
65
|
+
export declare function buildQwenGenerationPrompt(tools: QwenToolDef[], userText: string, parts?: QwenPromptParts): string;
|
|
66
|
+
export interface QwenCompletion {
|
|
67
|
+
/** The completion up to its first turn boundary. */
|
|
68
|
+
text: string;
|
|
69
|
+
/** The model wrote past its own turn (a second `<|im_start|>`, an invented `<tool_response>`). */
|
|
70
|
+
fabricated: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** Cut a completion at its first turn boundary; nothing after the cut may be executed. */
|
|
73
|
+
export declare function trimQwenCompletion(text: string): QwenCompletion;
|
|
74
|
+
export interface QwenParse {
|
|
75
|
+
calls: QwenFunctionCall[];
|
|
76
|
+
/** Text outside every call block, special tokens removed. */
|
|
77
|
+
content: string;
|
|
78
|
+
}
|
|
79
|
+
/** Parse a completion as the benchmark's reference parser does, coercing `<parameter=KEY>` values by the declared
|
|
80
|
+
* schema type. A block cut before its closing tags still yields a call: gate on `hasCompleteQwenToolCalls`. */
|
|
81
|
+
export declare function parseQwenOutput(text: string, tools: QwenToolDef[]): QwenParse;
|
|
82
|
+
export declare function parseQwenToolCalls(text: string, tools: QwenToolDef[]): QwenFunctionCall[];
|
|
83
|
+
/** True when the completion holds exactly `callCount` call blocks and every block and parameter is closed.
|
|
84
|
+
* A stray extra `</parameter>` (IQ2_M writes one) is not a cut-off; the reference parser reads past it. */
|
|
85
|
+
export declare function hasCompleteQwenToolCalls(text: string, callCount: number): boolean;
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
// Qwen native chat/tool wire format: renderer + parser. Byte parity with the pinned HF chat template is
|
|
2
|
+
// asserted by scripts/check-qwen-format.mjs against packages/ml-research/data/contracts/fixtures/qwen/.
|
|
3
|
+
export const QWEN_SYSTEM_TEXT = "You are a model that can do function calling with the following functions";
|
|
4
|
+
/** Non-thinking generation prompt: the template pre-fills an empty think block. */
|
|
5
|
+
export const QWEN_GENERATION_PROMPT = "<|im_start|>assistant\n<think>\n\n</think>\n\n";
|
|
6
|
+
export const QWEN_STOP_SEQUENCES = ["<|im_end|>", "<|im_start|>", "<|endoftext|>", "<tool_response>"];
|
|
7
|
+
/** The benchmark's cap; observed completions stay under 300 tokens. */
|
|
8
|
+
export const QWEN_MAX_NEW_TOKENS = 1024;
|
|
9
|
+
const TOOLS_HEAD = "# Tools\n\nYou have access to the following functions:\n\n<tools>";
|
|
10
|
+
const TOOLS_TAIL = "\n</tools>\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n" +
|
|
11
|
+
"<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n" +
|
|
12
|
+
"<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n" +
|
|
13
|
+
"</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n" +
|
|
14
|
+
"- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested " +
|
|
15
|
+
"within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n" +
|
|
16
|
+
"- You may provide optional reasoning for your function call in natural language BEFORE the function call, " +
|
|
17
|
+
"but NOT after\n- If there is no function call available, answer the question like normal with your current " +
|
|
18
|
+
"knowledge and do not tell the user about function calls\n</IMPORTANT>";
|
|
19
|
+
const isString = (value) => typeof value === "string";
|
|
20
|
+
const isNumber = (value) => typeof value === "number";
|
|
21
|
+
const isBoolean = (value) => typeof value === "boolean";
|
|
22
|
+
const isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
+
// --- Python value formatting ---------------------------------------------
|
|
24
|
+
// Python's str.strip() set: unlike JS trim() it takes U+001C-U+001F and U+0085 and leaves U+FEFF.
|
|
25
|
+
const PY_SPACE = "\\t-\\r\\x1c-\\x20\\x85\\xa0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000";
|
|
26
|
+
const PY_STRIP = new RegExp(`^[${PY_SPACE}]+|[${PY_SPACE}]+$`, "g");
|
|
27
|
+
export function pyStrip(text) {
|
|
28
|
+
return text.replace(PY_STRIP, "");
|
|
29
|
+
}
|
|
30
|
+
/** Python `str()` of a number (`json` selects json.dumps spelling for non-finite values). An integral
|
|
31
|
+
* value renders as an int: JS cannot tell `1.0` from `1`. */
|
|
32
|
+
export function pyNumber(n, json = false) {
|
|
33
|
+
if (Number.isNaN(n))
|
|
34
|
+
return json ? "NaN" : "nan";
|
|
35
|
+
if (!Number.isFinite(n))
|
|
36
|
+
return `${n < 0 ? "-" : ""}${json ? "Infinity" : "inf"}`;
|
|
37
|
+
if (Number.isInteger(n))
|
|
38
|
+
return Math.abs(n) < 1e21 ? String(n) : BigInt(n).toString();
|
|
39
|
+
const [mantissa, exponent] = n.toExponential().split("e");
|
|
40
|
+
const e = Number(exponent);
|
|
41
|
+
// repr() switches to exponent form below 1e-4, with at least two exponent digits.
|
|
42
|
+
return e >= -4 ? String(n) : `${mantissa}e-${String(-e).padStart(2, "0")}`;
|
|
43
|
+
}
|
|
44
|
+
function compareCodePoints(a, b) {
|
|
45
|
+
const x = Array.from(a);
|
|
46
|
+
const y = Array.from(b);
|
|
47
|
+
for (let i = 0; i < Math.min(x.length, y.length); i++) {
|
|
48
|
+
const d = (x[i].codePointAt(0) ?? 0) - (y[i].codePointAt(0) ?? 0);
|
|
49
|
+
if (d)
|
|
50
|
+
return d;
|
|
51
|
+
}
|
|
52
|
+
return x.length - y.length;
|
|
53
|
+
}
|
|
54
|
+
/** `json.dumps(value, ensure_ascii=False, sort_keys=sortKeys)`: `, ` and `: ` separators, Python floats. */
|
|
55
|
+
export function pyJson(value, sortKeys = false) {
|
|
56
|
+
if (value === null)
|
|
57
|
+
return "null";
|
|
58
|
+
if (isString(value))
|
|
59
|
+
return JSON.stringify(value);
|
|
60
|
+
if (isNumber(value))
|
|
61
|
+
return pyNumber(value, true);
|
|
62
|
+
if (isBoolean(value))
|
|
63
|
+
return value ? "true" : "false";
|
|
64
|
+
if (Array.isArray(value))
|
|
65
|
+
return `[${value.map((item) => pyJson(item, sortKeys)).join(", ")}]`;
|
|
66
|
+
const entries = Object.entries(value);
|
|
67
|
+
if (sortKeys)
|
|
68
|
+
entries.sort(([a], [b]) => compareCodePoints(a, b));
|
|
69
|
+
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}: ${pyJson(item, sortKeys)}`).join(", ")}}`;
|
|
70
|
+
}
|
|
71
|
+
/** A tool-call argument as the template prints it: containers as JSON, scalars through Python `str()`. */
|
|
72
|
+
function renderArgument(value) {
|
|
73
|
+
if (isString(value))
|
|
74
|
+
return value;
|
|
75
|
+
if (value === null)
|
|
76
|
+
return "None";
|
|
77
|
+
if (isBoolean(value))
|
|
78
|
+
return value ? "True" : "False";
|
|
79
|
+
return isNumber(value) ? pyNumber(value) : pyJson(value);
|
|
80
|
+
}
|
|
81
|
+
// --- Renderer ------------------------------------------------------------
|
|
82
|
+
export function renderQwenSystemTurn(tools, systemText = QWEN_SYSTEM_TEXT) {
|
|
83
|
+
const text = pyStrip(systemText ?? "");
|
|
84
|
+
if (!tools.length)
|
|
85
|
+
return systemText === null ? "" : `<|im_start|>system\n${text}<|im_end|>\n`;
|
|
86
|
+
// Training declares a tool as build_dataset.hf_tool does: name, description and parameters, nothing else.
|
|
87
|
+
const declarations = tools
|
|
88
|
+
.map(({ name, description, parameters }) => `\n${pyJson({ type: "function", function: { name, description, parameters } })}`)
|
|
89
|
+
.join("");
|
|
90
|
+
return `<|im_start|>system\n${TOOLS_HEAD}${declarations}${TOOLS_TAIL}${text ? `\n\n${text}` : ""}<|im_end|>\n`;
|
|
91
|
+
}
|
|
92
|
+
export function renderQwenUserTurn(text) {
|
|
93
|
+
return `<|im_start|>user\n${pyStrip(text)}<|im_end|>\n`;
|
|
94
|
+
}
|
|
95
|
+
export function renderQwenToolCall(call) {
|
|
96
|
+
const { name, arguments: args } = "function" in call ? call.function : call;
|
|
97
|
+
const parameters = Object.entries(args)
|
|
98
|
+
.map(([key, value]) => `<parameter=${key}>\n${renderArgument(value)}\n</parameter>\n`)
|
|
99
|
+
.join("");
|
|
100
|
+
return `<tool_call>\n<function=${name}>\n${parameters}</function>\n</tool_call>`;
|
|
101
|
+
}
|
|
102
|
+
function messageText(message) {
|
|
103
|
+
if (message.role !== "tool")
|
|
104
|
+
return pyStrip(message.content ?? "");
|
|
105
|
+
return pyStrip(isString(message.content) ? message.content : pyJson(message.content, true));
|
|
106
|
+
}
|
|
107
|
+
function renderAssistantTurn(message, think) {
|
|
108
|
+
let content = messageText(message);
|
|
109
|
+
let reasoning = "";
|
|
110
|
+
if (content.includes("</think>")) {
|
|
111
|
+
const parts = content.split("</think>");
|
|
112
|
+
reasoning = (parts[0].replace(/\n+$/, "").split("<think>").pop() ?? "").replace(/^\n+/, "");
|
|
113
|
+
content = parts[parts.length - 1].replace(/^\n+/, "");
|
|
114
|
+
}
|
|
115
|
+
let turn = `<|im_start|>assistant\n${think ? `<think>\n${pyStrip(reasoning)}\n</think>\n\n` : ""}${content}`;
|
|
116
|
+
(message.tool_calls ?? []).forEach((call, i) => {
|
|
117
|
+
turn += `${i ? "\n" : pyStrip(content) ? "\n\n" : ""}${renderQwenToolCall(call)}`;
|
|
118
|
+
});
|
|
119
|
+
return `${turn}<|im_end|>\n`;
|
|
120
|
+
}
|
|
121
|
+
// Consecutive tool messages share one user turn, opened and closed by their neighbours' roles.
|
|
122
|
+
function renderToolTurn(message, previous, next) {
|
|
123
|
+
const open = previous && previous.role !== "tool" ? "<|im_start|>user" : "";
|
|
124
|
+
const close = !next || next.role !== "tool" ? "<|im_end|>\n" : "";
|
|
125
|
+
return `${open}\n<tool_response>\n${messageText(message)}\n</tool_response>${close}`;
|
|
126
|
+
}
|
|
127
|
+
function isToolResponseCarrier(message) {
|
|
128
|
+
const content = messageText(message);
|
|
129
|
+
return content.startsWith("<tool_response>") && content.endsWith("</tool_response>");
|
|
130
|
+
}
|
|
131
|
+
/** Port of the chat template: assistant turns after the last user query carry a think block. */
|
|
132
|
+
export function renderQwenChat(tools, messages, generation = true) {
|
|
133
|
+
if (!messages.length)
|
|
134
|
+
throw new Error("No messages provided.");
|
|
135
|
+
const first = messages[0];
|
|
136
|
+
const systemText = first.role === "system" || first.role === "developer" ? first.content : null;
|
|
137
|
+
let lastQuery = -1;
|
|
138
|
+
for (let i = messages.length - 1; i >= 0 && lastQuery < 0; i--) {
|
|
139
|
+
if (messages[i].role === "user" && !isToolResponseCarrier(messages[i]))
|
|
140
|
+
lastQuery = i;
|
|
141
|
+
}
|
|
142
|
+
if (lastQuery < 0)
|
|
143
|
+
throw new Error("No user query found in messages.");
|
|
144
|
+
let prompt = renderQwenSystemTurn(tools, systemText);
|
|
145
|
+
messages.forEach((message, i) => {
|
|
146
|
+
if (message.role === "user")
|
|
147
|
+
prompt += renderQwenUserTurn(message.content);
|
|
148
|
+
else if (message.role === "assistant")
|
|
149
|
+
prompt += renderAssistantTurn(message, i > lastQuery);
|
|
150
|
+
else if (message.role === "tool")
|
|
151
|
+
prompt += renderToolTurn(message, messages[i - 1], messages[i + 1]);
|
|
152
|
+
else if (i > 0)
|
|
153
|
+
throw new Error("System message must be at the beginning.");
|
|
154
|
+
});
|
|
155
|
+
return generation ? prompt + QWEN_GENERATION_PROMPT : prompt;
|
|
156
|
+
}
|
|
157
|
+
const QUERY_ANCHOR = { role: "user", content: "" };
|
|
158
|
+
function renderTurns(messages, think) {
|
|
159
|
+
return messages
|
|
160
|
+
.map((message, i) => message.role === "assistant"
|
|
161
|
+
? renderAssistantTurn(message, think)
|
|
162
|
+
: renderToolTurn(message, messages[i - 1] ?? QUERY_ANCHOR, messages[i + 1]))
|
|
163
|
+
.join("");
|
|
164
|
+
}
|
|
165
|
+
/** The assistant and tool turns of one COMPLETED exchange, as they render before a later user turn. */
|
|
166
|
+
export function renderQwenExchange(messages) {
|
|
167
|
+
return renderTurns(messages, false);
|
|
168
|
+
}
|
|
169
|
+
/** Generation prompt: declarations, completed history exchanges, the user turn, this command's rounds. */
|
|
170
|
+
export function buildQwenGenerationPrompt(tools, userText, parts = {}) {
|
|
171
|
+
let prompt = renderQwenSystemTurn(tools, parts.systemText ?? QWEN_SYSTEM_TEXT);
|
|
172
|
+
for (const exchange of parts.history ?? [])
|
|
173
|
+
prompt += renderQwenUserTurn(exchange.user) + exchange.model;
|
|
174
|
+
return prompt + renderQwenUserTurn(userText) + renderTurns(parts.rounds ?? [], true) + QWEN_GENERATION_PROMPT;
|
|
175
|
+
}
|
|
176
|
+
// --- Completion guard ------------------------------------------------------
|
|
177
|
+
const TURN_MARKERS = ["<|im_end|>", "<|im_start|>", "<|endoftext|>", "<tool_response>"];
|
|
178
|
+
/** Cut a completion at its first turn boundary; nothing after the cut may be executed. */
|
|
179
|
+
export function trimQwenCompletion(text) {
|
|
180
|
+
const cut = Math.min(text.length, ...TURN_MARKERS.map((m) => text.indexOf(m)).filter((at) => at !== -1));
|
|
181
|
+
const rest = text.slice(cut).replace(/^(?:<\|im_end\|>|<\|endoftext\|>|\s)+/, "");
|
|
182
|
+
return { text: text.slice(0, cut), fabricated: rest.length > 0 };
|
|
183
|
+
}
|
|
184
|
+
// The reference parser (vLLM `qwen3_coder`) lexes these literals, longest first at each position.
|
|
185
|
+
const TERMINALS = new Map([
|
|
186
|
+
["<tool_call>", "tool_start"],
|
|
187
|
+
["</tool_call>", "tool_end"],
|
|
188
|
+
["<function=", "func_prefix"],
|
|
189
|
+
["</function>", "func_end"],
|
|
190
|
+
["<parameter=", "arg"],
|
|
191
|
+
["</parameter>", "arg"],
|
|
192
|
+
["<think>", "think"],
|
|
193
|
+
["</think>", "think_end"],
|
|
194
|
+
[">", "close_angle"],
|
|
195
|
+
]);
|
|
196
|
+
// Special tokens the reference parser drops wherever they appear.
|
|
197
|
+
const DROPPED = [
|
|
198
|
+
"<|im_end|>", "<|endoftext|>", "<|im_start|>", "<|object_ref_start|>", "<|object_ref_end|>", "<|box_start|>",
|
|
199
|
+
"<|box_end|>", "<|quad_start|>", "<|quad_end|>", "<|vision_start|>", "<|vision_end|>", "<|vision_pad|>",
|
|
200
|
+
"<|image_pad|>", "<|video_pad|>", "<|audio_start|>", "<|audio_end|>", "<|audio_pad|>",
|
|
201
|
+
];
|
|
202
|
+
const LITERALS = [...TERMINALS.keys(), ...DROPPED].sort((a, b) => b.length - a.length);
|
|
203
|
+
const PARAMETER = /<\s*parameter\s*=\s*([^>]*)>(.*?)(?:<\s*\/\s*parameter\s*>|(?=<\s*parameter\s*=))/gs;
|
|
204
|
+
const TYPE_ALIASES = new Map([
|
|
205
|
+
["str", "string"], ["text", "string"], ["varchar", "string"], ["char", "string"], ["enum", "string"],
|
|
206
|
+
["int", "integer"], ["int32", "integer"], ["int64", "integer"], ["uint", "integer"], ["uint32", "integer"],
|
|
207
|
+
["uint64", "integer"], ["long", "integer"], ["short", "integer"], ["unsigned", "integer"],
|
|
208
|
+
["float", "number"], ["float32", "number"], ["float64", "number"], ["double", "number"],
|
|
209
|
+
["bool", "boolean"], ["dict", "object"], ["arr", "array"], ["list", "array"], ["sequence", "array"],
|
|
210
|
+
]);
|
|
211
|
+
function jsonTypeName(value) {
|
|
212
|
+
if (value === null)
|
|
213
|
+
return "null";
|
|
214
|
+
if (isString(value))
|
|
215
|
+
return "string";
|
|
216
|
+
if (isBoolean(value))
|
|
217
|
+
return "boolean";
|
|
218
|
+
if (isNumber(value))
|
|
219
|
+
return Number.isInteger(value) ? "integer" : "number";
|
|
220
|
+
return Array.isArray(value) ? "array" : "object";
|
|
221
|
+
}
|
|
222
|
+
function schemaTypes(schema) {
|
|
223
|
+
const types = new Set();
|
|
224
|
+
if (!isJsonObject(schema))
|
|
225
|
+
return types.add("string");
|
|
226
|
+
for (const type of Array.isArray(schema.type) ? schema.type : [schema.type])
|
|
227
|
+
if (isString(type))
|
|
228
|
+
types.add(type);
|
|
229
|
+
for (const member of Array.isArray(schema.enum) ? schema.enum : [])
|
|
230
|
+
types.add(jsonTypeName(member));
|
|
231
|
+
for (const key of ["anyOf", "oneOf", "allOf"]) {
|
|
232
|
+
const choices = schema[key];
|
|
233
|
+
for (const choice of Array.isArray(choices) ? choices : [])
|
|
234
|
+
for (const type of schemaTypes(choice))
|
|
235
|
+
types.add(type);
|
|
236
|
+
}
|
|
237
|
+
return types.size ? types : types.add("string");
|
|
238
|
+
}
|
|
239
|
+
function canonicalType(type) {
|
|
240
|
+
const key = pyStrip(type).toLowerCase();
|
|
241
|
+
return TYPE_ALIASES.get(key) ?? key;
|
|
242
|
+
}
|
|
243
|
+
const PY_INT = /^[+-]?\d+(?:_\d+)*$/;
|
|
244
|
+
const PY_FLOAT = /^[+-]?(?:\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\.\d+(?:_\d+)*)(?:[eE][+-]?\d+(?:_\d+)*)?$/;
|
|
245
|
+
function isJsonFinite(value) {
|
|
246
|
+
if (isNumber(value))
|
|
247
|
+
return Number.isFinite(value);
|
|
248
|
+
if (Array.isArray(value))
|
|
249
|
+
return value.every(isJsonFinite);
|
|
250
|
+
return isJsonObject(value) ? Object.values(value).every(isJsonFinite) : true;
|
|
251
|
+
}
|
|
252
|
+
// JSON has no integer -0 and JS cannot spell a float one, so every parsed zero is +0.
|
|
253
|
+
function parseFiniteJson(text) {
|
|
254
|
+
try {
|
|
255
|
+
const parsed = JSON.parse(text, (_key, item) => (item === 0 ? 0 : item));
|
|
256
|
+
return isJsonFinite(parsed) ? parsed : undefined;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/** The reference `coerce_to_schema_type`: the first type that accepts the raw text wins, in this order. */
|
|
263
|
+
function coerceToSchemaType(value, schema) {
|
|
264
|
+
const types = new Set([...schemaTypes(schema)].map(canonicalType));
|
|
265
|
+
// int() and float() skip only C whitespace around an all-ASCII string, the full Unicode set otherwise.
|
|
266
|
+
const literal = /^[\x00-\x7f]*$/.test(value) ? value.replace(/^[ \t-\r]+|[ \t-\r]+$/g, "") : pyStrip(value);
|
|
267
|
+
const number = Number(literal.replace(/_/g, "")) || 0;
|
|
268
|
+
if (types.has("null") && value.toLowerCase() === "null")
|
|
269
|
+
return null;
|
|
270
|
+
if (types.has("integer") && PY_INT.test(literal))
|
|
271
|
+
return number;
|
|
272
|
+
if (types.has("number") && PY_FLOAT.test(literal) && Number.isFinite(number))
|
|
273
|
+
return number;
|
|
274
|
+
if (types.has("boolean")) {
|
|
275
|
+
const lower = pyStrip(value.toLowerCase());
|
|
276
|
+
if (lower === "true" || lower === "1")
|
|
277
|
+
return true;
|
|
278
|
+
if (lower === "false" || lower === "0")
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const parsed = parseFiniteJson(value);
|
|
282
|
+
if ((types.has("object") || types.has("array")) && parsed !== undefined)
|
|
283
|
+
return parsed;
|
|
284
|
+
return types.has("string") || parsed === undefined ? value : parsed;
|
|
285
|
+
}
|
|
286
|
+
function parseArguments(body, properties) {
|
|
287
|
+
const declared = isJsonObject(properties) && Object.keys(properties).length > 0 ? properties : null;
|
|
288
|
+
const parsed = new Map();
|
|
289
|
+
for (const [, key, text] of body.matchAll(PARAMETER)) {
|
|
290
|
+
const schema = declared && Object.hasOwn(declared, key) ? declared[key] : undefined;
|
|
291
|
+
const value = text.replace(/^\n/, "").replace(/\n$/, "");
|
|
292
|
+
parsed.set(key, isJsonObject(schema) ? coerceToSchemaType(value, schema) : value);
|
|
293
|
+
}
|
|
294
|
+
return Object.fromEntries(parsed);
|
|
295
|
+
}
|
|
296
|
+
/** Parse a completion as the benchmark's reference parser does, coercing `<parameter=KEY>` values by the declared
|
|
297
|
+
* schema type. A block cut before its closing tags still yields a call: gate on `hasCompleteQwenToolCalls`. */
|
|
298
|
+
export function parseQwenOutput(text, tools) {
|
|
299
|
+
const slots = [];
|
|
300
|
+
let state = "content";
|
|
301
|
+
let content = "";
|
|
302
|
+
const emit = (value) => {
|
|
303
|
+
if (state === "content")
|
|
304
|
+
content += value;
|
|
305
|
+
else if (state === "name")
|
|
306
|
+
slots[slots.length - 1].name += value;
|
|
307
|
+
else if (state === "args")
|
|
308
|
+
slots[slots.length - 1].args += value;
|
|
309
|
+
};
|
|
310
|
+
for (let i = 0; i < text.length;) {
|
|
311
|
+
const literal = text[i] === "<" || text[i] === ">" ? LITERALS.find((l) => text.startsWith(l, i)) : undefined;
|
|
312
|
+
if (!literal) {
|
|
313
|
+
emit(text[i++]);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
i += literal.length;
|
|
317
|
+
const terminal = TERMINALS.get(literal);
|
|
318
|
+
if (!terminal)
|
|
319
|
+
continue;
|
|
320
|
+
if ((terminal === "tool_start" || terminal === "func_prefix") && (state === "content" || state === "between")) {
|
|
321
|
+
slots.push({ name: "", args: "" });
|
|
322
|
+
state = terminal === "tool_start" ? "preamble" : "name";
|
|
323
|
+
}
|
|
324
|
+
else if (terminal === "func_prefix" && state === "preamble")
|
|
325
|
+
state = "name";
|
|
326
|
+
else if (terminal === "tool_end" && (state === "preamble" || state === "between"))
|
|
327
|
+
state = "content";
|
|
328
|
+
else if (terminal === "close_angle" && state === "name")
|
|
329
|
+
state = "args";
|
|
330
|
+
else if (terminal === "func_end" && (state === "name" || state === "args"))
|
|
331
|
+
state = "between";
|
|
332
|
+
else if (terminal !== "think_end" || state !== "content")
|
|
333
|
+
emit(literal);
|
|
334
|
+
}
|
|
335
|
+
const calls = [];
|
|
336
|
+
for (const slot of slots) {
|
|
337
|
+
const name = pyStrip(slot.name);
|
|
338
|
+
if (!name)
|
|
339
|
+
continue;
|
|
340
|
+
const tool = tools.find((t) => t.name === name);
|
|
341
|
+
calls.push({ name, arguments: parseArguments(slot.args, tool?.parameters.properties) });
|
|
342
|
+
}
|
|
343
|
+
return { calls, content: pyStrip(content) };
|
|
344
|
+
}
|
|
345
|
+
export function parseQwenToolCalls(text, tools) {
|
|
346
|
+
return parseQwenOutput(text, tools).calls;
|
|
347
|
+
}
|
|
348
|
+
/** True when the completion holds exactly `callCount` call blocks and every block and parameter is closed.
|
|
349
|
+
* A stray extra `</parameter>` (IQ2_M writes one) is not a cut-off; the reference parser reads past it. */
|
|
350
|
+
export function hasCompleteQwenToolCalls(text, callCount) {
|
|
351
|
+
const count = (pattern) => text.match(pattern)?.length ?? 0;
|
|
352
|
+
return ([/<tool_call>/g, /<\/tool_call>/g, /<function=/g, /<\/function>/g].every((p) => count(p) === callCount) &&
|
|
353
|
+
count(/<parameter=/g) <= count(/<\/parameter>/g));
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=qwen-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-format.js","sourceRoot":"","sources":["../src/qwen-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { lstat, open, readdir } from 'node:fs/promises';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
5
|
+
|
|
6
|
+
// Read at load: a pam mcp session later points PAM_AI_DATA_ROOT at its model root, not the plugin's.
|
|
7
|
+
const INHERITED_DATA_ROOT = process.env.PAM_AI_DATA_ROOT;
|
|
8
|
+
|
|
9
|
+
export function registrationDirectory() {
|
|
10
|
+
const configured = INHERITED_DATA_ROOT;
|
|
11
|
+
const root = configured && isAbsolute(configured) ? configured : process.platform === 'darwin'
|
|
12
|
+
? resolve(homedir(), 'Library/Application Support/MAP Audio/PAM')
|
|
13
|
+
: resolve(process.env.APPDATA || resolve(homedir(), '.config'), 'MAP Audio/PAM');
|
|
14
|
+
return resolve(root, 'bridge/instances');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function readBridgeRegistrations(directory = registrationDirectory()) {
|
|
18
|
+
const entries = [];
|
|
19
|
+
let names;
|
|
20
|
+
try { names = await readdir(directory); } catch { return entries; }
|
|
21
|
+
for (const name of names.sort()) {
|
|
22
|
+
if (!name.endsWith('.json')) continue;
|
|
23
|
+
let file;
|
|
24
|
+
try {
|
|
25
|
+
// O_NOFOLLOW does not exist on Windows, so refuse links before opening as well.
|
|
26
|
+
if ((await lstat(resolve(directory, name))).isSymbolicLink()) continue;
|
|
27
|
+
file = await open(resolve(directory, name), constants.O_RDONLY | (constants.O_NOFOLLOW || 0));
|
|
28
|
+
const info = await file.stat();
|
|
29
|
+
if (!info.isFile() || info.size <= 0 || info.size > 16384
|
|
30
|
+
|| (process.getuid && (info.uid !== process.getuid() || (info.mode & 0o077) !== 0))) continue;
|
|
31
|
+
const record = JSON.parse(await file.readFile('utf8'));
|
|
32
|
+
if (!record || typeof record.instanceId !== 'string' || record.instanceId.length === 0 || typeof record.product !== 'string'
|
|
33
|
+
|| typeof record.token !== 'string' || !/^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/.test(record.token)
|
|
34
|
+
|| !Number.isInteger(record.port) || record.port <= 0 || record.port > 65535
|
|
35
|
+
|| !Number.isInteger(record.pid) || record.pid <= 0) continue;
|
|
36
|
+
try { process.kill(record.pid, 0); } catch (error) { if (error.code !== 'EPERM') continue; }
|
|
37
|
+
entries.push({ port: record.port, pid: record.pid, instanceId: record.instanceId, product: record.product, token: record.token });
|
|
38
|
+
} catch {} finally { await file?.close(); }
|
|
39
|
+
}
|
|
40
|
+
return entries;
|
|
41
|
+
}
|