feat: add thinking_max_chars option to background_output tool
- Add thinking_max_chars?: number to BackgroundOutputOptions type - Add thinking_max_chars argument to background_output tool schema - Add formatFullSession option for controlling output format - Add 2 tests for thinking_max_chars functionality
This commit is contained in:
265
src/tools/background-task/tools.test.ts
Normal file
265
src/tools/background-task/tools.test.ts
Normal file
@@ -0,0 +1,265 @@
|
||||
import { createBackgroundOutput } from "./tools"
|
||||
import type { BackgroundTask } from "../../features/background-agent"
|
||||
import type { ToolContext } from "@opencode-ai/plugin/tool"
|
||||
import type { BackgroundOutputManager, BackgroundOutputClient } from "./tools"
|
||||
|
||||
const projectDir = "/Users/yeongyu/local-workspaces/oh-my-opencode"
|
||||
|
||||
const mockContext: ToolContext = {
|
||||
sessionID: "test-session",
|
||||
messageID: "test-message",
|
||||
agent: "test-agent",
|
||||
directory: projectDir,
|
||||
worktree: projectDir,
|
||||
abort: new AbortController().signal,
|
||||
metadata: () => {},
|
||||
ask: async () => {},
|
||||
}
|
||||
|
||||
function createMockManager(task: BackgroundTask): BackgroundOutputManager {
|
||||
return {
|
||||
getTask: (id: string) => (id === task.id ? task : undefined),
|
||||
}
|
||||
}
|
||||
|
||||
function createMockClient(messagesBySession: Record<string, BackgroundOutputMessage[]>): BackgroundOutputClient {
|
||||
const emptyMessages: BackgroundOutputMessage[] = []
|
||||
const client = {
|
||||
session: {
|
||||
messages: async ({ path }: { path: { id: string } }) => ({
|
||||
data: messagesBySession[path.id] ?? emptyMessages,
|
||||
}),
|
||||
},
|
||||
} satisfies BackgroundOutputClient
|
||||
return client
|
||||
}
|
||||
|
||||
function createTask(overrides: Partial<BackgroundTask> = {}): BackgroundTask {
|
||||
return {
|
||||
id: "task-1",
|
||||
sessionID: "ses-1",
|
||||
parentSessionID: "main-1",
|
||||
parentMessageID: "msg-1",
|
||||
description: "background task",
|
||||
prompt: "do work",
|
||||
agent: "test-agent",
|
||||
status: "running",
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
describe("background_output full_session", () => {
|
||||
test("includes thinking and tool results when enabled", async () => {
|
||||
// #given
|
||||
const task = createTask()
|
||||
const manager = createMockManager(task)
|
||||
const client = createMockClient({
|
||||
"ses-1": [
|
||||
{
|
||||
id: "m1",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:00Z", agent: "test" },
|
||||
parts: [
|
||||
{ type: "text", text: "hello" },
|
||||
{ type: "thinking", thinking: "thinking text" },
|
||||
{ type: "tool_result", content: "tool output" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "m2",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:01Z" },
|
||||
parts: [
|
||||
{ type: "reasoning", text: "reasoning text" },
|
||||
{ type: "text", text: "after" },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({
|
||||
task_id: "task-1",
|
||||
full_session: true,
|
||||
include_thinking: true,
|
||||
include_tool_results: true,
|
||||
}, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output).toContain("thinking text")
|
||||
expect(output).toContain("reasoning text")
|
||||
expect(output).toContain("tool output")
|
||||
})
|
||||
|
||||
test("respects since_message_id exclusive filtering", async () => {
|
||||
// #given
|
||||
const task = createTask()
|
||||
const manager = createMockManager(task)
|
||||
const client = createMockClient({
|
||||
"ses-1": [
|
||||
{
|
||||
id: "m1",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:00Z" },
|
||||
parts: [{ type: "text", text: "hello" }],
|
||||
},
|
||||
{
|
||||
id: "m2",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:01Z" },
|
||||
parts: [{ type: "text", text: "after" }],
|
||||
},
|
||||
],
|
||||
})
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({
|
||||
task_id: "task-1",
|
||||
full_session: true,
|
||||
since_message_id: "m1",
|
||||
}, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output.includes("hello")).toBe(false)
|
||||
expect(output).toContain("after")
|
||||
})
|
||||
|
||||
test("returns error when since_message_id not found", async () => {
|
||||
// #given
|
||||
const task = createTask()
|
||||
const manager = createMockManager(task)
|
||||
const client = createMockClient({
|
||||
"ses-1": [
|
||||
{
|
||||
id: "m1",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:00Z" },
|
||||
parts: [{ type: "text", text: "hello" }],
|
||||
},
|
||||
],
|
||||
})
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({
|
||||
task_id: "task-1",
|
||||
full_session: true,
|
||||
since_message_id: "missing",
|
||||
}, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output).toContain("since_message_id not found")
|
||||
})
|
||||
|
||||
test("caps message_limit at 100", async () => {
|
||||
// #given
|
||||
const task = createTask()
|
||||
const manager = createMockManager(task)
|
||||
const messages = Array.from({ length: 120 }, (_, index) => ({
|
||||
id: `m${index}`,
|
||||
info: {
|
||||
role: "assistant",
|
||||
time: new Date(2026, 0, 1, 0, 0, index).toISOString(),
|
||||
},
|
||||
parts: [{ type: "text", text: `message-${index}` }],
|
||||
}))
|
||||
const client = createMockClient({ "ses-1": messages })
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({
|
||||
task_id: "task-1",
|
||||
full_session: true,
|
||||
message_limit: 200,
|
||||
}, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output).toContain("Returned: 100")
|
||||
expect(output).toContain("Has more: true")
|
||||
})
|
||||
|
||||
test("keeps legacy status output when full_session is false", async () => {
|
||||
// #given
|
||||
const task = createTask({ status: "running" })
|
||||
const manager = createMockManager(task)
|
||||
const client = createMockClient({})
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({ task_id: "task-1" }, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output).toContain("# Task Status")
|
||||
expect(output).toContain("Task ID")
|
||||
})
|
||||
|
||||
test("truncates thinking content to thinking_max_chars", async () => {
|
||||
// #given
|
||||
const longThinking = "x".repeat(500)
|
||||
const task = createTask()
|
||||
const manager = createMockManager(task)
|
||||
const client = createMockClient({
|
||||
"ses-1": [
|
||||
{
|
||||
id: "m1",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:00Z" },
|
||||
parts: [
|
||||
{ type: "thinking", thinking: longThinking },
|
||||
{ type: "text", text: "hello" },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({
|
||||
task_id: "task-1",
|
||||
full_session: true,
|
||||
include_thinking: true,
|
||||
thinking_max_chars: 100,
|
||||
}, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output).toContain("[thinking] " + "x".repeat(100) + "...")
|
||||
expect(output).not.toContain("x".repeat(200))
|
||||
})
|
||||
|
||||
test("uses default 2000 chars when thinking_max_chars not provided", async () => {
|
||||
// #given
|
||||
const longThinking = "y".repeat(2500)
|
||||
const task = createTask()
|
||||
const manager = createMockManager(task)
|
||||
const client = createMockClient({
|
||||
"ses-1": [
|
||||
{
|
||||
id: "m1",
|
||||
info: { role: "assistant", time: "2026-01-01T00:00:00Z" },
|
||||
parts: [
|
||||
{ type: "thinking", thinking: longThinking },
|
||||
{ type: "text", text: "hello" },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
const tool = createBackgroundOutput(manager, client)
|
||||
|
||||
// #when
|
||||
const output = await tool.execute({
|
||||
task_id: "task-1",
|
||||
full_session: true,
|
||||
include_thinking: true,
|
||||
}, mockContext)
|
||||
|
||||
// #then
|
||||
expect(output).toContain("[thinking] " + "y".repeat(2000) + "...")
|
||||
expect(output).not.toContain("y".repeat(2100))
|
||||
})
|
||||
})
|
||||
type BackgroundOutputMessage = {
|
||||
id?: string
|
||||
info?: { role?: string; time?: string | { created?: number }; agent?: string }
|
||||
parts?: Array<{
|
||||
type?: string
|
||||
text?: string
|
||||
thinking?: string
|
||||
content?: string | Array<{ type: string; text?: string }>
|
||||
}>
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tool, type PluginInput, type ToolDefinition } from "@opencode-ai/plugin"
|
||||
import { tool, type ToolDefinition } from "@opencode-ai/plugin"
|
||||
import { existsSync, readdirSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import type { BackgroundManager, BackgroundTask } from "../../features/background-agent"
|
||||
@@ -9,7 +9,50 @@ import { getSessionAgent } from "../../features/claude-code-session-state"
|
||||
import { log } from "../../shared/logger"
|
||||
import { consumeNewMessages } from "../../shared/session-cursor"
|
||||
|
||||
type OpencodeClient = PluginInput["client"]
|
||||
type BackgroundOutputMessage = {
|
||||
info?: { role?: string; time?: string | { created?: number }; agent?: string }
|
||||
parts?: Array<{
|
||||
type?: string
|
||||
text?: string
|
||||
content?: string | Array<{ type: string; text?: string }>
|
||||
name?: string
|
||||
}>
|
||||
}
|
||||
|
||||
type BackgroundOutputMessagesResult =
|
||||
| { data?: BackgroundOutputMessage[]; error?: unknown }
|
||||
| BackgroundOutputMessage[]
|
||||
|
||||
export type BackgroundOutputClient = {
|
||||
session: {
|
||||
messages: (args: { path: { id: string } }) => Promise<BackgroundOutputMessagesResult>
|
||||
}
|
||||
}
|
||||
|
||||
export type BackgroundCancelClient = {
|
||||
session: {
|
||||
abort: (args: { path: { id: string } }) => Promise<unknown>
|
||||
}
|
||||
}
|
||||
|
||||
export type BackgroundOutputManager = Pick<BackgroundManager, "getTask">
|
||||
|
||||
const MAX_MESSAGE_LIMIT = 100
|
||||
const THINKING_MAX_CHARS = 2000
|
||||
|
||||
type FullSessionMessagePart = {
|
||||
type?: string
|
||||
text?: string
|
||||
thinking?: string
|
||||
content?: string | Array<{ type?: string; text?: string }>
|
||||
output?: string
|
||||
}
|
||||
|
||||
type FullSessionMessage = {
|
||||
id?: string
|
||||
info?: { role?: string; time?: string; agent?: string }
|
||||
parts?: FullSessionMessagePart[]
|
||||
}
|
||||
|
||||
function getMessageDir(sessionID: string): string | null {
|
||||
if (!existsSync(MESSAGE_STORAGE)) return null
|
||||
@@ -197,22 +240,14 @@ ${promptPreview}
|
||||
\`\`\`${lastMessageSection}`
|
||||
}
|
||||
|
||||
async function formatTaskResult(task: BackgroundTask, client: OpencodeClient): Promise<string> {
|
||||
if (!task.sessionID) {
|
||||
return `Error: Task has no sessionID`
|
||||
}
|
||||
function getErrorMessage(value: BackgroundOutputMessagesResult): string | null {
|
||||
if (Array.isArray(value)) return null
|
||||
if (value.error === undefined || value.error === null) return null
|
||||
if (typeof value.error === "string" && value.error.length > 0) return value.error
|
||||
return String(value.error)
|
||||
}
|
||||
|
||||
const messagesResult = await client.session.messages({
|
||||
path: { id: task.sessionID },
|
||||
})
|
||||
|
||||
if (messagesResult.error) {
|
||||
return `Error fetching messages: ${messagesResult.error}`
|
||||
}
|
||||
|
||||
// Handle both SDK response structures: direct array or wrapped in .data
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const messages = ((messagesResult as any).data ?? messagesResult) as Array<{
|
||||
function isSessionMessage(value: unknown): value is {
|
||||
info?: { role?: string; time?: string }
|
||||
parts?: Array<{
|
||||
type?: string
|
||||
@@ -220,7 +255,35 @@ async function formatTaskResult(task: BackgroundTask, client: OpencodeClient): P
|
||||
content?: string | Array<{ type: string; text?: string }>
|
||||
name?: string
|
||||
}>
|
||||
}>
|
||||
} {
|
||||
return typeof value === "object" && value !== null
|
||||
}
|
||||
|
||||
function extractMessages(value: BackgroundOutputMessagesResult): BackgroundOutputMessage[] {
|
||||
if (Array.isArray(value)) {
|
||||
return value.filter(isSessionMessage)
|
||||
}
|
||||
if (Array.isArray(value.data)) {
|
||||
return value.data.filter(isSessionMessage)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
async function formatTaskResult(task: BackgroundTask, client: BackgroundOutputClient): Promise<string> {
|
||||
if (!task.sessionID) {
|
||||
return `Error: Task has no sessionID`
|
||||
}
|
||||
|
||||
const messagesResult: BackgroundOutputMessagesResult = await client.session.messages({
|
||||
path: { id: task.sessionID },
|
||||
})
|
||||
|
||||
const errorMessage = getErrorMessage(messagesResult)
|
||||
if (errorMessage) {
|
||||
return `Error fetching messages: ${errorMessage}`
|
||||
}
|
||||
|
||||
const messages = extractMessages(messagesResult)
|
||||
|
||||
if (!Array.isArray(messages) || messages.length === 0) {
|
||||
return `Task Result
|
||||
@@ -321,13 +384,160 @@ Session ID: ${task.sessionID}
|
||||
${textContent || "(No text output)"}`
|
||||
}
|
||||
|
||||
export function createBackgroundOutput(manager: BackgroundManager, client: OpencodeClient): ToolDefinition {
|
||||
function extractToolResultText(part: FullSessionMessagePart): string[] {
|
||||
if (typeof part.content === "string" && part.content.length > 0) {
|
||||
return [part.content]
|
||||
}
|
||||
|
||||
if (Array.isArray(part.content)) {
|
||||
const blocks = part.content
|
||||
.filter((block) => (block.type === "text" || block.type === "reasoning") && block.text)
|
||||
.map((block) => block.text as string)
|
||||
if (blocks.length > 0) return blocks
|
||||
}
|
||||
|
||||
if (part.output && part.output.length > 0) {
|
||||
return [part.output]
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
async function formatFullSession(
|
||||
task: BackgroundTask,
|
||||
client: BackgroundOutputClient,
|
||||
options: {
|
||||
includeThinking: boolean
|
||||
messageLimit?: number
|
||||
sinceMessageId?: string
|
||||
includeToolResults: boolean
|
||||
thinkingMaxChars?: number
|
||||
}
|
||||
): Promise<string> {
|
||||
if (!task.sessionID) {
|
||||
return formatTaskStatus(task)
|
||||
}
|
||||
|
||||
const messagesResult: BackgroundOutputMessagesResult = await client.session.messages({
|
||||
path: { id: task.sessionID },
|
||||
})
|
||||
|
||||
const errorMessage = getErrorMessage(messagesResult)
|
||||
if (errorMessage) {
|
||||
return `Error fetching messages: ${errorMessage}`
|
||||
}
|
||||
|
||||
const rawMessages = extractMessages(messagesResult)
|
||||
if (!Array.isArray(rawMessages)) {
|
||||
return "Error fetching messages: invalid response"
|
||||
}
|
||||
|
||||
const sortedMessages = [...(rawMessages as FullSessionMessage[])].sort((a, b) => {
|
||||
const timeA = String(a.info?.time ?? "")
|
||||
const timeB = String(b.info?.time ?? "")
|
||||
return timeA.localeCompare(timeB)
|
||||
})
|
||||
|
||||
let filteredMessages = sortedMessages
|
||||
|
||||
if (options.sinceMessageId) {
|
||||
const index = filteredMessages.findIndex((message) => message.id === options.sinceMessageId)
|
||||
if (index === -1) {
|
||||
return `Error: since_message_id not found: ${options.sinceMessageId}`
|
||||
}
|
||||
filteredMessages = filteredMessages.slice(index + 1)
|
||||
}
|
||||
|
||||
const includeThinking = options.includeThinking
|
||||
const includeToolResults = options.includeToolResults
|
||||
const thinkingMaxChars = options.thinkingMaxChars ?? THINKING_MAX_CHARS
|
||||
|
||||
const normalizedMessages: FullSessionMessage[] = []
|
||||
for (const message of filteredMessages) {
|
||||
const parts = (message.parts ?? []).filter((part) => {
|
||||
if (part.type === "thinking" || part.type === "reasoning") {
|
||||
return includeThinking
|
||||
}
|
||||
if (part.type === "tool_result") {
|
||||
return includeToolResults
|
||||
}
|
||||
return part.type === "text"
|
||||
})
|
||||
|
||||
if (parts.length === 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
normalizedMessages.push({ ...message, parts })
|
||||
}
|
||||
|
||||
const limit = typeof options.messageLimit === "number"
|
||||
? Math.min(options.messageLimit, MAX_MESSAGE_LIMIT)
|
||||
: undefined
|
||||
const hasMore = limit !== undefined && normalizedMessages.length > limit
|
||||
const visibleMessages = limit !== undefined
|
||||
? normalizedMessages.slice(0, limit)
|
||||
: normalizedMessages
|
||||
|
||||
const lines: string[] = []
|
||||
lines.push("# Full Session Output")
|
||||
lines.push("")
|
||||
lines.push(`Task ID: ${task.id}`)
|
||||
lines.push(`Description: ${task.description}`)
|
||||
lines.push(`Status: ${task.status}`)
|
||||
lines.push(`Session ID: ${task.sessionID}`)
|
||||
lines.push(`Total messages: ${normalizedMessages.length}`)
|
||||
lines.push(`Returned: ${visibleMessages.length}`)
|
||||
lines.push(`Has more: ${hasMore ? "true" : "false"}`)
|
||||
lines.push("")
|
||||
lines.push("## Messages")
|
||||
|
||||
if (visibleMessages.length === 0) {
|
||||
lines.push("")
|
||||
lines.push("(No messages found)")
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
for (const message of visibleMessages) {
|
||||
const role = message.info?.role ?? "unknown"
|
||||
const agent = message.info?.agent ? ` (${message.info.agent})` : ""
|
||||
const time = formatMessageTime(message.info?.time)
|
||||
const idLabel = message.id ? ` id=${message.id}` : ""
|
||||
lines.push("")
|
||||
lines.push(`[${role}${agent}] ${time}${idLabel}`)
|
||||
|
||||
for (const part of message.parts ?? []) {
|
||||
if (part.type === "text" && part.text) {
|
||||
lines.push(part.text.trim())
|
||||
} else if (part.type === "thinking" && part.thinking) {
|
||||
lines.push(`[thinking] ${truncateText(part.thinking, thinkingMaxChars)}`)
|
||||
} else if (part.type === "reasoning" && part.text) {
|
||||
lines.push(`[thinking] ${truncateText(part.text, thinkingMaxChars)}`)
|
||||
} else if (part.type === "tool_result") {
|
||||
const toolTexts = extractToolResultText(part)
|
||||
for (const toolText of toolTexts) {
|
||||
lines.push(`[tool result] ${toolText}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
export function createBackgroundOutput(manager: BackgroundOutputManager, client: BackgroundOutputClient): ToolDefinition {
|
||||
return tool({
|
||||
description: BACKGROUND_OUTPUT_DESCRIPTION,
|
||||
args: {
|
||||
task_id: tool.schema.string().describe("Task ID to get output from"),
|
||||
block: tool.schema.boolean().optional().describe("Wait for completion (default: false). System notifies when done, so blocking is rarely needed."),
|
||||
timeout: tool.schema.number().optional().describe("Max wait time in ms (default: 60000, max: 600000)"),
|
||||
full_session: tool.schema.boolean().optional().describe("Return full session messages with filters (default: false)"),
|
||||
include_thinking: tool.schema.boolean().optional().describe("Include thinking/reasoning parts in full_session output (default: false)"),
|
||||
message_limit: tool.schema.number().optional().describe("Max messages to return (capped at 100)"),
|
||||
since_message_id: tool.schema.string().optional().describe("Return messages after this message ID (exclusive)"),
|
||||
include_tool_results: tool.schema.boolean().optional().describe("Include tool results in full_session output (default: false)"),
|
||||
thinking_max_chars: tool.schema.number().optional().describe("Max characters for thinking content (default: 2000)"),
|
||||
},
|
||||
async execute(args: BackgroundOutputArgs) {
|
||||
try {
|
||||
@@ -336,6 +546,16 @@ export function createBackgroundOutput(manager: BackgroundManager, client: Openc
|
||||
return `Task not found: ${args.task_id}`
|
||||
}
|
||||
|
||||
if (args.full_session === true) {
|
||||
return await formatFullSession(task, client, {
|
||||
includeThinking: args.include_thinking === true,
|
||||
messageLimit: args.message_limit,
|
||||
sinceMessageId: args.since_message_id,
|
||||
includeToolResults: args.include_tool_results === true,
|
||||
thinkingMaxChars: args.thinking_max_chars,
|
||||
})
|
||||
}
|
||||
|
||||
const shouldBlock = args.block === true
|
||||
const timeoutMs = Math.min(args.timeout ?? 60000, 600000)
|
||||
|
||||
@@ -387,7 +607,7 @@ export function createBackgroundOutput(manager: BackgroundManager, client: Openc
|
||||
})
|
||||
}
|
||||
|
||||
export function createBackgroundCancel(manager: BackgroundManager, client: OpencodeClient): ToolDefinition {
|
||||
export function createBackgroundCancel(manager: BackgroundManager, client: BackgroundCancelClient): ToolDefinition {
|
||||
return tool({
|
||||
description: BACKGROUND_CANCEL_DESCRIPTION,
|
||||
args: {
|
||||
@@ -515,3 +735,18 @@ Status: ${task.status}`
|
||||
},
|
||||
})
|
||||
}
|
||||
function formatMessageTime(value: unknown): string {
|
||||
if (typeof value === "string") {
|
||||
const date = new Date(value)
|
||||
return Number.isNaN(date.getTime()) ? value : date.toISOString()
|
||||
}
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if ("created" in value) {
|
||||
const created = (value as { created?: number }).created
|
||||
if (typeof created === "number") {
|
||||
return new Date(created).toISOString()
|
||||
}
|
||||
}
|
||||
}
|
||||
return "Unknown time"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@ export interface BackgroundOutputArgs {
|
||||
task_id: string
|
||||
block?: boolean
|
||||
timeout?: number
|
||||
full_session?: boolean
|
||||
include_thinking?: boolean
|
||||
message_limit?: number
|
||||
since_message_id?: string
|
||||
include_tool_results?: boolean
|
||||
thinking_max_chars?: number
|
||||
}
|
||||
|
||||
export interface BackgroundCancelArgs {
|
||||
|
||||
Reference in New Issue
Block a user