feat: add /reasoning reasoning visibility
This commit is contained in:
@@ -603,6 +603,7 @@ Quick reference (send these in chat):
|
|||||||
| `/activation mention\|always` | Group activation (owner-only) |
|
| `/activation mention\|always` | Group activation (owner-only) |
|
||||||
| `/think <level>` | Set thinking level (off\|minimal\|low\|medium\|high) |
|
| `/think <level>` | Set thinking level (off\|minimal\|low\|medium\|high) |
|
||||||
| `/verbose on\|off` | Toggle verbose mode |
|
| `/verbose on\|off` | Toggle verbose mode |
|
||||||
|
| `/reasoning on\|off` | Toggle reasoning visibility |
|
||||||
| `/elevated on\|off` | Toggle elevated bash mode (approved senders only) |
|
| `/elevated on\|off` | Toggle elevated bash mode (approved senders only) |
|
||||||
| `/model <name>` | Switch AI model (see below) |
|
| `/model <name>` | Switch AI model (see below) |
|
||||||
| `/queue <mode>` | Queue mode (see below) |
|
| `/queue <mode>` | Queue mode (see below) |
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ Text + native (when enabled):
|
|||||||
- `/reset` or `/new`
|
- `/reset` or `/new`
|
||||||
- `/think <level>` (aliases: `/thinking`, `/t`)
|
- `/think <level>` (aliases: `/thinking`, `/t`)
|
||||||
- `/verbose on|off` (alias: `/v`)
|
- `/verbose on|off` (alias: `/v`)
|
||||||
|
- `/reasoning on|off` (alias: `/reason`)
|
||||||
- `/elevated on|off` (alias: `/elev`)
|
- `/elevated on|off` (alias: `/elev`)
|
||||||
- `/model <name>`
|
- `/model <name>`
|
||||||
- `/queue <mode>` (plus options like `debounce:2s cap:25 drop:summarize`)
|
- `/queue <mode>` (plus options like `debounce:2s cap:25 drop:summarize`)
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ read_when:
|
|||||||
- Inline directive affects only that message; session/global defaults apply otherwise.
|
- Inline directive affects only that message; session/global defaults apply otherwise.
|
||||||
- When verbose is on, agents that emit structured tool results (Pi, other JSON agents) send each tool result back as its own metadata-only message, prefixed with `<emoji> <tool-name>: <arg>` when available (path/command); the tool output itself is not forwarded. These tool summaries are sent as soon as each tool finishes (separate bubbles), not as streaming deltas. If you toggle `/verbose on|off` while a run is in-flight, subsequent tool bubbles honor the new setting.
|
- When verbose is on, agents that emit structured tool results (Pi, other JSON agents) send each tool result back as its own metadata-only message, prefixed with `<emoji> <tool-name>: <arg>` when available (path/command); the tool output itself is not forwarded. These tool summaries are sent as soon as each tool finishes (separate bubbles), not as streaming deltas. If you toggle `/verbose on|off` while a run is in-flight, subsequent tool bubbles honor the new setting.
|
||||||
|
|
||||||
|
## Reasoning visibility (/reasoning)
|
||||||
|
- Levels: `on|off`.
|
||||||
|
- Directive-only message toggles whether thinking blocks are shown as italic text in replies.
|
||||||
|
- When enabled, any model-provided reasoning content is appended as a separate italic block.
|
||||||
|
- Alias: `/reason`.
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
- Elevated mode docs live in [`docs/elevated.md`](/tools/elevated).
|
- Elevated mode docs live in [`docs/elevated.md`](/tools/elevated).
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ Use SSH tunneling or Tailscale to reach the Gateway WS.
|
|||||||
- `/model <provider/model>` (or `/model list`, `/models`)
|
- `/model <provider/model>` (or `/model list`, `/models`)
|
||||||
- `/think <off|minimal|low|medium|high>`
|
- `/think <off|minimal|low|medium|high>`
|
||||||
- `/verbose <on|off>`
|
- `/verbose <on|off>`
|
||||||
|
- `/reasoning <on|off>`
|
||||||
- `/elevated <on|off>`
|
- `/elevated <on|off>`
|
||||||
- `/elev <on|off>`
|
- `/elev <on|off>`
|
||||||
- `/activation <mention|always>`
|
- `/activation <mention|always>`
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ import {
|
|||||||
type Skill,
|
type Skill,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/pi-coding-agent";
|
||||||
import { resolveHeartbeatPrompt } from "../auto-reply/heartbeat.js";
|
import { resolveHeartbeatPrompt } from "../auto-reply/heartbeat.js";
|
||||||
import type { ThinkLevel, VerboseLevel } from "../auto-reply/thinking.js";
|
import type {
|
||||||
|
ReasoningLevel,
|
||||||
|
ThinkLevel,
|
||||||
|
VerboseLevel,
|
||||||
|
} from "../auto-reply/thinking.js";
|
||||||
import { formatToolAggregate } from "../auto-reply/tool-meta.js";
|
import { formatToolAggregate } from "../auto-reply/tool-meta.js";
|
||||||
import type { ClawdbotConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
import { getMachineDisplayName } from "../infra/machine-name.js";
|
import { getMachineDisplayName } from "../infra/machine-name.js";
|
||||||
@@ -53,7 +57,11 @@ import {
|
|||||||
type BlockReplyChunking,
|
type BlockReplyChunking,
|
||||||
subscribeEmbeddedPiSession,
|
subscribeEmbeddedPiSession,
|
||||||
} from "./pi-embedded-subscribe.js";
|
} from "./pi-embedded-subscribe.js";
|
||||||
import { extractAssistantText } from "./pi-embedded-utils.js";
|
import {
|
||||||
|
extractAssistantText,
|
||||||
|
extractAssistantThinking,
|
||||||
|
formatReasoningMarkdown,
|
||||||
|
} from "./pi-embedded-utils.js";
|
||||||
import { toToolDefinitions } from "./pi-tool-definition-adapter.js";
|
import { toToolDefinitions } from "./pi-tool-definition-adapter.js";
|
||||||
import { createClawdbotCodingTools } from "./pi-tools.js";
|
import { createClawdbotCodingTools } from "./pi-tools.js";
|
||||||
import { resolveSandboxContext } from "./sandbox.js";
|
import { resolveSandboxContext } from "./sandbox.js";
|
||||||
@@ -575,6 +583,7 @@ export async function runEmbeddedPiAgent(params: {
|
|||||||
authProfileId?: string;
|
authProfileId?: string;
|
||||||
thinkLevel?: ThinkLevel;
|
thinkLevel?: ThinkLevel;
|
||||||
verboseLevel?: VerboseLevel;
|
verboseLevel?: VerboseLevel;
|
||||||
|
reasoningLevel?: ReasoningLevel;
|
||||||
bashElevated?: BashElevatedDefaults;
|
bashElevated?: BashElevatedDefaults;
|
||||||
timeoutMs: number;
|
timeoutMs: number;
|
||||||
runId: string;
|
runId: string;
|
||||||
@@ -846,6 +855,7 @@ export async function runEmbeddedPiAgent(params: {
|
|||||||
session,
|
session,
|
||||||
runId: params.runId,
|
runId: params.runId,
|
||||||
verboseLevel: params.verboseLevel,
|
verboseLevel: params.verboseLevel,
|
||||||
|
includeReasoning: params.reasoningLevel === "on",
|
||||||
shouldEmitToolResult: params.shouldEmitToolResult,
|
shouldEmitToolResult: params.shouldEmitToolResult,
|
||||||
onToolResult: params.onToolResult,
|
onToolResult: params.onToolResult,
|
||||||
onBlockReply: params.onBlockReply,
|
onBlockReply: params.onBlockReply,
|
||||||
@@ -1064,10 +1074,22 @@ export async function runEmbeddedPiAgent(params: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fallbackText = lastAssistant
|
||||||
|
? (() => {
|
||||||
|
const base = extractAssistantText(lastAssistant);
|
||||||
|
if (params.reasoningLevel !== "on") return base;
|
||||||
|
const thinking = extractAssistantThinking(lastAssistant);
|
||||||
|
const formatted = thinking
|
||||||
|
? formatReasoningMarkdown(thinking)
|
||||||
|
: "";
|
||||||
|
if (!formatted) return base;
|
||||||
|
return base ? `${base}\n\n${formatted}` : formatted;
|
||||||
|
})()
|
||||||
|
: "";
|
||||||
for (const text of assistantTexts.length
|
for (const text of assistantTexts.length
|
||||||
? assistantTexts
|
? assistantTexts
|
||||||
: lastAssistant
|
: fallbackText
|
||||||
? [extractAssistantText(lastAssistant)]
|
? [fallbackText]
|
||||||
: []) {
|
: []) {
|
||||||
const { text: cleanedText, mediaUrls } = splitMediaFromOutput(text);
|
const { text: cleanedText, mediaUrls } = splitMediaFromOutput(text);
|
||||||
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0))
|
if (!cleanedText && (!mediaUrls || mediaUrls.length === 0))
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import type { BlockReplyChunking } from "./pi-embedded-block-chunker.js";
|
|||||||
import { EmbeddedBlockChunker } from "./pi-embedded-block-chunker.js";
|
import { EmbeddedBlockChunker } from "./pi-embedded-block-chunker.js";
|
||||||
import {
|
import {
|
||||||
extractAssistantText,
|
extractAssistantText,
|
||||||
|
extractAssistantThinking,
|
||||||
|
formatReasoningMarkdown,
|
||||||
inferToolMetaFromArgs,
|
inferToolMetaFromArgs,
|
||||||
} from "./pi-embedded-utils.js";
|
} from "./pi-embedded-utils.js";
|
||||||
|
|
||||||
@@ -85,6 +87,7 @@ export function subscribeEmbeddedPiSession(params: {
|
|||||||
session: AgentSession;
|
session: AgentSession;
|
||||||
runId: string;
|
runId: string;
|
||||||
verboseLevel?: "off" | "on";
|
verboseLevel?: "off" | "on";
|
||||||
|
includeReasoning?: boolean;
|
||||||
shouldEmitToolResult?: () => boolean;
|
shouldEmitToolResult?: () => boolean;
|
||||||
onToolResult?: (payload: {
|
onToolResult?: (payload: {
|
||||||
text?: string;
|
text?: string;
|
||||||
@@ -120,6 +123,7 @@ export function subscribeEmbeddedPiSession(params: {
|
|||||||
let pendingCompactionRetry = 0;
|
let pendingCompactionRetry = 0;
|
||||||
let compactionRetryResolve: (() => void) | undefined;
|
let compactionRetryResolve: (() => void) | undefined;
|
||||||
let compactionRetryPromise: Promise<void> | null = null;
|
let compactionRetryPromise: Promise<void> | null = null;
|
||||||
|
let lastReasoningSent: string | undefined;
|
||||||
|
|
||||||
const ensureCompactionPromise = () => {
|
const ensureCompactionPromise = () => {
|
||||||
if (!compactionRetryPromise) {
|
if (!compactionRetryPromise) {
|
||||||
@@ -216,6 +220,24 @@ export function subscribeEmbeddedPiSession(params: {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const extractThinkingFromText = (text: string): string => {
|
||||||
|
if (!text || !THINKING_TAG_RE.test(text)) return "";
|
||||||
|
THINKING_TAG_RE.lastIndex = 0;
|
||||||
|
let result = "";
|
||||||
|
let lastIndex = 0;
|
||||||
|
let inThinking = false;
|
||||||
|
for (const match of text.matchAll(THINKING_TAG_RE)) {
|
||||||
|
const idx = match.index ?? 0;
|
||||||
|
if (inThinking) {
|
||||||
|
result += text.slice(lastIndex, idx);
|
||||||
|
}
|
||||||
|
const tag = match[0].toLowerCase();
|
||||||
|
inThinking = !tag.includes("/");
|
||||||
|
lastIndex = idx + match[0].length;
|
||||||
|
}
|
||||||
|
return result.trim();
|
||||||
|
};
|
||||||
|
|
||||||
const resetForCompactionRetry = () => {
|
const resetForCompactionRetry = () => {
|
||||||
assistantTexts.length = 0;
|
assistantTexts.length = 0;
|
||||||
toolMetas.length = 0;
|
toolMetas.length = 0;
|
||||||
@@ -244,6 +266,7 @@ export function subscribeEmbeddedPiSession(params: {
|
|||||||
blockChunker?.reset();
|
blockChunker?.reset();
|
||||||
lastStreamedAssistant = undefined;
|
lastStreamedAssistant = undefined;
|
||||||
lastBlockReplyText = undefined;
|
lastBlockReplyText = undefined;
|
||||||
|
lastReasoningSent = undefined;
|
||||||
assistantTextBaseline = assistantTexts.length;
|
assistantTextBaseline = assistantTexts.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,19 +493,26 @@ export function subscribeEmbeddedPiSession(params: {
|
|||||||
if (evt.type === "message_end") {
|
if (evt.type === "message_end") {
|
||||||
const msg = (evt as AgentEvent & { message: AgentMessage }).message;
|
const msg = (evt as AgentEvent & { message: AgentMessage }).message;
|
||||||
if (msg?.role === "assistant") {
|
if (msg?.role === "assistant") {
|
||||||
|
const assistantMessage = msg as AssistantMessage;
|
||||||
|
const rawText = extractAssistantText(assistantMessage);
|
||||||
const cleaned = params.enforceFinalTag
|
const cleaned = params.enforceFinalTag
|
||||||
? stripThinkingSegments(
|
? stripThinkingSegments(stripUnpairedThinkingTags(rawText))
|
||||||
stripUnpairedThinkingTags(
|
: stripThinkingSegments(rawText);
|
||||||
extractAssistantText(msg as AssistantMessage),
|
const baseText =
|
||||||
),
|
|
||||||
)
|
|
||||||
: stripThinkingSegments(
|
|
||||||
extractAssistantText(msg as AssistantMessage),
|
|
||||||
);
|
|
||||||
const text =
|
|
||||||
params.enforceFinalTag && cleaned
|
params.enforceFinalTag && cleaned
|
||||||
? (extractFinalText(cleaned)?.trim() ?? cleaned)
|
? (extractFinalText(cleaned)?.trim() ?? cleaned)
|
||||||
: cleaned;
|
: cleaned;
|
||||||
|
const rawThinking = params.includeReasoning
|
||||||
|
? extractAssistantThinking(assistantMessage) ||
|
||||||
|
extractThinkingFromText(rawText)
|
||||||
|
: "";
|
||||||
|
const formattedReasoning = rawThinking
|
||||||
|
? formatReasoningMarkdown(rawThinking)
|
||||||
|
: "";
|
||||||
|
const text =
|
||||||
|
baseText && formattedReasoning
|
||||||
|
? `${baseText}\n\n${formattedReasoning}`
|
||||||
|
: baseText || formattedReasoning;
|
||||||
|
|
||||||
const addedDuringMessage =
|
const addedDuringMessage =
|
||||||
assistantTexts.length > assistantTextBaseline;
|
assistantTexts.length > assistantTextBaseline;
|
||||||
@@ -516,6 +546,16 @@ export function subscribeEmbeddedPiSession(params: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const onBlockReply = params.onBlockReply;
|
||||||
|
const shouldEmitReasoningBlock =
|
||||||
|
Boolean(formattedReasoning) &&
|
||||||
|
Boolean(onBlockReply) &&
|
||||||
|
formattedReasoning !== lastReasoningSent &&
|
||||||
|
(blockReplyBreak === "text_end" || Boolean(blockChunker));
|
||||||
|
if (shouldEmitReasoningBlock && formattedReasoning && onBlockReply) {
|
||||||
|
lastReasoningSent = formattedReasoning;
|
||||||
|
void onBlockReply({ text: formattedReasoning });
|
||||||
|
}
|
||||||
deltaBuffer = "";
|
deltaBuffer = "";
|
||||||
blockBuffer = "";
|
blockBuffer = "";
|
||||||
blockChunker?.reset();
|
blockChunker?.reset();
|
||||||
|
|||||||
@@ -19,6 +19,32 @@ export function extractAssistantText(msg: AssistantMessage): string {
|
|||||||
return blocks.join("\n").trim();
|
return blocks.join("\n").trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function extractAssistantThinking(msg: AssistantMessage): string {
|
||||||
|
if (!Array.isArray(msg.content)) return "";
|
||||||
|
const blocks = msg.content
|
||||||
|
.map((block) => {
|
||||||
|
if (!block || typeof block !== "object") return "";
|
||||||
|
const record = block as unknown as Record<string, unknown>;
|
||||||
|
if (record.type === "thinking" && typeof record.thinking === "string") {
|
||||||
|
return record.thinking.trim();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
return blocks.join("\n").trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatReasoningMarkdown(text: string): string {
|
||||||
|
const trimmed = text.trim();
|
||||||
|
if (!trimmed) return "";
|
||||||
|
const lines = trimmed.split(/\r?\n/);
|
||||||
|
const wrapped = lines
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.map((line) => (line ? `_${line}_` : ""))
|
||||||
|
.filter((line) => line.length > 0);
|
||||||
|
return wrapped.length > 0 ? [`_Reasoning:_`, ...wrapped].join("\n") : "";
|
||||||
|
}
|
||||||
|
|
||||||
export function inferToolMetaFromArgs(
|
export function inferToolMetaFromArgs(
|
||||||
toolName: string,
|
toolName: string,
|
||||||
args: unknown,
|
args: unknown,
|
||||||
|
|||||||
@@ -79,6 +79,13 @@ const CHAT_COMMANDS: ChatCommandDefinition[] = [
|
|||||||
textAliases: ["/verbose", "/v"],
|
textAliases: ["/verbose", "/v"],
|
||||||
acceptsArgs: true,
|
acceptsArgs: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "reasoning",
|
||||||
|
nativeName: "reasoning",
|
||||||
|
description: "Toggle reasoning visibility.",
|
||||||
|
textAliases: ["/reasoning", "/reason"],
|
||||||
|
acceptsArgs: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "elevated",
|
key: "elevated",
|
||||||
nativeName: "elevated",
|
nativeName: "elevated",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { drainSystemEvents } from "../infra/system-events.js";
|
|||||||
import {
|
import {
|
||||||
extractElevatedDirective,
|
extractElevatedDirective,
|
||||||
extractQueueDirective,
|
extractQueueDirective,
|
||||||
|
extractReasoningDirective,
|
||||||
extractReplyToTag,
|
extractReplyToTag,
|
||||||
extractThinkDirective,
|
extractThinkDirective,
|
||||||
extractVerboseDirective,
|
extractVerboseDirective,
|
||||||
@@ -99,6 +100,12 @@ describe("directive parsing", () => {
|
|||||||
expect(res.verboseLevel).toBe("on");
|
expect(res.verboseLevel).toBe("on");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("matches reasoning directive", () => {
|
||||||
|
const res = extractReasoningDirective("/reasoning on please");
|
||||||
|
expect(res.hasDirective).toBe(true);
|
||||||
|
expect(res.reasoningLevel).toBe("on");
|
||||||
|
});
|
||||||
|
|
||||||
it("matches elevated with leading space", () => {
|
it("matches elevated with leading space", () => {
|
||||||
const res = extractElevatedDirective(" please /elevated on now");
|
const res = extractElevatedDirective(" please /elevated on now");
|
||||||
expect(res.hasDirective).toBe(true);
|
expect(res.hasDirective).toBe(true);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import type { MsgContext, TemplateContext } from "./templating.js";
|
|||||||
import {
|
import {
|
||||||
type ElevatedLevel,
|
type ElevatedLevel,
|
||||||
normalizeThinkLevel,
|
normalizeThinkLevel,
|
||||||
|
type ReasoningLevel,
|
||||||
type ThinkLevel,
|
type ThinkLevel,
|
||||||
type VerboseLevel,
|
type VerboseLevel,
|
||||||
} from "./thinking.js";
|
} from "./thinking.js";
|
||||||
@@ -75,6 +76,7 @@ import type { GetReplyOptions, ReplyPayload } from "./types.js";
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
extractElevatedDirective,
|
extractElevatedDirective,
|
||||||
|
extractReasoningDirective,
|
||||||
extractThinkDirective,
|
extractThinkDirective,
|
||||||
extractVerboseDirective,
|
extractVerboseDirective,
|
||||||
} from "./reply/directives.js";
|
} from "./reply/directives.js";
|
||||||
@@ -288,6 +290,9 @@ export async function getReplyFromConfig(
|
|||||||
hasVerboseDirective: false,
|
hasVerboseDirective: false,
|
||||||
verboseLevel: undefined,
|
verboseLevel: undefined,
|
||||||
rawVerboseLevel: undefined,
|
rawVerboseLevel: undefined,
|
||||||
|
hasReasoningDirective: false,
|
||||||
|
reasoningLevel: undefined,
|
||||||
|
rawReasoningLevel: undefined,
|
||||||
hasElevatedDirective: false,
|
hasElevatedDirective: false,
|
||||||
elevatedLevel: undefined,
|
elevatedLevel: undefined,
|
||||||
rawElevatedLevel: undefined,
|
rawElevatedLevel: undefined,
|
||||||
@@ -310,6 +315,7 @@ export async function getReplyFromConfig(
|
|||||||
const hasDirective =
|
const hasDirective =
|
||||||
parsedDirectives.hasThinkDirective ||
|
parsedDirectives.hasThinkDirective ||
|
||||||
parsedDirectives.hasVerboseDirective ||
|
parsedDirectives.hasVerboseDirective ||
|
||||||
|
parsedDirectives.hasReasoningDirective ||
|
||||||
parsedDirectives.hasElevatedDirective ||
|
parsedDirectives.hasElevatedDirective ||
|
||||||
parsedDirectives.hasStatusDirective ||
|
parsedDirectives.hasStatusDirective ||
|
||||||
parsedDirectives.hasModelDirective ||
|
parsedDirectives.hasModelDirective ||
|
||||||
@@ -327,6 +333,7 @@ export async function getReplyFromConfig(
|
|||||||
...parsedDirectives,
|
...parsedDirectives,
|
||||||
hasThinkDirective: false,
|
hasThinkDirective: false,
|
||||||
hasVerboseDirective: false,
|
hasVerboseDirective: false,
|
||||||
|
hasReasoningDirective: false,
|
||||||
hasStatusDirective: false,
|
hasStatusDirective: false,
|
||||||
hasModelDirective: false,
|
hasModelDirective: false,
|
||||||
hasQueueDirective: false,
|
hasQueueDirective: false,
|
||||||
@@ -377,6 +384,10 @@ export async function getReplyFromConfig(
|
|||||||
(directives.verboseLevel as VerboseLevel | undefined) ??
|
(directives.verboseLevel as VerboseLevel | undefined) ??
|
||||||
(sessionEntry?.verboseLevel as VerboseLevel | undefined) ??
|
(sessionEntry?.verboseLevel as VerboseLevel | undefined) ??
|
||||||
(agentCfg?.verboseDefault as VerboseLevel | undefined);
|
(agentCfg?.verboseDefault as VerboseLevel | undefined);
|
||||||
|
const resolvedReasoningLevel: ReasoningLevel =
|
||||||
|
(directives.reasoningLevel as ReasoningLevel | undefined) ??
|
||||||
|
(sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ??
|
||||||
|
"off";
|
||||||
const resolvedElevatedLevel = elevatedAllowed
|
const resolvedElevatedLevel = elevatedAllowed
|
||||||
? ((directives.elevatedLevel as ElevatedLevel | undefined) ??
|
? ((directives.elevatedLevel as ElevatedLevel | undefined) ??
|
||||||
(sessionEntry?.elevatedLevel as ElevatedLevel | undefined) ??
|
(sessionEntry?.elevatedLevel as ElevatedLevel | undefined) ??
|
||||||
@@ -542,6 +553,7 @@ export async function getReplyFromConfig(
|
|||||||
defaultGroupActivation: () => defaultActivation,
|
defaultGroupActivation: () => defaultActivation,
|
||||||
resolvedThinkLevel,
|
resolvedThinkLevel,
|
||||||
resolvedVerboseLevel: resolvedVerboseLevel ?? "off",
|
resolvedVerboseLevel: resolvedVerboseLevel ?? "off",
|
||||||
|
resolvedReasoningLevel,
|
||||||
resolvedElevatedLevel,
|
resolvedElevatedLevel,
|
||||||
resolveDefaultThinkingLevel: modelState.resolveDefaultThinkingLevel,
|
resolveDefaultThinkingLevel: modelState.resolveDefaultThinkingLevel,
|
||||||
provider,
|
provider,
|
||||||
@@ -734,6 +746,7 @@ export async function getReplyFromConfig(
|
|||||||
authProfileId,
|
authProfileId,
|
||||||
thinkLevel: resolvedThinkLevel,
|
thinkLevel: resolvedThinkLevel,
|
||||||
verboseLevel: resolvedVerboseLevel,
|
verboseLevel: resolvedVerboseLevel,
|
||||||
|
reasoningLevel: resolvedReasoningLevel,
|
||||||
elevatedLevel: resolvedElevatedLevel,
|
elevatedLevel: resolvedElevatedLevel,
|
||||||
bashElevated: {
|
bashElevated: {
|
||||||
enabled: elevatedEnabled,
|
enabled: elevatedEnabled,
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ export async function runReplyAgent(params: {
|
|||||||
authProfileId: followupRun.run.authProfileId,
|
authProfileId: followupRun.run.authProfileId,
|
||||||
thinkLevel: followupRun.run.thinkLevel,
|
thinkLevel: followupRun.run.thinkLevel,
|
||||||
verboseLevel: followupRun.run.verboseLevel,
|
verboseLevel: followupRun.run.verboseLevel,
|
||||||
|
reasoningLevel: followupRun.run.reasoningLevel,
|
||||||
bashElevated: followupRun.run.bashElevated,
|
bashElevated: followupRun.run.bashElevated,
|
||||||
timeoutMs: followupRun.run.timeoutMs,
|
timeoutMs: followupRun.run.timeoutMs,
|
||||||
runId,
|
runId,
|
||||||
|
|||||||
@@ -41,7 +41,12 @@ import {
|
|||||||
formatTokenCount,
|
formatTokenCount,
|
||||||
} from "../status.js";
|
} from "../status.js";
|
||||||
import type { MsgContext } from "../templating.js";
|
import type { MsgContext } from "../templating.js";
|
||||||
import type { ElevatedLevel, ThinkLevel, VerboseLevel } from "../thinking.js";
|
import type {
|
||||||
|
ElevatedLevel,
|
||||||
|
ReasoningLevel,
|
||||||
|
ThinkLevel,
|
||||||
|
VerboseLevel,
|
||||||
|
} from "../thinking.js";
|
||||||
import type { ReplyPayload } from "../types.js";
|
import type { ReplyPayload } from "../types.js";
|
||||||
import { isAbortTrigger, setAbortMemory } from "./abort.js";
|
import { isAbortTrigger, setAbortMemory } from "./abort.js";
|
||||||
import type { InlineDirectives } from "./directive-handling.js";
|
import type { InlineDirectives } from "./directive-handling.js";
|
||||||
@@ -202,6 +207,7 @@ export async function handleCommands(params: {
|
|||||||
defaultGroupActivation: () => "always" | "mention";
|
defaultGroupActivation: () => "always" | "mention";
|
||||||
resolvedThinkLevel?: ThinkLevel;
|
resolvedThinkLevel?: ThinkLevel;
|
||||||
resolvedVerboseLevel: VerboseLevel;
|
resolvedVerboseLevel: VerboseLevel;
|
||||||
|
resolvedReasoningLevel: ReasoningLevel;
|
||||||
resolvedElevatedLevel?: ElevatedLevel;
|
resolvedElevatedLevel?: ElevatedLevel;
|
||||||
resolveDefaultThinkingLevel: () => Promise<ThinkLevel | undefined>;
|
resolveDefaultThinkingLevel: () => Promise<ThinkLevel | undefined>;
|
||||||
provider: string;
|
provider: string;
|
||||||
@@ -226,6 +232,7 @@ export async function handleCommands(params: {
|
|||||||
defaultGroupActivation,
|
defaultGroupActivation,
|
||||||
resolvedThinkLevel,
|
resolvedThinkLevel,
|
||||||
resolvedVerboseLevel,
|
resolvedVerboseLevel,
|
||||||
|
resolvedReasoningLevel,
|
||||||
resolvedElevatedLevel,
|
resolvedElevatedLevel,
|
||||||
resolveDefaultThinkingLevel,
|
resolveDefaultThinkingLevel,
|
||||||
provider,
|
provider,
|
||||||
@@ -405,6 +412,7 @@ export async function handleCommands(params: {
|
|||||||
resolvedThink:
|
resolvedThink:
|
||||||
resolvedThinkLevel ?? (await resolveDefaultThinkingLevel()),
|
resolvedThinkLevel ?? (await resolveDefaultThinkingLevel()),
|
||||||
resolvedVerbose: resolvedVerboseLevel,
|
resolvedVerbose: resolvedVerboseLevel,
|
||||||
|
resolvedReasoning: resolvedReasoningLevel,
|
||||||
resolvedElevated: resolvedElevatedLevel,
|
resolvedElevated: resolvedElevatedLevel,
|
||||||
modelAuth: resolveModelAuthLabel(provider, cfg),
|
modelAuth: resolveModelAuthLabel(provider, cfg),
|
||||||
webLinked,
|
webLinked,
|
||||||
|
|||||||
@@ -32,9 +32,11 @@ import type { ReplyPayload } from "../types.js";
|
|||||||
import {
|
import {
|
||||||
type ElevatedLevel,
|
type ElevatedLevel,
|
||||||
extractElevatedDirective,
|
extractElevatedDirective,
|
||||||
|
extractReasoningDirective,
|
||||||
extractStatusDirective,
|
extractStatusDirective,
|
||||||
extractThinkDirective,
|
extractThinkDirective,
|
||||||
extractVerboseDirective,
|
extractVerboseDirective,
|
||||||
|
type ReasoningLevel,
|
||||||
type ThinkLevel,
|
type ThinkLevel,
|
||||||
type VerboseLevel,
|
type VerboseLevel,
|
||||||
} from "./directives.js";
|
} from "./directives.js";
|
||||||
@@ -155,6 +157,9 @@ export type InlineDirectives = {
|
|||||||
hasVerboseDirective: boolean;
|
hasVerboseDirective: boolean;
|
||||||
verboseLevel?: VerboseLevel;
|
verboseLevel?: VerboseLevel;
|
||||||
rawVerboseLevel?: string;
|
rawVerboseLevel?: string;
|
||||||
|
hasReasoningDirective: boolean;
|
||||||
|
reasoningLevel?: ReasoningLevel;
|
||||||
|
rawReasoningLevel?: string;
|
||||||
hasElevatedDirective: boolean;
|
hasElevatedDirective: boolean;
|
||||||
elevatedLevel?: ElevatedLevel;
|
elevatedLevel?: ElevatedLevel;
|
||||||
rawElevatedLevel?: string;
|
rawElevatedLevel?: string;
|
||||||
@@ -188,12 +193,18 @@ export function parseInlineDirectives(body: string): InlineDirectives {
|
|||||||
rawLevel: rawVerboseLevel,
|
rawLevel: rawVerboseLevel,
|
||||||
hasDirective: hasVerboseDirective,
|
hasDirective: hasVerboseDirective,
|
||||||
} = extractVerboseDirective(thinkCleaned);
|
} = extractVerboseDirective(thinkCleaned);
|
||||||
|
const {
|
||||||
|
cleaned: reasoningCleaned,
|
||||||
|
reasoningLevel,
|
||||||
|
rawLevel: rawReasoningLevel,
|
||||||
|
hasDirective: hasReasoningDirective,
|
||||||
|
} = extractReasoningDirective(verboseCleaned);
|
||||||
const {
|
const {
|
||||||
cleaned: elevatedCleaned,
|
cleaned: elevatedCleaned,
|
||||||
elevatedLevel,
|
elevatedLevel,
|
||||||
rawLevel: rawElevatedLevel,
|
rawLevel: rawElevatedLevel,
|
||||||
hasDirective: hasElevatedDirective,
|
hasDirective: hasElevatedDirective,
|
||||||
} = extractElevatedDirective(verboseCleaned);
|
} = extractElevatedDirective(reasoningCleaned);
|
||||||
const { cleaned: statusCleaned, hasDirective: hasStatusDirective } =
|
const { cleaned: statusCleaned, hasDirective: hasStatusDirective } =
|
||||||
extractStatusDirective(elevatedCleaned);
|
extractStatusDirective(elevatedCleaned);
|
||||||
const {
|
const {
|
||||||
@@ -225,6 +236,9 @@ export function parseInlineDirectives(body: string): InlineDirectives {
|
|||||||
hasVerboseDirective,
|
hasVerboseDirective,
|
||||||
verboseLevel,
|
verboseLevel,
|
||||||
rawVerboseLevel,
|
rawVerboseLevel,
|
||||||
|
hasReasoningDirective,
|
||||||
|
reasoningLevel,
|
||||||
|
rawReasoningLevel,
|
||||||
hasElevatedDirective,
|
hasElevatedDirective,
|
||||||
elevatedLevel,
|
elevatedLevel,
|
||||||
rawElevatedLevel,
|
rawElevatedLevel,
|
||||||
@@ -257,6 +271,7 @@ export function isDirectiveOnly(params: {
|
|||||||
if (
|
if (
|
||||||
!directives.hasThinkDirective &&
|
!directives.hasThinkDirective &&
|
||||||
!directives.hasVerboseDirective &&
|
!directives.hasVerboseDirective &&
|
||||||
|
!directives.hasReasoningDirective &&
|
||||||
!directives.hasElevatedDirective &&
|
!directives.hasElevatedDirective &&
|
||||||
!directives.hasModelDirective &&
|
!directives.hasModelDirective &&
|
||||||
!directives.hasQueueDirective
|
!directives.hasQueueDirective
|
||||||
@@ -367,6 +382,11 @@ export async function handleDirectiveOnly(params: {
|
|||||||
text: `Unrecognized verbose level "${directives.rawVerboseLevel ?? ""}". Valid levels: off, on.`,
|
text: `Unrecognized verbose level "${directives.rawVerboseLevel ?? ""}". Valid levels: off, on.`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (directives.hasReasoningDirective && !directives.reasoningLevel) {
|
||||||
|
return {
|
||||||
|
text: `Unrecognized reasoning level "${directives.rawReasoningLevel ?? ""}". Valid levels: on, off.`,
|
||||||
|
};
|
||||||
|
}
|
||||||
if (directives.hasElevatedDirective && !directives.elevatedLevel) {
|
if (directives.hasElevatedDirective && !directives.elevatedLevel) {
|
||||||
return {
|
return {
|
||||||
text: `Unrecognized elevated level "${directives.rawElevatedLevel ?? ""}". Valid levels: off, on.`,
|
text: `Unrecognized elevated level "${directives.rawElevatedLevel ?? ""}". Valid levels: off, on.`,
|
||||||
@@ -476,6 +496,11 @@ export async function handleDirectiveOnly(params: {
|
|||||||
if (directives.verboseLevel === "off") delete sessionEntry.verboseLevel;
|
if (directives.verboseLevel === "off") delete sessionEntry.verboseLevel;
|
||||||
else sessionEntry.verboseLevel = directives.verboseLevel;
|
else sessionEntry.verboseLevel = directives.verboseLevel;
|
||||||
}
|
}
|
||||||
|
if (directives.hasReasoningDirective && directives.reasoningLevel) {
|
||||||
|
if (directives.reasoningLevel === "off")
|
||||||
|
delete sessionEntry.reasoningLevel;
|
||||||
|
else sessionEntry.reasoningLevel = directives.reasoningLevel;
|
||||||
|
}
|
||||||
if (directives.hasElevatedDirective && directives.elevatedLevel) {
|
if (directives.hasElevatedDirective && directives.elevatedLevel) {
|
||||||
if (directives.elevatedLevel === "off") delete sessionEntry.elevatedLevel;
|
if (directives.elevatedLevel === "off") delete sessionEntry.elevatedLevel;
|
||||||
else sessionEntry.elevatedLevel = directives.elevatedLevel;
|
else sessionEntry.elevatedLevel = directives.elevatedLevel;
|
||||||
@@ -533,6 +558,13 @@ export async function handleDirectiveOnly(params: {
|
|||||||
: `${SYSTEM_MARK} Verbose logging enabled.`,
|
: `${SYSTEM_MARK} Verbose logging enabled.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (directives.hasReasoningDirective && directives.reasoningLevel) {
|
||||||
|
parts.push(
|
||||||
|
directives.reasoningLevel === "off"
|
||||||
|
? `${SYSTEM_MARK} Reasoning visibility disabled.`
|
||||||
|
: `${SYSTEM_MARK} Reasoning visibility enabled.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (directives.hasElevatedDirective && directives.elevatedLevel) {
|
if (directives.hasElevatedDirective && directives.elevatedLevel) {
|
||||||
parts.push(
|
parts.push(
|
||||||
directives.elevatedLevel === "off"
|
directives.elevatedLevel === "off"
|
||||||
@@ -634,6 +666,14 @@ export async function persistInlineDirectives(params: {
|
|||||||
}
|
}
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
if (directives.hasReasoningDirective && directives.reasoningLevel) {
|
||||||
|
if (directives.reasoningLevel === "off") {
|
||||||
|
delete sessionEntry.reasoningLevel;
|
||||||
|
} else {
|
||||||
|
sessionEntry.reasoningLevel = directives.reasoningLevel;
|
||||||
|
}
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
directives.hasElevatedDirective &&
|
directives.hasElevatedDirective &&
|
||||||
directives.elevatedLevel &&
|
directives.elevatedLevel &&
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import type { ReasoningLevel } from "../thinking.js";
|
||||||
import {
|
import {
|
||||||
type ElevatedLevel,
|
type ElevatedLevel,
|
||||||
normalizeElevatedLevel,
|
normalizeElevatedLevel,
|
||||||
|
normalizeReasoningLevel,
|
||||||
normalizeThinkLevel,
|
normalizeThinkLevel,
|
||||||
normalizeVerboseLevel,
|
normalizeVerboseLevel,
|
||||||
type ThinkLevel,
|
type ThinkLevel,
|
||||||
@@ -74,6 +76,28 @@ export function extractElevatedDirective(body?: string): {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function extractReasoningDirective(body?: string): {
|
||||||
|
cleaned: string;
|
||||||
|
reasoningLevel?: ReasoningLevel;
|
||||||
|
rawLevel?: string;
|
||||||
|
hasDirective: boolean;
|
||||||
|
} {
|
||||||
|
if (!body) return { cleaned: "", hasDirective: false };
|
||||||
|
const match = body.match(
|
||||||
|
/(?:^|\s)\/(?:reasoning|reason)(?=$|\s|:)\s*:?\s*([a-zA-Z-]+)\b/i,
|
||||||
|
);
|
||||||
|
const reasoningLevel = normalizeReasoningLevel(match?.[1]);
|
||||||
|
const cleaned = match
|
||||||
|
? body.replace(match[0], "").replace(/\s+/g, " ").trim()
|
||||||
|
: body.trim();
|
||||||
|
return {
|
||||||
|
cleaned,
|
||||||
|
reasoningLevel,
|
||||||
|
rawLevel: match?.[1],
|
||||||
|
hasDirective: !!match,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function extractStatusDirective(body?: string): {
|
export function extractStatusDirective(body?: string): {
|
||||||
cleaned: string;
|
cleaned: string;
|
||||||
hasDirective: boolean;
|
hasDirective: boolean;
|
||||||
@@ -89,4 +113,4 @@ export function extractStatusDirective(body?: string): {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { ElevatedLevel, ThinkLevel, VerboseLevel };
|
export type { ElevatedLevel, ReasoningLevel, ThinkLevel, VerboseLevel };
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ export function createFollowupRunner(params: {
|
|||||||
authProfileId: queued.run.authProfileId,
|
authProfileId: queued.run.authProfileId,
|
||||||
thinkLevel: queued.run.thinkLevel,
|
thinkLevel: queued.run.thinkLevel,
|
||||||
verboseLevel: queued.run.verboseLevel,
|
verboseLevel: queued.run.verboseLevel,
|
||||||
|
reasoningLevel: queued.run.reasoningLevel,
|
||||||
bashElevated: queued.run.bashElevated,
|
bashElevated: queued.run.bashElevated,
|
||||||
timeoutMs: queued.run.timeoutMs,
|
timeoutMs: queued.run.timeoutMs,
|
||||||
runId,
|
runId,
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import type { ClawdbotConfig } from "../../config/config.js";
|
|||||||
import type { SessionEntry } from "../../config/sessions.js";
|
import type { SessionEntry } from "../../config/sessions.js";
|
||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
import type { OriginatingChannelType } from "../templating.js";
|
import type { OriginatingChannelType } from "../templating.js";
|
||||||
import type { ElevatedLevel, ThinkLevel, VerboseLevel } from "./directives.js";
|
import type {
|
||||||
|
ElevatedLevel,
|
||||||
|
ReasoningLevel,
|
||||||
|
ThinkLevel,
|
||||||
|
VerboseLevel,
|
||||||
|
} from "./directives.js";
|
||||||
import { isRoutableChannel } from "./route-reply.js";
|
import { isRoutableChannel } from "./route-reply.js";
|
||||||
export type QueueMode =
|
export type QueueMode =
|
||||||
| "steer"
|
| "steer"
|
||||||
@@ -54,6 +59,7 @@ export type FollowupRun = {
|
|||||||
authProfileId?: string;
|
authProfileId?: string;
|
||||||
thinkLevel?: ThinkLevel;
|
thinkLevel?: ThinkLevel;
|
||||||
verboseLevel?: VerboseLevel;
|
verboseLevel?: VerboseLevel;
|
||||||
|
reasoningLevel?: ReasoningLevel;
|
||||||
elevatedLevel?: ElevatedLevel;
|
elevatedLevel?: ElevatedLevel;
|
||||||
bashElevated?: {
|
bashElevated?: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ import {
|
|||||||
type SessionScope,
|
type SessionScope,
|
||||||
} from "../config/sessions.js";
|
} from "../config/sessions.js";
|
||||||
import { shortenHomePath } from "../utils.js";
|
import { shortenHomePath } from "../utils.js";
|
||||||
import type { ElevatedLevel, ThinkLevel, VerboseLevel } from "./thinking.js";
|
import type {
|
||||||
|
ElevatedLevel,
|
||||||
|
ReasoningLevel,
|
||||||
|
ThinkLevel,
|
||||||
|
VerboseLevel,
|
||||||
|
} from "./thinking.js";
|
||||||
|
|
||||||
type AgentConfig = NonNullable<ClawdbotConfig["agent"]>;
|
type AgentConfig = NonNullable<ClawdbotConfig["agent"]>;
|
||||||
|
|
||||||
@@ -34,6 +39,7 @@ type StatusArgs = {
|
|||||||
groupActivation?: "mention" | "always";
|
groupActivation?: "mention" | "always";
|
||||||
resolvedThink?: ThinkLevel;
|
resolvedThink?: ThinkLevel;
|
||||||
resolvedVerbose?: VerboseLevel;
|
resolvedVerbose?: VerboseLevel;
|
||||||
|
resolvedReasoning?: ReasoningLevel;
|
||||||
resolvedElevated?: ElevatedLevel;
|
resolvedElevated?: ElevatedLevel;
|
||||||
modelAuth?: string;
|
modelAuth?: string;
|
||||||
now?: number;
|
now?: number;
|
||||||
@@ -173,6 +179,7 @@ export function buildStatusMessage(args: StatusArgs): string {
|
|||||||
const thinkLevel = args.resolvedThink ?? args.agent?.thinkingDefault ?? "off";
|
const thinkLevel = args.resolvedThink ?? args.agent?.thinkingDefault ?? "off";
|
||||||
const verboseLevel =
|
const verboseLevel =
|
||||||
args.resolvedVerbose ?? args.agent?.verboseDefault ?? "off";
|
args.resolvedVerbose ?? args.agent?.verboseDefault ?? "off";
|
||||||
|
const reasoningLevel = args.resolvedReasoning ?? "off";
|
||||||
const elevatedLevel =
|
const elevatedLevel =
|
||||||
args.resolvedElevated ??
|
args.resolvedElevated ??
|
||||||
args.sessionEntry?.elevatedLevel ??
|
args.sessionEntry?.elevatedLevel ??
|
||||||
@@ -241,8 +248,8 @@ export function buildStatusMessage(args: StatusArgs): string {
|
|||||||
)}${entry?.abortedLastRun ? " • last run aborted" : ""}`;
|
)}${entry?.abortedLastRun ? " • last run aborted" : ""}`;
|
||||||
|
|
||||||
const optionsLine = runtime.sandboxed
|
const optionsLine = runtime.sandboxed
|
||||||
? `Options: thinking=${thinkLevel} | verbose=${verboseLevel} | elevated=${elevatedLevel}`
|
? `Options: thinking=${thinkLevel} | verbose=${verboseLevel} | reasoning=${reasoningLevel} | elevated=${elevatedLevel}`
|
||||||
: `Options: thinking=${thinkLevel} | verbose=${verboseLevel}`;
|
: `Options: thinking=${thinkLevel} | verbose=${verboseLevel} | reasoning=${reasoningLevel}`;
|
||||||
|
|
||||||
const modelLabel = model ? `${provider}/${model}` : "unknown";
|
const modelLabel = model ? `${provider}/${model}` : "unknown";
|
||||||
|
|
||||||
@@ -273,6 +280,6 @@ export function buildHelpMessage(): string {
|
|||||||
return [
|
return [
|
||||||
"ℹ️ Help",
|
"ℹ️ Help",
|
||||||
"Shortcuts: /new reset | /compact [instructions] | /restart relink",
|
"Shortcuts: /new reset | /compact [instructions] | /restart relink",
|
||||||
"Options: /think <level> | /verbose on|off | /elevated on|off | /model <id>",
|
"Options: /think <level> | /verbose on|off | /reasoning on|off | /elevated on|off | /model <id>",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { normalizeThinkLevel } from "./thinking.js";
|
import { normalizeReasoningLevel, normalizeThinkLevel } from "./thinking.js";
|
||||||
|
|
||||||
describe("normalizeThinkLevel", () => {
|
describe("normalizeThinkLevel", () => {
|
||||||
it("accepts mid as medium", () => {
|
it("accepts mid as medium", () => {
|
||||||
expect(normalizeThinkLevel("mid")).toBe("medium");
|
expect(normalizeThinkLevel("mid")).toBe("medium");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("normalizeReasoningLevel", () => {
|
||||||
|
it("accepts on/off", () => {
|
||||||
|
expect(normalizeReasoningLevel("on")).toBe("on");
|
||||||
|
expect(normalizeReasoningLevel("off")).toBe("off");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts show/hide", () => {
|
||||||
|
expect(normalizeReasoningLevel("show")).toBe("on");
|
||||||
|
expect(normalizeReasoningLevel("hide")).toBe("off");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export type ThinkLevel = "off" | "minimal" | "low" | "medium" | "high";
|
export type ThinkLevel = "off" | "minimal" | "low" | "medium" | "high";
|
||||||
export type VerboseLevel = "off" | "on";
|
export type VerboseLevel = "off" | "on";
|
||||||
export type ElevatedLevel = "off" | "on";
|
export type ElevatedLevel = "off" | "on";
|
||||||
|
export type ReasoningLevel = "off" | "on";
|
||||||
|
|
||||||
// Normalize user-provided thinking level strings to the canonical enum.
|
// Normalize user-provided thinking level strings to the canonical enum.
|
||||||
export function normalizeThinkLevel(
|
export function normalizeThinkLevel(
|
||||||
@@ -55,3 +56,31 @@ export function normalizeElevatedLevel(
|
|||||||
if (["on", "true", "yes", "1"].includes(key)) return "on";
|
if (["on", "true", "yes", "1"].includes(key)) return "on";
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize reasoning visibility flags used to toggle reasoning exposure.
|
||||||
|
export function normalizeReasoningLevel(
|
||||||
|
raw?: string | null,
|
||||||
|
): ReasoningLevel | undefined {
|
||||||
|
if (!raw) return undefined;
|
||||||
|
const key = raw.toLowerCase();
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
"off",
|
||||||
|
"false",
|
||||||
|
"no",
|
||||||
|
"0",
|
||||||
|
"hide",
|
||||||
|
"hidden",
|
||||||
|
"disable",
|
||||||
|
"disabled",
|
||||||
|
].includes(key)
|
||||||
|
)
|
||||||
|
return "off";
|
||||||
|
if (
|
||||||
|
["on", "true", "yes", "1", "show", "visible", "enable", "enabled"].includes(
|
||||||
|
key,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return "on";
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type SessionRow = {
|
|||||||
abortedLastRun?: boolean;
|
abortedLastRun?: boolean;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
groupActivation?: string;
|
groupActivation?: string;
|
||||||
inputTokens?: number;
|
inputTokens?: number;
|
||||||
outputTokens?: number;
|
outputTokens?: number;
|
||||||
@@ -99,6 +100,7 @@ const formatFlagsCell = (row: SessionRow, rich: boolean) => {
|
|||||||
const flags = [
|
const flags = [
|
||||||
row.thinkingLevel ? `think:${row.thinkingLevel}` : null,
|
row.thinkingLevel ? `think:${row.thinkingLevel}` : null,
|
||||||
row.verboseLevel ? `verbose:${row.verboseLevel}` : null,
|
row.verboseLevel ? `verbose:${row.verboseLevel}` : null,
|
||||||
|
row.reasoningLevel ? `reasoning:${row.reasoningLevel}` : null,
|
||||||
row.groupActivation ? `activation:${row.groupActivation}` : null,
|
row.groupActivation ? `activation:${row.groupActivation}` : null,
|
||||||
row.systemSent ? "system" : null,
|
row.systemSent ? "system" : null,
|
||||||
row.abortedLastRun ? "aborted" : null,
|
row.abortedLastRun ? "aborted" : null,
|
||||||
@@ -147,6 +149,7 @@ function toRows(store: Record<string, SessionEntry>): SessionRow[] {
|
|||||||
abortedLastRun: entry?.abortedLastRun,
|
abortedLastRun: entry?.abortedLastRun,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
groupActivation: entry?.groupActivation,
|
groupActivation: entry?.groupActivation,
|
||||||
inputTokens: entry?.inputTokens,
|
inputTokens: entry?.inputTokens,
|
||||||
outputTokens: entry?.outputTokens,
|
outputTokens: entry?.outputTokens,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export type SessionStatus = {
|
|||||||
age: number | null;
|
age: number | null;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
elevatedLevel?: string;
|
elevatedLevel?: string;
|
||||||
systemSent?: boolean;
|
systemSent?: boolean;
|
||||||
abortedLastRun?: boolean;
|
abortedLastRun?: boolean;
|
||||||
@@ -111,6 +112,7 @@ export async function getStatusSummary(): Promise<StatusSummary> {
|
|||||||
age,
|
age,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
elevatedLevel: entry?.elevatedLevel,
|
elevatedLevel: entry?.elevatedLevel,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
abortedLastRun: entry?.abortedLastRun,
|
abortedLastRun: entry?.abortedLastRun,
|
||||||
@@ -198,6 +200,9 @@ const buildFlags = (entry: SessionEntry): string[] => {
|
|||||||
const verbose = entry?.verboseLevel;
|
const verbose = entry?.verboseLevel;
|
||||||
if (typeof verbose === "string" && verbose.length > 0)
|
if (typeof verbose === "string" && verbose.length > 0)
|
||||||
flags.push(`verbose:${verbose}`);
|
flags.push(`verbose:${verbose}`);
|
||||||
|
const reasoning = entry?.reasoningLevel;
|
||||||
|
if (typeof reasoning === "string" && reasoning.length > 0)
|
||||||
|
flags.push(`reasoning:${reasoning}`);
|
||||||
const elevated = entry?.elevatedLevel;
|
const elevated = entry?.elevatedLevel;
|
||||||
if (typeof elevated === "string" && elevated.length > 0)
|
if (typeof elevated === "string" && elevated.length > 0)
|
||||||
flags.push(`elevated:${elevated}`);
|
flags.push(`elevated:${elevated}`);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export type SessionEntry = {
|
|||||||
chatType?: SessionChatType;
|
chatType?: SessionChatType;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
elevatedLevel?: string;
|
elevatedLevel?: string;
|
||||||
providerOverride?: string;
|
providerOverride?: string;
|
||||||
modelOverride?: string;
|
modelOverride?: string;
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ export const SessionsPatchParamsSchema = Type.Object(
|
|||||||
key: NonEmptyString,
|
key: NonEmptyString,
|
||||||
thinkingLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
thinkingLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
verboseLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
verboseLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
|
reasoningLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
elevatedLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
elevatedLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
model: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
model: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
spawnedBy: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
spawnedBy: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { resolveAgentTimeoutMs } from "../agents/timeout.js";
|
|||||||
import { normalizeGroupActivation } from "../auto-reply/group-activation.js";
|
import { normalizeGroupActivation } from "../auto-reply/group-activation.js";
|
||||||
import {
|
import {
|
||||||
normalizeElevatedLevel,
|
normalizeElevatedLevel,
|
||||||
|
normalizeReasoningLevel,
|
||||||
normalizeThinkLevel,
|
normalizeThinkLevel,
|
||||||
normalizeVerboseLevel,
|
normalizeVerboseLevel,
|
||||||
} from "../auto-reply/thinking.js";
|
} from "../auto-reply/thinking.js";
|
||||||
@@ -434,6 +435,26 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("reasoningLevel" in p) {
|
||||||
|
const raw = p.reasoningLevel;
|
||||||
|
if (raw === null) {
|
||||||
|
delete next.reasoningLevel;
|
||||||
|
} else if (raw !== undefined) {
|
||||||
|
const normalized = normalizeReasoningLevel(String(raw));
|
||||||
|
if (!normalized) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
error: {
|
||||||
|
code: ErrorCodes.INVALID_REQUEST,
|
||||||
|
message: `invalid reasoningLevel: ${String(raw)}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (normalized === "off") delete next.reasoningLevel;
|
||||||
|
else next.reasoningLevel = normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ("elevatedLevel" in p) {
|
if ("elevatedLevel" in p) {
|
||||||
const raw = p.elevatedLevel;
|
const raw = p.elevatedLevel;
|
||||||
if (raw === null) {
|
if (raw === null) {
|
||||||
@@ -602,6 +623,7 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) {
|
|||||||
abortedLastRun: false,
|
abortedLastRun: false,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
model: entry?.model,
|
model: entry?.model,
|
||||||
contextTokens: entry?.contextTokens,
|
contextTokens: entry?.contextTokens,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
@@ -986,6 +1008,7 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) {
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
lastProvider: entry?.lastProvider,
|
lastProvider: entry?.lastProvider,
|
||||||
lastTo: entry?.lastTo,
|
lastTo: entry?.lastTo,
|
||||||
@@ -1125,6 +1148,7 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) {
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
lastProvider: entry?.lastProvider,
|
lastProvider: entry?.lastProvider,
|
||||||
@@ -1207,6 +1231,7 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) {
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
lastProvider: entry?.lastProvider,
|
lastProvider: entry?.lastProvider,
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ export const agentHandlers: GatewayRequestHandlers = {
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
skillsSnapshot: entry?.skillsSnapshot,
|
skillsSnapshot: entry?.skillsSnapshot,
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ export const chatHandlers: GatewayRequestHandlers = {
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
lastProvider: entry?.lastProvider,
|
lastProvider: entry?.lastProvider,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from "../../agents/pi-embedded.js";
|
} from "../../agents/pi-embedded.js";
|
||||||
import { normalizeGroupActivation } from "../../auto-reply/group-activation.js";
|
import { normalizeGroupActivation } from "../../auto-reply/group-activation.js";
|
||||||
import {
|
import {
|
||||||
|
normalizeReasoningLevel,
|
||||||
normalizeThinkLevel,
|
normalizeThinkLevel,
|
||||||
normalizeVerboseLevel,
|
normalizeVerboseLevel,
|
||||||
} from "../../auto-reply/thinking.js";
|
} from "../../auto-reply/thinking.js";
|
||||||
@@ -211,6 +212,28 @@ export const sessionsHandlers: GatewayRequestHandlers = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("reasoningLevel" in p) {
|
||||||
|
const raw = p.reasoningLevel;
|
||||||
|
if (raw === null) {
|
||||||
|
delete next.reasoningLevel;
|
||||||
|
} else if (raw !== undefined) {
|
||||||
|
const normalized = normalizeReasoningLevel(String(raw));
|
||||||
|
if (!normalized) {
|
||||||
|
respond(
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
errorShape(
|
||||||
|
ErrorCodes.INVALID_REQUEST,
|
||||||
|
'invalid reasoningLevel (use "on"|"off")',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (normalized === "off") delete next.reasoningLevel;
|
||||||
|
else next.reasoningLevel = normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ("model" in p) {
|
if ("model" in p) {
|
||||||
const raw = p.model;
|
const raw = p.model;
|
||||||
if (raw === null) {
|
if (raw === null) {
|
||||||
@@ -370,6 +393,7 @@ export const sessionsHandlers: GatewayRequestHandlers = {
|
|||||||
abortedLastRun: false,
|
abortedLastRun: false,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
model: entry?.model,
|
model: entry?.model,
|
||||||
contextTokens: entry?.contextTokens,
|
contextTokens: entry?.contextTokens,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export type GatewaySessionRow = {
|
|||||||
abortedLastRun?: boolean;
|
abortedLastRun?: boolean;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
elevatedLevel?: string;
|
elevatedLevel?: string;
|
||||||
sendPolicy?: "allow" | "deny";
|
sendPolicy?: "allow" | "deny";
|
||||||
inputTokens?: number;
|
inputTokens?: number;
|
||||||
@@ -441,6 +442,7 @@ export function listSessionsFromStore(params: {
|
|||||||
abortedLastRun: entry?.abortedLastRun,
|
abortedLastRun: entry?.abortedLastRun,
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
elevatedLevel: entry?.elevatedLevel,
|
elevatedLevel: entry?.elevatedLevel,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
inputTokens: entry?.inputTokens,
|
inputTokens: entry?.inputTokens,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { SlashCommand } from "@mariozechner/pi-tui";
|
|||||||
|
|
||||||
const THINK_LEVELS = ["off", "minimal", "low", "medium", "high"];
|
const THINK_LEVELS = ["off", "minimal", "low", "medium", "high"];
|
||||||
const VERBOSE_LEVELS = ["on", "off"];
|
const VERBOSE_LEVELS = ["on", "off"];
|
||||||
|
const REASONING_LEVELS = ["on", "off"];
|
||||||
const ELEVATED_LEVELS = ["on", "off"];
|
const ELEVATED_LEVELS = ["on", "off"];
|
||||||
const ACTIVATION_LEVELS = ["mention", "always"];
|
const ACTIVATION_LEVELS = ["mention", "always"];
|
||||||
const TOGGLE = ["on", "off"];
|
const TOGGLE = ["on", "off"];
|
||||||
@@ -53,6 +54,14 @@ export function getSlashCommands(): SlashCommand[] {
|
|||||||
(value) => ({ value, label: value }),
|
(value) => ({ value, label: value }),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "reasoning",
|
||||||
|
description: "Set reasoning on/off",
|
||||||
|
getArgumentCompletions: (prefix) =>
|
||||||
|
REASONING_LEVELS.filter((v) => v.startsWith(prefix.toLowerCase())).map(
|
||||||
|
(value) => ({ value, label: value }),
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "elevated",
|
name: "elevated",
|
||||||
description: "Set elevated on/off",
|
description: "Set elevated on/off",
|
||||||
@@ -103,6 +112,7 @@ export function helpText(): string {
|
|||||||
"/model <provider/model> (or /models)",
|
"/model <provider/model> (or /models)",
|
||||||
"/think <off|minimal|low|medium|high>",
|
"/think <off|minimal|low|medium|high>",
|
||||||
"/verbose <on|off>",
|
"/verbose <on|off>",
|
||||||
|
"/reasoning <on|off>",
|
||||||
"/elevated <on|off>",
|
"/elevated <on|off>",
|
||||||
"/elev <on|off>",
|
"/elev <on|off>",
|
||||||
"/activation <mention|always>",
|
"/activation <mention|always>",
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export type GatewaySessionList = {
|
|||||||
updatedAt?: number | null;
|
updatedAt?: number | null;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
sendPolicy?: string;
|
sendPolicy?: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
contextTokens?: number | null;
|
contextTokens?: number | null;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type AgentEvent = {
|
|||||||
type SessionInfo = {
|
type SessionInfo = {
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
contextTokens?: number | null;
|
contextTokens?: number | null;
|
||||||
totalTokens?: number | null;
|
totalTokens?: number | null;
|
||||||
@@ -167,10 +168,11 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
);
|
);
|
||||||
const think = sessionInfo.thinkingLevel ?? "off";
|
const think = sessionInfo.thinkingLevel ?? "off";
|
||||||
const verbose = sessionInfo.verboseLevel ?? "off";
|
const verbose = sessionInfo.verboseLevel ?? "off";
|
||||||
|
const reasoning = sessionInfo.reasoningLevel ?? "off";
|
||||||
const deliver = deliverDefault ? "on" : "off";
|
const deliver = deliverDefault ? "on" : "off";
|
||||||
footer.setText(
|
footer.setText(
|
||||||
theme.dim(
|
theme.dim(
|
||||||
`${connection} | session ${sessionLabel} | model ${modelLabel} | think ${think} | verbose ${verbose} | ${tokens} | deliver ${deliver}`,
|
`${connection} | session ${sessionLabel} | model ${modelLabel} | think ${think} | verbose ${verbose} | reasoning ${reasoning} | ${tokens} | deliver ${deliver}`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -198,6 +200,7 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
sessionInfo = {
|
sessionInfo = {
|
||||||
thinkingLevel: entry?.thinkingLevel,
|
thinkingLevel: entry?.thinkingLevel,
|
||||||
verboseLevel: entry?.verboseLevel,
|
verboseLevel: entry?.verboseLevel,
|
||||||
|
reasoningLevel: entry?.reasoningLevel,
|
||||||
model: entry?.model ?? result.defaults?.model ?? undefined,
|
model: entry?.model ?? result.defaults?.model ?? undefined,
|
||||||
contextTokens: entry?.contextTokens ?? result.defaults?.contextTokens,
|
contextTokens: entry?.contextTokens ?? result.defaults?.contextTokens,
|
||||||
totalTokens: entry?.totalTokens ?? null,
|
totalTokens: entry?.totalTokens ?? null,
|
||||||
@@ -586,6 +589,22 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
chatLog.addSystem(`verbose failed: ${String(err)}`);
|
chatLog.addSystem(`verbose failed: ${String(err)}`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "reasoning":
|
||||||
|
if (!args) {
|
||||||
|
chatLog.addSystem("usage: /reasoning <on|off>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await client.patchSession({
|
||||||
|
key: currentSessionKey,
|
||||||
|
reasoningLevel: args,
|
||||||
|
});
|
||||||
|
chatLog.addSystem(`reasoning set to ${args}`);
|
||||||
|
await refreshSessionInfo();
|
||||||
|
} catch (err) {
|
||||||
|
chatLog.addSystem(`reasoning failed: ${String(err)}`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "elevated":
|
case "elevated":
|
||||||
if (!args) {
|
if (!args) {
|
||||||
chatLog.addSystem("usage: /elevated <on|off>");
|
chatLog.addSystem("usage: /elevated <on|off>");
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ export type GatewaySessionRow = {
|
|||||||
abortedLastRun?: boolean;
|
abortedLastRun?: boolean;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
elevatedLevel?: string;
|
elevatedLevel?: string;
|
||||||
inputTokens?: number;
|
inputTokens?: number;
|
||||||
outputTokens?: number;
|
outputTokens?: number;
|
||||||
@@ -251,6 +252,7 @@ export type SessionsPatchResult = {
|
|||||||
updatedAt?: number;
|
updatedAt?: number;
|
||||||
thinkingLevel?: string;
|
thinkingLevel?: string;
|
||||||
verboseLevel?: string;
|
verboseLevel?: string;
|
||||||
|
reasoningLevel?: string;
|
||||||
elevatedLevel?: string;
|
elevatedLevel?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user