open-agents-ai 0.187.371 → 0.187.373
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/dist/index.js +288 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -81,6 +81,7 @@ function loadConfigFile() {
|
|
|
81
81
|
if (typeof parsed.dryRun === "boolean") result.dryRun = parsed.dryRun;
|
|
82
82
|
if (typeof parsed.verbose === "boolean") result.verbose = parsed.verbose;
|
|
83
83
|
if (typeof parsed.dbPath === "string") result.dbPath = parsed.dbPath;
|
|
84
|
+
if (typeof parsed.thinking === "boolean") result.thinking = parsed.thinking;
|
|
84
85
|
return result;
|
|
85
86
|
} catch {
|
|
86
87
|
return {};
|
|
@@ -515672,18 +515673,57 @@ function stripThinkBlocks(s2) {
|
|
|
515672
515673
|
function computeEffectiveThink(params) {
|
|
515673
515674
|
if (process.env["OA_FORCE_NO_THINK"] === "1")
|
|
515674
515675
|
return false;
|
|
515676
|
+
if (params.suppressed)
|
|
515677
|
+
return false;
|
|
515678
|
+
const userOptedIn = params.requestThink === true || params.requestThink === void 0 && params.defaultThink === true;
|
|
515679
|
+
if (userOptedIn)
|
|
515680
|
+
return true;
|
|
515681
|
+
if (params.requestThink === false)
|
|
515682
|
+
return false;
|
|
515675
515683
|
if (params.hasTools)
|
|
515676
515684
|
return false;
|
|
515677
|
-
if (
|
|
515678
|
-
return params.requestThink;
|
|
515679
|
-
if (process.env["OA_THINK_AUTO"] === "1" && Array.isArray(params.messages)) {
|
|
515685
|
+
if (process.env["OA_THINK_AUTO"] !== "0" && Array.isArray(params.messages)) {
|
|
515680
515686
|
const blob = params.messages.filter((m2) => m2.role === "user" || m2.role === "system").map((m2) => typeof m2.content === "string" ? m2.content : "").join("\n").toLowerCase();
|
|
515681
|
-
if (/\b(plan|decompose|analyze(?:\s+complex)?|step\s*by\s*step|reason through|think through)\b/.test(blob)) {
|
|
515687
|
+
if (/\b(plan|decompose|analyze(?:\s+complex)?|step\s*by\s*step|reason through|think through|reason step)\b/.test(blob)) {
|
|
515682
515688
|
return true;
|
|
515683
515689
|
}
|
|
515684
515690
|
}
|
|
515685
515691
|
return params.defaultThink;
|
|
515686
515692
|
}
|
|
515693
|
+
function sanitizeHistoryThink(messages2) {
|
|
515694
|
+
let lastAsstIdx = -1;
|
|
515695
|
+
for (let i2 = messages2.length - 1; i2 >= 0; i2--) {
|
|
515696
|
+
if (messages2[i2]?.role === "assistant") {
|
|
515697
|
+
lastAsstIdx = i2;
|
|
515698
|
+
break;
|
|
515699
|
+
}
|
|
515700
|
+
}
|
|
515701
|
+
return messages2.map((m2, i2) => {
|
|
515702
|
+
if (m2.role !== "assistant" || typeof m2.content !== "string")
|
|
515703
|
+
return m2;
|
|
515704
|
+
if (i2 === lastAsstIdx)
|
|
515705
|
+
return m2;
|
|
515706
|
+
return { ...m2, content: stripThinkBlocks(m2.content) };
|
|
515707
|
+
});
|
|
515708
|
+
}
|
|
515709
|
+
function classifyThinkOutcome(raw) {
|
|
515710
|
+
if (!raw)
|
|
515711
|
+
return "empty_after_strip";
|
|
515712
|
+
const hasOpen = /<think>/i.test(raw);
|
|
515713
|
+
const hasClose = /<\/think>/i.test(raw);
|
|
515714
|
+
if (hasOpen && !hasClose)
|
|
515715
|
+
return "unclosed_think";
|
|
515716
|
+
const stripped = stripThinkBlocks(raw);
|
|
515717
|
+
if (stripped.trim().length < 2)
|
|
515718
|
+
return "empty_after_strip";
|
|
515719
|
+
if (hasOpen && hasClose) {
|
|
515720
|
+
const thinkLen = raw.length - stripped.length;
|
|
515721
|
+
if (thinkLen > raw.length * 0.9 && stripped.trim().length < 40) {
|
|
515722
|
+
return "runaway_think";
|
|
515723
|
+
}
|
|
515724
|
+
}
|
|
515725
|
+
return null;
|
|
515726
|
+
}
|
|
515687
515727
|
var SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, VISUAL_TOOLS, AUDIO_TOOLS, SOCIAL_TOOLS, SPATIAL_TOOLS, CODE_TOOLS, AgenticRunner, OllamaAgenticBackend;
|
|
515688
515728
|
var init_agenticRunner = __esm({
|
|
515689
515729
|
"packages/orchestrator/dist/agenticRunner.js"() {
|
|
@@ -516506,6 +516546,40 @@ ${body}`;
|
|
|
516506
516546
|
}
|
|
516507
516547
|
}
|
|
516508
516548
|
}
|
|
516549
|
+
/**
|
|
516550
|
+
* Think-loop-guard runner hook. Called once per turn at the top of the
|
|
516551
|
+
* agentic loop. Responsibilities:
|
|
516552
|
+
* 1. Consume OA_THINK_GUARD_RESET env var (written by /think reset) to
|
|
516553
|
+
* clear a prior suppression — the CLI can't talk to the backend
|
|
516554
|
+
* directly, so it drops a timestamp in the env and we pick it up.
|
|
516555
|
+
* 2. Emit a one-shot user-visible warning the first turn after the
|
|
516556
|
+
* guard trips, so the user knows why answers suddenly look different.
|
|
516557
|
+
*/
|
|
516558
|
+
_lastThinkGuardResetAt = 0;
|
|
516559
|
+
_maybeApplyThinkGuard() {
|
|
516560
|
+
const resetRaw = process.env["OA_THINK_GUARD_RESET"];
|
|
516561
|
+
if (resetRaw) {
|
|
516562
|
+
const ts = Number(resetRaw);
|
|
516563
|
+
if (Number.isFinite(ts) && ts > this._lastThinkGuardResetAt) {
|
|
516564
|
+
this._lastThinkGuardResetAt = ts;
|
|
516565
|
+
if (typeof this.backend.resetThinkGuard === "function") {
|
|
516566
|
+
this.backend.resetThinkGuard();
|
|
516567
|
+
this.emit({
|
|
516568
|
+
type: "status",
|
|
516569
|
+
content: "🧠 Think-guard cleared — reasoning mode will re-enable on the next eligible request.",
|
|
516570
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
516571
|
+
});
|
|
516572
|
+
}
|
|
516573
|
+
}
|
|
516574
|
+
}
|
|
516575
|
+
if (typeof this.backend.consumeSuppressionNotice === "function" && this.backend.consumeSuppressionNotice()) {
|
|
516576
|
+
this.emit({
|
|
516577
|
+
type: "status",
|
|
516578
|
+
content: "⚠ Think-mode auto-suppressed — two consecutive empty/unclosed-<think> responses detected. Continuing with direct answers. Use `/think reset` to retry.",
|
|
516579
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
516580
|
+
});
|
|
516581
|
+
}
|
|
516582
|
+
}
|
|
516509
516583
|
/**
|
|
516510
516584
|
* Detect repetition in recent tool calls.
|
|
516511
516585
|
* Returns a score 0-1 where 1 = fully repetitive (stuck in a loop).
|
|
@@ -516784,6 +516858,7 @@ TASK: ${task}` : task;
|
|
|
516784
516858
|
}
|
|
516785
516859
|
for (let turn = 0; turn < this.options.maxTurns; turn++) {
|
|
516786
516860
|
clearTurnState(this._appState);
|
|
516861
|
+
this._maybeApplyThinkGuard();
|
|
516787
516862
|
if (this._paused) {
|
|
516788
516863
|
const shouldContinue = await this.waitIfPaused();
|
|
516789
516864
|
if (!shouldContinue) {
|
|
@@ -518264,6 +518339,7 @@ You have ${this.options.maxTurns} more turns. Continue making progress. Call tas
|
|
|
518264
518339
|
messages2.push(...compacted);
|
|
518265
518340
|
}
|
|
518266
518341
|
for (let turn = 0; turn < this.options.maxTurns; turn++) {
|
|
518342
|
+
this._maybeApplyThinkGuard();
|
|
518267
518343
|
if (this._paused) {
|
|
518268
518344
|
const shouldContinue = await this.waitIfPaused();
|
|
518269
518345
|
if (!shouldContinue) {
|
|
@@ -521120,13 +521196,23 @@ ${description}`
|
|
|
521120
521196
|
return resp;
|
|
521121
521197
|
}
|
|
521122
521198
|
};
|
|
521123
|
-
OllamaAgenticBackend = class {
|
|
521199
|
+
OllamaAgenticBackend = class _OllamaAgenticBackend {
|
|
521124
521200
|
baseUrl;
|
|
521125
521201
|
model;
|
|
521126
521202
|
apiKey;
|
|
521127
521203
|
thinking;
|
|
521128
521204
|
/** Abort signal — set by the runner so /stop can cancel in-flight requests */
|
|
521129
521205
|
_abortSignal = null;
|
|
521206
|
+
// ── Think-loop guard (0.187.372) ──────────────────────────────────────
|
|
521207
|
+
// If the model keeps producing empty / unclosed-think responses, we
|
|
521208
|
+
// assume Qwen3 dual-mode is looping and start suppressing think for
|
|
521209
|
+
// this backend instance. User can clear via /think reset.
|
|
521210
|
+
_thinkFailStreak = 0;
|
|
521211
|
+
_thinkSuccessStreak = 0;
|
|
521212
|
+
_thinkSuppressed = false;
|
|
521213
|
+
_thinkSuppressedNotified = false;
|
|
521214
|
+
static _thinkFailThreshold = 2;
|
|
521215
|
+
static _thinkRecoveryThreshold = 6;
|
|
521130
521216
|
/** Multi-key pool — round-robin rotation per request for load distribution */
|
|
521131
521217
|
_keyPool = [];
|
|
521132
521218
|
_keyIndex = 0;
|
|
@@ -521148,6 +521234,61 @@ ${description}`
|
|
|
521148
521234
|
setAbortSignal(signal) {
|
|
521149
521235
|
this._abortSignal = signal;
|
|
521150
521236
|
}
|
|
521237
|
+
/** Is think currently auto-suppressed by the loop-guard? */
|
|
521238
|
+
isThinkSuppressed() {
|
|
521239
|
+
return this._thinkSuppressed;
|
|
521240
|
+
}
|
|
521241
|
+
/** Clear the loop-guard — lets think re-enable on the next eligible request. */
|
|
521242
|
+
resetThinkGuard() {
|
|
521243
|
+
this._thinkFailStreak = 0;
|
|
521244
|
+
this._thinkSuccessStreak = 0;
|
|
521245
|
+
this._thinkSuppressed = false;
|
|
521246
|
+
this._thinkSuppressedNotified = false;
|
|
521247
|
+
}
|
|
521248
|
+
/**
|
|
521249
|
+
* Feed a completed assistant response into the loop-guard. We only
|
|
521250
|
+
* update counters on responses that WERE think=true — otherwise
|
|
521251
|
+
* think-off responses (the vast majority) would drive the counters
|
|
521252
|
+
* and mask the failure signal we're trying to detect.
|
|
521253
|
+
*
|
|
521254
|
+
* Failure classes (per classifyThinkOutcome) bump the fail streak.
|
|
521255
|
+
* Healthy think-mode responses bump the success streak and, past a
|
|
521256
|
+
* threshold, clear a prior suppression so think can come back on if
|
|
521257
|
+
* the model is behaving again.
|
|
521258
|
+
*
|
|
521259
|
+
* Returns the classification so callers can decide whether to
|
|
521260
|
+
* emit a warning / retry.
|
|
521261
|
+
*/
|
|
521262
|
+
recordThinkOutcome(raw, wasThinkRequested) {
|
|
521263
|
+
if (!wasThinkRequested)
|
|
521264
|
+
return null;
|
|
521265
|
+
const cls = classifyThinkOutcome(raw);
|
|
521266
|
+
if (cls !== null) {
|
|
521267
|
+
this._thinkFailStreak++;
|
|
521268
|
+
this._thinkSuccessStreak = 0;
|
|
521269
|
+
if (this._thinkFailStreak >= _OllamaAgenticBackend._thinkFailThreshold && !this._thinkSuppressed) {
|
|
521270
|
+
this._thinkSuppressed = true;
|
|
521271
|
+
}
|
|
521272
|
+
} else {
|
|
521273
|
+
this._thinkSuccessStreak++;
|
|
521274
|
+
this._thinkFailStreak = 0;
|
|
521275
|
+
if (this._thinkSuppressed && this._thinkSuccessStreak >= _OllamaAgenticBackend._thinkRecoveryThreshold) {
|
|
521276
|
+
this._thinkSuppressed = false;
|
|
521277
|
+
this._thinkSuppressedNotified = false;
|
|
521278
|
+
}
|
|
521279
|
+
}
|
|
521280
|
+
return cls;
|
|
521281
|
+
}
|
|
521282
|
+
/** Pick up the one-shot "notify about suppression" flag. Returns true
|
|
521283
|
+
* the first time it's called after a trip; false thereafter until
|
|
521284
|
+
* the guard resets. Used by the runner to emit a single warning. */
|
|
521285
|
+
consumeSuppressionNotice() {
|
|
521286
|
+
if (this._thinkSuppressed && !this._thinkSuppressedNotified) {
|
|
521287
|
+
this._thinkSuppressedNotified = true;
|
|
521288
|
+
return true;
|
|
521289
|
+
}
|
|
521290
|
+
return false;
|
|
521291
|
+
}
|
|
521151
521292
|
/** Build auth headers — adapts to provider (Bearer for most, x-api-key for Anthropic).
|
|
521152
521293
|
* When a key pool is set, round-robins through keys per request. */
|
|
521153
521294
|
authHeaders() {
|
|
@@ -521171,12 +521312,13 @@ ${description}`
|
|
|
521171
521312
|
if (this._isAnthropic) {
|
|
521172
521313
|
return this._anthropicChatCompletion(request);
|
|
521173
521314
|
}
|
|
521174
|
-
const cleanedMessages = request.messages
|
|
521315
|
+
const cleanedMessages = sanitizeHistoryThink(request.messages);
|
|
521175
521316
|
const effectiveThink = computeEffectiveThink({
|
|
521176
521317
|
requestThink: request.think,
|
|
521177
521318
|
defaultThink: this.thinking,
|
|
521178
521319
|
hasTools: Array.isArray(request.tools) && request.tools.length > 0,
|
|
521179
|
-
messages: cleanedMessages
|
|
521320
|
+
messages: cleanedMessages,
|
|
521321
|
+
suppressed: this._thinkSuppressed
|
|
521180
521322
|
});
|
|
521181
521323
|
let effectiveMaxTokens = request.maxTokens;
|
|
521182
521324
|
if (effectiveThink === true && (effectiveMaxTokens ?? 0) < 4096) {
|
|
@@ -521207,6 +521349,71 @@ ${description}`
|
|
|
521207
521349
|
const data = await resp.json();
|
|
521208
521350
|
const choices = data.choices ?? [];
|
|
521209
521351
|
const usage = data.usage;
|
|
521352
|
+
const firstChoice = choices[0];
|
|
521353
|
+
const responseText = firstChoice ? String(firstChoice.message?.content ?? "") : "";
|
|
521354
|
+
const outcome = this.recordThinkOutcome(responseText, effectiveThink === true);
|
|
521355
|
+
if (outcome !== null && effectiveThink === true) {
|
|
521356
|
+
const justSuppressed = this._thinkSuppressed && this._thinkFailStreak === _OllamaAgenticBackend._thinkFailThreshold;
|
|
521357
|
+
if (justSuppressed || outcome === "empty_after_strip" || outcome === "unclosed_think") {
|
|
521358
|
+
const retryBody = {
|
|
521359
|
+
model: this.model,
|
|
521360
|
+
messages: cleanedMessages,
|
|
521361
|
+
tools: request.tools,
|
|
521362
|
+
temperature: request.temperature,
|
|
521363
|
+
max_tokens: request.maxTokens,
|
|
521364
|
+
think: false
|
|
521365
|
+
};
|
|
521366
|
+
try {
|
|
521367
|
+
const retryOpts = {
|
|
521368
|
+
method: "POST",
|
|
521369
|
+
headers: this.authHeaders(),
|
|
521370
|
+
body: JSON.stringify(retryBody)
|
|
521371
|
+
};
|
|
521372
|
+
if (this._abortSignal)
|
|
521373
|
+
retryOpts.signal = this._abortSignal;
|
|
521374
|
+
const retryResp = await fetch(`${this.baseUrl}/v1/chat/completions`, retryOpts);
|
|
521375
|
+
if (retryResp.ok) {
|
|
521376
|
+
const retryData = await retryResp.json();
|
|
521377
|
+
const retryChoices = retryData.choices ?? [];
|
|
521378
|
+
const retryUsage = retryData.usage;
|
|
521379
|
+
if (retryChoices.length > 0) {
|
|
521380
|
+
return {
|
|
521381
|
+
choices: retryChoices.map((c8) => {
|
|
521382
|
+
const msg = c8.message;
|
|
521383
|
+
const toolCalls = msg.tool_calls ?? [];
|
|
521384
|
+
return {
|
|
521385
|
+
message: {
|
|
521386
|
+
content: msg.content || null,
|
|
521387
|
+
toolCalls: toolCalls.length > 0 ? toolCalls.map((tc) => {
|
|
521388
|
+
const fn = tc.function;
|
|
521389
|
+
let args;
|
|
521390
|
+
try {
|
|
521391
|
+
args = typeof fn.arguments === "string" ? JSON.parse(fn.arguments) : fn.arguments ?? {};
|
|
521392
|
+
} catch {
|
|
521393
|
+
const repaired = repairJson(fn.arguments);
|
|
521394
|
+
args = repaired ?? { _raw: fn.arguments };
|
|
521395
|
+
}
|
|
521396
|
+
return {
|
|
521397
|
+
id: tc.id || crypto.randomUUID(),
|
|
521398
|
+
name: fn.name,
|
|
521399
|
+
arguments: args
|
|
521400
|
+
};
|
|
521401
|
+
}) : void 0
|
|
521402
|
+
}
|
|
521403
|
+
};
|
|
521404
|
+
}),
|
|
521405
|
+
usage: retryUsage ? {
|
|
521406
|
+
totalTokens: retryUsage.total_tokens ?? 0,
|
|
521407
|
+
promptTokens: retryUsage.prompt_tokens,
|
|
521408
|
+
completionTokens: retryUsage.completion_tokens
|
|
521409
|
+
} : void 0
|
|
521410
|
+
};
|
|
521411
|
+
}
|
|
521412
|
+
}
|
|
521413
|
+
} catch {
|
|
521414
|
+
}
|
|
521415
|
+
}
|
|
521416
|
+
}
|
|
521210
521417
|
return {
|
|
521211
521418
|
choices: choices.map((c8) => {
|
|
521212
521419
|
const msg = c8.message;
|
|
@@ -521350,7 +521557,8 @@ ${description}`
|
|
|
521350
521557
|
requestThink: request.think,
|
|
521351
521558
|
defaultThink: this.thinking,
|
|
521352
521559
|
hasTools: Array.isArray(request.tools) && request.tools.length > 0,
|
|
521353
|
-
messages: cleanedMessages
|
|
521560
|
+
messages: cleanedMessages,
|
|
521561
|
+
suppressed: this._thinkSuppressed
|
|
521354
521562
|
});
|
|
521355
521563
|
let effectiveMaxTokens = request.maxTokens;
|
|
521356
521564
|
if (effectiveThink === true && (effectiveMaxTokens ?? 0) < 4096) {
|
|
@@ -521382,6 +521590,9 @@ ${description}`
|
|
|
521382
521590
|
}
|
|
521383
521591
|
let sseBuffer = "";
|
|
521384
521592
|
const decoder = new TextDecoder();
|
|
521593
|
+
let accumulatedContent = "";
|
|
521594
|
+
let accumulatedThinking = "";
|
|
521595
|
+
let sawReasoningTokens = false;
|
|
521385
521596
|
for await (const rawChunk of resp.body) {
|
|
521386
521597
|
sseBuffer += decoder.decode(rawChunk, { stream: true });
|
|
521387
521598
|
const parts = sseBuffer.split("\n\n");
|
|
@@ -521390,8 +521601,10 @@ ${description}`
|
|
|
521390
521601
|
const line = part.trim();
|
|
521391
521602
|
if (!line)
|
|
521392
521603
|
continue;
|
|
521393
|
-
if (line === "data: [DONE]")
|
|
521604
|
+
if (line === "data: [DONE]") {
|
|
521605
|
+
this._finalizeStreamGuard(effectiveThink, accumulatedContent, accumulatedThinking, sawReasoningTokens);
|
|
521394
521606
|
return;
|
|
521607
|
+
}
|
|
521395
521608
|
if (!line.startsWith("data: "))
|
|
521396
521609
|
continue;
|
|
521397
521610
|
try {
|
|
@@ -521415,9 +521628,12 @@ ${description}`
|
|
|
521415
521628
|
const finishReason = choice.finish_reason;
|
|
521416
521629
|
const reasoningToken = delta?.reasoning ?? delta?.reasoning_content;
|
|
521417
521630
|
if (reasoningToken) {
|
|
521631
|
+
sawReasoningTokens = true;
|
|
521632
|
+
accumulatedThinking += reasoningToken;
|
|
521418
521633
|
yield { type: "content", content: reasoningToken, thinking: true };
|
|
521419
521634
|
}
|
|
521420
521635
|
if (delta?.content) {
|
|
521636
|
+
accumulatedContent += delta.content;
|
|
521421
521637
|
yield { type: "content", content: delta.content };
|
|
521422
521638
|
}
|
|
521423
521639
|
const tcDeltas = delta?.tool_calls;
|
|
@@ -521451,6 +521667,23 @@ ${description}`
|
|
|
521451
521667
|
}
|
|
521452
521668
|
}
|
|
521453
521669
|
}
|
|
521670
|
+
this._finalizeStreamGuard(effectiveThink, accumulatedContent, accumulatedThinking, sawReasoningTokens);
|
|
521671
|
+
}
|
|
521672
|
+
/** Reconstruct a raw-looking assistant response from the streamed
|
|
521673
|
+
* parts, then feed it into the loop-guard. Used at stream end (both
|
|
521674
|
+
* the [DONE] case and the fell-off-the-end case). */
|
|
521675
|
+
_finalizeStreamGuard(thinkRequested, content, thinking, hadReasoningTokens) {
|
|
521676
|
+
if (!thinkRequested) {
|
|
521677
|
+
this.recordThinkOutcome(content, false);
|
|
521678
|
+
return;
|
|
521679
|
+
}
|
|
521680
|
+
let rawLike;
|
|
521681
|
+
if (hadReasoningTokens && thinking) {
|
|
521682
|
+
rawLike = `<think>${thinking}</think>${content}`;
|
|
521683
|
+
} else {
|
|
521684
|
+
rawLike = content;
|
|
521685
|
+
}
|
|
521686
|
+
this.recordThinkOutcome(rawLike, true);
|
|
521454
521687
|
}
|
|
521455
521688
|
};
|
|
521456
521689
|
}
|
|
@@ -533035,6 +533268,10 @@ var init_status_bar = __esm({
|
|
|
533035
533268
|
setNeovimFocusChecker(checker) {
|
|
533036
533269
|
this._isNeovimFocused = checker;
|
|
533037
533270
|
}
|
|
533271
|
+
/** Expose current mouse-tracking state for /mouse status display. */
|
|
533272
|
+
isMouseTrackingEnabled() {
|
|
533273
|
+
return this._mouseTrackingEnabled;
|
|
533274
|
+
}
|
|
533038
533275
|
/** Enable mouse tracking — respects neovim focus state */
|
|
533039
533276
|
enableMouseTracking() {
|
|
533040
533277
|
if (this._mouseTrackingEnabled || isOverlayActive()) return;
|
|
@@ -546170,13 +546407,18 @@ Clone a new voice: /voice clone <wav-file> [name]`);
|
|
|
546170
546407
|
if (token === "status" || token === "?") {
|
|
546171
546408
|
const cur = ctx3.config.thinking ?? false;
|
|
546172
546409
|
renderInfo2(`Thinking mode: ${cur ? "on" : "off"} — ${desc(cur)}`);
|
|
546173
|
-
if (process.env["OA_THINK_AUTO"]
|
|
546410
|
+
if (process.env["OA_THINK_AUTO"] !== "0") renderInfo2("Auto-heuristic active (set OA_THINK_AUTO=0 to disable) — user messages with plan/decompose/analyze/step-by-step/reason-through auto-flip to think=on, tool calls stay off.");
|
|
546174
546411
|
if (process.env["OA_FORCE_NO_THINK"] === "1") renderWarning2("OA_FORCE_NO_THINK=1 forces off regardless of /think setting");
|
|
546175
546412
|
return "handled";
|
|
546176
546413
|
}
|
|
546177
546414
|
if (token === "auto") {
|
|
546178
546415
|
process.env["OA_THINK_AUTO"] = "1";
|
|
546179
|
-
renderInfo2("Thinking auto-heuristic enabled
|
|
546416
|
+
renderInfo2("Thinking auto-heuristic enabled (default since 0.187.372). User message containing plan/decompose/analyze/step-by-step/reason-through auto-flips think=on; tool calls still force off. Disable with OA_THINK_AUTO=0.");
|
|
546417
|
+
return "handled";
|
|
546418
|
+
}
|
|
546419
|
+
if (token === "reset" || token === "clear") {
|
|
546420
|
+
process.env["OA_THINK_GUARD_RESET"] = String(Date.now());
|
|
546421
|
+
renderInfo2("Loop-guard reset requested. If think was auto-suppressed after empty/unclosed-think responses, it will re-enable on the next eligible request.");
|
|
546180
546422
|
return "handled";
|
|
546181
546423
|
}
|
|
546182
546424
|
let isOn;
|
|
@@ -546197,6 +546439,32 @@ Clone a new voice: /voice clone <wav-file> [name]`);
|
|
|
546197
546439
|
}
|
|
546198
546440
|
return "handled";
|
|
546199
546441
|
}
|
|
546442
|
+
case "mouse": {
|
|
546443
|
+
const t2 = (arg || "").trim().toLowerCase();
|
|
546444
|
+
const isOnNow = ctx3.isMouseEnabled?.() ?? true;
|
|
546445
|
+
if (t2 === "off" || t2 === "0" || t2 === "false" || t2 === "no") {
|
|
546446
|
+
ctx3.disableMouse?.();
|
|
546447
|
+
renderInfo2("Mouse tracking: off — click-drag to select text natively. Re-enable with /mouse on.");
|
|
546448
|
+
return "handled";
|
|
546449
|
+
}
|
|
546450
|
+
if (t2 === "on" || t2 === "1" || t2 === "true" || t2 === "yes") {
|
|
546451
|
+
ctx3.enableMouse?.();
|
|
546452
|
+
renderInfo2("Mouse tracking: on — header buttons + scroll wheel active. Disable with /mouse off for native text selection.");
|
|
546453
|
+
return "handled";
|
|
546454
|
+
}
|
|
546455
|
+
if (t2 === "status" || t2 === "?") {
|
|
546456
|
+
renderInfo2(`Mouse tracking: ${isOnNow ? "on" : "off"}`);
|
|
546457
|
+
return "handled";
|
|
546458
|
+
}
|
|
546459
|
+
if (isOnNow) {
|
|
546460
|
+
ctx3.disableMouse?.();
|
|
546461
|
+
renderInfo2("Mouse tracking: off — click-drag to select text natively. Re-enable with /mouse on.");
|
|
546462
|
+
} else {
|
|
546463
|
+
ctx3.enableMouse?.();
|
|
546464
|
+
renderInfo2("Mouse tracking: on — header buttons + scroll wheel active.");
|
|
546465
|
+
}
|
|
546466
|
+
return "handled";
|
|
546467
|
+
}
|
|
546200
546468
|
case "tools": {
|
|
546201
546469
|
const tools = listCustomToolFiles(ctx3.repoRoot);
|
|
546202
546470
|
if (tools.length === 0) {
|
|
@@ -582407,6 +582675,15 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
582407
582675
|
deactivateStatusBar() {
|
|
582408
582676
|
statusBar.deactivate();
|
|
582409
582677
|
},
|
|
582678
|
+
disableMouse() {
|
|
582679
|
+
statusBar.disableMouseTracking();
|
|
582680
|
+
},
|
|
582681
|
+
enableMouse() {
|
|
582682
|
+
statusBar.enableMouseTracking();
|
|
582683
|
+
},
|
|
582684
|
+
isMouseEnabled() {
|
|
582685
|
+
return statusBar.isMouseTrackingEnabled?.() ?? true;
|
|
582686
|
+
},
|
|
582410
582687
|
stopBanner() {
|
|
582411
582688
|
banner.stop();
|
|
582412
582689
|
if (carousel.isRunning) carousel.stop();
|
package/package.json
CHANGED