Revert "Fix chat completions response handling"
This reverts commit 02593e56d0.
This commit is contained in:
parent
22f293b4d6
commit
07db57d106
4 changed files with 7 additions and 66 deletions
|
|
@ -10,7 +10,7 @@ This file provides guidelines for codex agents contributing to the Sortana proje
|
||||||
- `options/`: The options page HTML, JavaScript and bundled Bulma CSS (v1.0.3).
|
- `options/`: The options page HTML, JavaScript and bundled Bulma CSS (v1.0.3).
|
||||||
- `details.html` and `details.js`: View AI reasoning and clear cache for a message.
|
- `details.html` and `details.js`: View AI reasoning and clear cache for a message.
|
||||||
- `resources/`: Images and other static files.
|
- `resources/`: Images and other static files.
|
||||||
- `prompt_templates/`: Custom/legacy templated message material kept in-repo for non-native prompt flows.
|
- `prompt_templates/`: Provider-specific templated message formats for non-OpenAI flows (qwen, mistral, harmony, plus legacy openai template material kept in-repo).
|
||||||
- `build-xpi.ps1`: PowerShell script to package the extension.
|
- `build-xpi.ps1`: PowerShell script to package the extension.
|
||||||
- `build-xpi.sh`: Bash script to package the extension.
|
- `build-xpi.sh`: Bash script to package the extension.
|
||||||
- `resources/svg2img.ps1`: PowerShell script to regenerate themed PNG icons from SVGs.
|
- `resources/svg2img.ps1`: PowerShell script to regenerate themed PNG icons from SVGs.
|
||||||
|
|
@ -38,7 +38,7 @@ There are currently no automated tests for this project. If you add tests in the
|
||||||
Sortana targets `POST /v1/chat/completions`. The endpoint value stored in settings is a base URL; the full request URL is constructed by appending `/v1/chat/completions` (adding a slash when needed) and defaulting to `https://` if no scheme is provided. Endpoint normalization strips a trailing `/v1`, `/v1/chat/completions`, `/v1/completions`, or `/v1/models`.
|
Sortana targets `POST /v1/chat/completions`. The endpoint value stored in settings is a base URL; the full request URL is constructed by appending `/v1/chat/completions` (adding a slash when needed) and defaulting to `https://` if no scheme is provided. Endpoint normalization strips a trailing `/v1`, `/v1/chat/completions`, `/v1/completions`, or `/v1/models`.
|
||||||
The options page can query `/v1/models` from the same base URL to populate the Model dropdown; selecting **None** omits the `model` field from the request payload.
|
The options page can query `/v1/models` from the same base URL to populate the Model dropdown; selecting **None** omits the `model` field from the request payload.
|
||||||
Advanced options allow an optional API key plus `OpenAI-Organization` and `OpenAI-Project` headers; these headers are only sent when values are provided.
|
Advanced options allow an optional API key plus `OpenAI-Organization` and `OpenAI-Project` headers; these headers are only sent when values are provided.
|
||||||
Requests use a Chat Completions `messages` array and ask for strict JSON schema output via `response_format`. Built-in request formats send native `system` and `user` chat messages; only the custom format sends a single templated user message. Responses are parsed from `choices[0].message`, with `match` as a boolean and `reason` as a short string, and parsing falls back to the last JSON object if a backend prepends extra reasoning text. Unsupported OpenAI sampling fields are filtered out, and the saved `max_tokens` setting is translated to `max_completion_tokens`.
|
Requests use a Chat Completions `messages` array and ask for strict JSON schema output via `response_format`. Responses are parsed from `choices[0].message`, with `match` as a boolean and `reason` as a short string. Unsupported OpenAI sampling fields are filtered out, and the saved `max_tokens` setting is translated to `max_completion_tokens`.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ Classification requests ask the model for structured JSON output with a required
|
||||||
- **Configurable endpoint** – set the classification service base URL on the options page.
|
- **Configurable endpoint** – set the classification service base URL on the options page.
|
||||||
- **Model selection** – load available models from the endpoint and choose one (or omit the model field).
|
- **Model selection** – load available models from the endpoint and choose one (or omit the model field).
|
||||||
- **Optional OpenAI auth headers** – provide an API key plus optional organization/project headers when needed.
|
- **Optional OpenAI auth headers** – provide an API key plus optional organization/project headers when needed.
|
||||||
- **Request formats** – built-in formats use native chat messages; a custom format can still send one templated user message when needed.
|
- **Request formats** – use native OpenAI chat messages or choose Qwen, Mistral, Harmony (gpt-oss), or a custom templated message format.
|
||||||
- **Custom system prompts** – tailor the instructions sent to the model for more precise results.
|
- **Custom system prompts** – tailor the instructions sent to the model for more precise results.
|
||||||
- **Persistent result caching** – classification results and reasoning are saved to disk so messages aren't re-evaluated across restarts.
|
- **Persistent result caching** – classification results and reasoning are saved to disk so messages aren't re-evaluated across restarts.
|
||||||
- **Advanced parameters** – tune generation settings like temperature and top‑p from the options page. Unsupported OpenAI sampling fields are filtered out automatically.
|
- **Advanced parameters** – tune generation settings like temperature and top‑p from the options page. Unsupported OpenAI sampling fields are filtered out automatically.
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ Classification criterion: ${criterion}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMessages(body, criterion) {
|
function buildMessages(body, criterion) {
|
||||||
if (gTemplateName !== "custom") {
|
if (gTemplateName === "openai") {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
role: "system",
|
role: "system",
|
||||||
|
|
@ -391,56 +391,6 @@ function extractMessageContent(content) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractLastJsonObject(text) {
|
|
||||||
if (typeof text !== "string" || !text) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let last = null;
|
|
||||||
let start = -1;
|
|
||||||
let depth = 0;
|
|
||||||
let inString = false;
|
|
||||||
let escape = false;
|
|
||||||
|
|
||||||
for (let i = 0; i < text.length; i += 1) {
|
|
||||||
const ch = text[i];
|
|
||||||
if (inString) {
|
|
||||||
if (escape) {
|
|
||||||
escape = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ch === "\\") {
|
|
||||||
escape = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ch === "\"") {
|
|
||||||
inString = false;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ch === "\"") {
|
|
||||||
inString = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ch === "{") {
|
|
||||||
if (depth === 0) {
|
|
||||||
start = i;
|
|
||||||
}
|
|
||||||
depth += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ch === "}" && depth > 0) {
|
|
||||||
depth -= 1;
|
|
||||||
if (depth === 0 && start !== -1) {
|
|
||||||
last = text.slice(start, i + 1);
|
|
||||||
start = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return last;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseMatch(result) {
|
function parseMatch(result) {
|
||||||
const message = result?.choices?.[0]?.message;
|
const message = result?.choices?.[0]?.message;
|
||||||
if (!message || typeof message !== "object") {
|
if (!message || typeof message !== "object") {
|
||||||
|
|
@ -474,18 +424,9 @@ function parseMatch(result) {
|
||||||
try {
|
try {
|
||||||
obj = JSON.parse(extracted.text);
|
obj = JSON.parse(extracted.text);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const candidate = extractLastJsonObject(extracted.text);
|
|
||||||
if (!candidate) {
|
|
||||||
reportParseError("Failed to parse JSON from AI response.", extracted.text.slice(0, 800));
|
reportParseError("Failed to parse JSON from AI response.", extracted.text.slice(0, 800));
|
||||||
return { matched: false, reason: "" };
|
return { matched: false, reason: "" };
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
obj = JSON.parse(candidate);
|
|
||||||
} catch (inner) {
|
|
||||||
reportParseError("Failed to parse JSON from AI response.", extracted.text.slice(0, 800));
|
|
||||||
return { matched: false, reason: "" };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof obj?.match !== "boolean") {
|
if (typeof obj?.match !== "boolean") {
|
||||||
reportParseError("AI response missing valid match boolean.", extracted.text.slice(0, 800));
|
reportParseError("AI response missing valid match boolean.", extracted.text.slice(0, 800));
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
<select id="template"></select>
|
<select id="template"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help">Built-in formats use native chat messages over Chat Completions. Custom format sends one templated user message.</p>
|
<p class="help">OpenAI Chat uses native chat messages. Other formats send one templated user message over Chat Completions.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="custom-template-container" class="field is-hidden">
|
<div id="custom-template-container" class="field is-hidden">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue