diff --git a/action.yml b/action.yml index 0675d69..ad0adad 100644 --- a/action.yml +++ b/action.yml @@ -7,9 +7,9 @@ inputs: description: "Prompt to send to the agent" required: true effort: - description: "Effort level: nothink (fast), think (default), max (most capable)" + description: "Effort level: mini (fast), auto (default), max (most capable)" required: false - default: "think" + default: "auto" cwd: description: "Working directory for the agent (defaults to GITHUB_WORKSPACE)" required: false diff --git a/agents/claude.ts b/agents/claude.ts index 953324d..5deaeba 100644 --- a/agents/claude.ts +++ b/agents/claude.ts @@ -6,10 +6,10 @@ import { addInstructions } from "./instructions.ts"; import { agent, createAgentEnv, installFromNpmTarball } from "./shared.ts"; // Model selection based on effort level -// Note: nothink uses Haiku for speed, think uses Sonnet for balance, max uses Opus for capability +// Note: mini uses Haiku for speed, auto uses opusplan for balance, max uses Opus for capability const claudeEffortModels: Record = { - nothink: "haiku", - think: "opusplan", + mini: "haiku", + auto: "opusplan", max: "opus", }; diff --git a/agents/codex.ts b/agents/codex.ts index 238a835..b3fb77f 100644 --- a/agents/codex.ts +++ b/agents/codex.ts @@ -15,16 +15,18 @@ import { agent, installFromNpmTarball, setupProcessAgentEnv } from "./shared.ts" // model configuration based on effort level const codexModel: Record = { - nothink: "gpt-5.1-codex-mini", - think: "gpt-5.1-codex", + mini: "gpt-5.1-codex-mini", + // https://developers.openai.com/codex/models/ + // gpt-5.2-codex is not yet available via api key (even through codex cli) + auto: "gpt-5.1-codex", max: "gpt-5.1-codex-max", } as const; // reasoning effort configuration based on effort level // uses modelReasoningEffort parameter from ThreadOptions const codexReasoningEffort: Record = { - nothink: "low", - think: undefined, // use default + mini: "low", + auto: undefined, // use default max: "high", }; diff --git a/agents/cursor.ts b/agents/cursor.ts index 2f05df6..db0b4f1 100644 --- a/agents/cursor.ts +++ b/agents/cursor.ts @@ -13,10 +13,10 @@ import { } from "./shared.ts"; // effort configuration for Cursor -// only "max" overrides the model; nothink/think use default ("auto") +// only "max" overrides the model; mini/auto use default ("auto") const cursorEffortModels: Record = { - nothink: null, // use default (auto) - think: null, // use default (auto) + mini: null, // use default (auto) + auto: null, // use default (auto) max: "opus-4.5-thinking", } as const; diff --git a/agents/gemini.ts b/agents/gemini.ts index 08db1c1..e40da8a 100644 --- a/agents/gemini.ts +++ b/agents/gemini.ts @@ -15,10 +15,15 @@ import { // effort configuration: model + thinking level // thinkingLevel is set via settings.json modelConfig.generateContentConfig.thinkingConfig // see: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels +// latest models: const geminiEffortConfig: Record = { - nothink: { model: "gemini-2.5-flash", thinkingLevel: "LOW" }, - think: { model: "gemini-2.5-flash", thinkingLevel: "HIGH" }, - max: { model: "gemini-2.5-pro", thinkingLevel: "HIGH" }, + // https://ai.google.dev/gemini-api/docs/models + // the docs mention needing to enable preview features for these models but if you + // pass the model directly it works if we ever did need to do something like this, + // we could write to .gemini/settings.json + mini: { model: "gemini-3-flash-preview", thinkingLevel: "LOW" }, + auto: { model: "gemini-3-flash-preview", thinkingLevel: "HIGH" }, + max: { model: "gemini-3-pro-preview", thinkingLevel: "HIGH" }, } as const; // gemini cli event types inferred from stream-json output (NDJSON format) diff --git a/dispatch/entry b/dispatch/entry index b1251b5..e79afa0 100755 --- a/dispatch/entry +++ b/dispatch/entry @@ -83424,7 +83424,7 @@ var schema = ark.schema; var define2 = ark.define; var declare = ark.declare; -// node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.77_zod@4.3.5/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs +// node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.2.7_zod@4.3.5/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs import { join as join5 } from "path"; import { fileURLToPath as fileURLToPath2 } from "url"; import { setMaxListeners } from "events"; @@ -90212,6 +90212,7 @@ function getInitialState() { } return { originalCwd: resolvedCwd, + projectRoot: resolvedCwd, totalCostUSD: 0, totalAPIDuration: 0, totalAPIDurationWithoutRetries: 0, @@ -90260,6 +90261,7 @@ function getInitialState() { inMemoryErrorLog: [], inlinePlugins: [], sessionBypassPermissionsMode: false, + sessionTrustAccepted: false, sessionPersistenceDisabled: false, hasExitedPlanMode: false, needsPlanModeExitAttachment: false, @@ -90272,25 +90274,14 @@ function getInitialState() { teleportedSessionInfo: null, invokedSkills: /* @__PURE__ */ new Map(), slowOperations: [], - sdkBetas: void 0 + sdkBetas: void 0, + mainThreadAgentType: void 0 }; } var STATE = getInitialState(); function getSessionId() { return STATE.sessionId; } -var MAX_SLOW_OPERATIONS = 10; -var SLOW_OPERATION_TTL_MS = 1e4; -function addSlowOperation(operation, durationMs) { - if (true) - return; - const now = Date.now(); - STATE.slowOperations = STATE.slowOperations.filter((op) => now - op.timestamp < SLOW_OPERATION_TTL_MS); - STATE.slowOperations.push({ operation, durationMs, timestamp: now }); - if (STATE.slowOperations.length > MAX_SLOW_OPERATIONS) { - STATE.slowOperations = STATE.slowOperations.slice(-MAX_SLOW_OPERATIONS); - } -} function createBufferedWriter({ writeFn, flushIntervalMs = 1e3, @@ -90362,9 +90353,7 @@ function withSlowLogging(operation, fn2) { return fn2(); } finally { const duration6 = performance.now() - startTime; - if (duration6 > SLOW_OPERATION_THRESHOLD_MS) { - logForDebugging(`[SLOW OPERATION DETECTED] ${operation} (${duration6.toFixed(1)}ms)`); - addSlowOperation(operation, duration6); + if (duration6 > SLOW_OPERATION_THRESHOLD_MS && false) { } } } @@ -90420,7 +90409,7 @@ function getDebugWriter() { } return debugWriter; } -function logForDebugging(message, { level } = { +function logForDebugging2(message, { level } = { level: "debug" }) { if (!shouldLogDebugMessage(message)) { @@ -90463,15 +90452,14 @@ var updateLatestDebugLogSymlink = memoize_default(() => { } catch { } }); +var isLoggingSlowOperation = false; function withSlowLogging2(operation, fn2) { const startTime = performance.now(); try { return fn2(); } finally { const duration6 = performance.now() - startTime; - if (duration6 > SLOW_OPERATION_THRESHOLD_MS) { - logForDebugging(`[SLOW OPERATION DETECTED] fs.${operation} (${duration6.toFixed(1)}ms)`); - addSlowOperation(`fs.${operation}`, duration6); + if (duration6 > SLOW_OPERATION_THRESHOLD_MS && !isLoggingSlowOperation && false) { } } } @@ -91254,7 +91242,7 @@ var Query = class { this.firstResultReceivedResolve(); } if (this.isSingleUserTurn) { - logForDebugging(`[Query.readMessages] First result received for single-turn query, closing stdin`); + logForDebugging2(`[Query.readMessages] First result received for single-turn query, closing stdin`); this.transport.endInput(); } } @@ -91498,23 +91486,23 @@ var Query = class { return (await this.initialization).account; } async streamInput(stream) { - logForDebugging(`[Query.streamInput] Starting to process input stream`); + logForDebugging2(`[Query.streamInput] Starting to process input stream`); try { let messageCount = 0; for await (const message of stream) { messageCount++; - logForDebugging(`[Query.streamInput] Processing message ${messageCount}: ${message.type}`); + logForDebugging2(`[Query.streamInput] Processing message ${messageCount}: ${message.type}`); if (this.abortController?.signal.aborted) break; await Promise.resolve(this.transport.write(jsonStringify(message) + ` `)); } - logForDebugging(`[Query.streamInput] Finished processing ${messageCount} messages from input stream`); + logForDebugging2(`[Query.streamInput] Finished processing ${messageCount} messages from input stream`); if (messageCount > 0 && this.hasBidirectionalNeeds()) { - logForDebugging(`[Query.streamInput] Has bidirectional needs, waiting for first result`); + logForDebugging2(`[Query.streamInput] Has bidirectional needs, waiting for first result`); await this.waitForFirstResult(); } - logForDebugging(`[Query] Calling transport.endInput() to close stdin to CLI process`); + logForDebugging2(`[Query] Calling transport.endInput() to close stdin to CLI process`); this.transport.endInput(); } catch (error50) { if (!(error50 instanceof AbortError)) { @@ -91524,7 +91512,7 @@ var Query = class { } waitForFirstResult() { if (this.firstResultReceived) { - logForDebugging(`[Query.waitForFirstResult] Result already received, returning immediately`); + logForDebugging2(`[Query.waitForFirstResult] Result already received, returning immediately`); return Promise.resolve(); } return new Promise((resolve2) => { @@ -99836,7 +99824,7 @@ function query({ const dirname2 = join5(filename, ".."); pathToClaudeCodeExecutable = join5(dirname2, "cli.js"); } - process.env.CLAUDE_AGENT_SDK_VERSION = "0.1.77"; + process.env.CLAUDE_AGENT_SDK_VERSION = "0.2.7"; const { abortController = createAbortController(), additionalDirectories = [], @@ -99992,13 +99980,13 @@ var package_default = { dependencies: { "@actions/core": "^1.11.1", "@actions/github": "^6.0.1", - "@anthropic-ai/claude-agent-sdk": "0.1.77", + "@anthropic-ai/claude-agent-sdk": "0.2.7", "@ark/fs": "0.53.0", "@ark/util": "0.53.0", "@octokit/plugin-throttling": "^11.0.3", "@octokit/rest": "^22.0.0", "@octokit/webhooks-types": "^7.6.1", - "@openai/codex-sdk": "0.58.0", + "@openai/codex-sdk": "0.80.0", "@opencode-ai/sdk": "^1.0.143", "@standard-schema/spec": "1.0.0", "@toon-format/toon": "^1.0.0", @@ -100342,7 +100330,7 @@ var agentsManifest = { } }; var AgentName = type.enumerated(...Object.keys(agentsManifest)); -var Effort = type.enumerated("nothink", "think", "max"); +var Effort = type.enumerated("mini", "auto", "max"); // modes.ts var ModeSchema = type({ @@ -104740,8 +104728,8 @@ var agent = (input) => { // agents/claude.ts var claudeEffortModels = { - nothink: "haiku", - think: "opusplan", + mini: "haiku", + auto: "opusplan", max: "opus" }; var claude = agent({ @@ -104887,7 +104875,7 @@ var messageHandlers = { import { mkdirSync as mkdirSync3, writeFileSync } from "node:fs"; import { join as join6 } from "node:path"; -// node_modules/.pnpm/@openai+codex-sdk@0.58.0/node_modules/@openai/codex-sdk/dist/index.js +// node_modules/.pnpm/@openai+codex-sdk@0.80.0/node_modules/@openai/codex-sdk/dist/index.js import { promises as fs2 } from "fs"; import os from "os"; import path from "path"; @@ -104958,9 +104946,11 @@ var Thread = class { skipGitRepoCheck: options?.skipGitRepoCheck, outputSchemaFile: schemaPath, modelReasoningEffort: options?.modelReasoningEffort, + signal: turnOptions.signal, networkAccessEnabled: options?.networkAccessEnabled, webSearchEnabled: options?.webSearchEnabled, - approvalPolicy: options?.approvalPolicy + approvalPolicy: options?.approvalPolicy, + additionalDirectories: options?.additionalDirectories }); try { for await (const item of generator) { @@ -105024,8 +105014,10 @@ var INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE"; var TYPESCRIPT_SDK_ORIGINATOR = "codex_sdk_ts"; var CodexExec = class { executablePath; - constructor(executablePath = null) { + envOverride; + constructor(executablePath = null, env3) { this.executablePath = executablePath || findCodexPath(); + this.envOverride = env3; } async *run(args3) { const commandArgs = ["exec", "--experimental-json"]; @@ -105038,6 +105030,11 @@ var CodexExec = class { if (args3.workingDirectory) { commandArgs.push("--cd", args3.workingDirectory); } + if (args3.additionalDirectories?.length) { + for (const dir of args3.additionalDirectories) { + commandArgs.push("--add-dir", dir); + } + } if (args3.skipGitRepoCheck) { commandArgs.push("--skip-git-repo-check"); } @@ -105048,7 +105045,10 @@ var CodexExec = class { commandArgs.push("--config", `model_reasoning_effort="${args3.modelReasoningEffort}"`); } if (args3.networkAccessEnabled !== void 0) { - commandArgs.push("--config", `sandbox_workspace_write.network_access=${args3.networkAccessEnabled}`); + commandArgs.push( + "--config", + `sandbox_workspace_write.network_access=${args3.networkAccessEnabled}` + ); } if (args3.webSearchEnabled !== void 0) { commandArgs.push("--config", `features.web_search_request=${args3.webSearchEnabled}`); @@ -105064,9 +105064,16 @@ var CodexExec = class { if (args3.threadId) { commandArgs.push("resume", args3.threadId); } - const env3 = { - ...process.env - }; + const env3 = {}; + if (this.envOverride) { + Object.assign(env3, this.envOverride); + } else { + for (const [key, value2] of Object.entries(process.env)) { + if (value2 !== void 0) { + env3[key] = value2; + } + } + } if (!env3[INTERNAL_ORIGINATOR_ENV]) { env3[INTERNAL_ORIGINATOR_ENV] = TYPESCRIPT_SDK_ORIGINATOR; } @@ -105077,7 +105084,8 @@ var CodexExec = class { env3.CODEX_API_KEY = args3.apiKey; } const child = spawn2(this.executablePath, commandArgs, { - env: env3 + env: env3, + signal: args3.signal }); let spawnError = null; child.once("error", (err) => spawnError = err); @@ -105097,6 +105105,13 @@ var CodexExec = class { stderrChunks.push(data); }); } + const exitPromise = new Promise( + (resolve2) => { + child.once("exit", (code, signal) => { + resolve2({ code, signal }); + }); + } + ); const rl = readline.createInterface({ input: child.stdout, crlfDelay: Infinity @@ -105105,20 +105120,13 @@ var CodexExec = class { for await (const line of rl) { yield line; } - const exitCode = new Promise((resolve2, reject) => { - child.once("exit", (code) => { - if (code === 0) { - resolve2(code); - } else { - const stderrBuffer = Buffer.concat(stderrChunks); - reject( - new Error(`Codex Exec exited with code ${code}: ${stderrBuffer.toString("utf8")}`) - ); - } - }); - }); if (spawnError) throw spawnError; - await exitCode; + const { code, signal } = await exitPromise; + if (code !== 0 || signal) { + const stderrBuffer = Buffer.concat(stderrChunks); + const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`; + throw new Error(`Codex Exec exited with ${detail}: ${stderrBuffer.toString("utf8")}`); + } } finally { rl.close(); child.removeAllListeners(); @@ -105188,7 +105196,7 @@ var Codex = class { exec; options; constructor(options = {}) { - this.exec = new CodexExec(options.codexPathOverride); + this.exec = new CodexExec(options.codexPathOverride, options.env); this.options = options; } /** @@ -105212,13 +105220,15 @@ var Codex = class { // agents/codex.ts var codexModel = { - nothink: "gpt-5.1-codex-mini", - think: "gpt-5.1-codex", + mini: "gpt-5.1-codex-mini", + // https://developers.openai.com/codex/models/ + // gpt-5.2-codex is not yet available via api key (even through codex cli) + auto: "gpt-5.1-codex", max: "gpt-5.1-codex-max" }; var codexReasoningEffort = { - nothink: "low", - think: void 0, + mini: "low", + auto: void 0, // use default max: "high" }; @@ -105416,9 +105426,9 @@ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as rea import { homedir as homedir2 } from "node:os"; import { join as join7 } from "node:path"; var cursorEffortModels = { - nothink: null, + mini: null, // use default (auto) - think: null, + auto: null, // use default (auto) max: "opus-4.5-thinking" }; @@ -105727,9 +105737,13 @@ async function spawn4(options) { // agents/gemini.ts var geminiEffortConfig = { - nothink: { model: "gemini-2.5-flash", thinkingLevel: "LOW" }, - think: { model: "gemini-2.5-flash", thinkingLevel: "HIGH" }, - max: { model: "gemini-2.5-pro", thinkingLevel: "HIGH" } + // https://ai.google.dev/gemini-api/docs/models + // the docs mention needing to enable preview features for these models but if you + // pass the model directly it works if we ever did need to do something like this, + // we could write to .gemini/settings.json + mini: { model: "gemini-3-flash-preview", thinkingLevel: "LOW" }, + auto: { model: "gemini-3-flash-preview", thinkingLevel: "HIGH" }, + max: { model: "gemini-3-pro-preview", thinkingLevel: "HIGH" } }; var assistantMessageBuffer = ""; var messageHandlers3 = { @@ -138688,7 +138702,7 @@ function parsePayload(inputs) { prompt: inputs.prompt, event: inputs.event, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox, disableProgressComment: inputs.disableProgressComment, comment_id: inputs.comment_id, @@ -138703,7 +138717,7 @@ function parsePayload(inputs) { } return { ...parsedPrompt, - effort: parsedPrompt.effort ?? inputs.effort ?? "think" + effort: parsedPrompt.effort ?? inputs.effort ?? "auto" }; } catch { return { @@ -138714,7 +138728,7 @@ function parsePayload(inputs) { trigger: "unknown" }, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox }; } @@ -138761,7 +138775,7 @@ function validateApiKey(params) { }; } async function runAgent(ctx) { - const effort = ctx.payload.effort ?? "think"; + const effort = ctx.payload.effort ?? "auto"; log.info(`Running ${ctx.agent.name} with effort=${effort}...`); const { context: _context, ...eventWithoutContext } = ctx.payload.event; const promptContent = `${ctx.payload.prompt} diff --git a/effort.md b/effort.md index 71986e8..0bb6316 100644 --- a/effort.md +++ b/effort.md @@ -2,11 +2,14 @@ Pullfrog supports three effort levels that control model selection and reasoning depth: -- **`nothink`** — Fast, minimal reasoning. Best for simple tasks. -- **`think`** — Balanced (default). Good for most tasks. -- **`max`** — Maximum capability. Best for complex tasks requiring deep reasoning. +- **`#mini`** — Fast, minimal reasoning. Best for simple tasks. +- **`#auto`** — Balanced (default). Good for most tasks. +- **`#max`** — Maximum capability. Best for complex tasks requiring deep reasoning. -The effort level can be specified via the `effort` input in `action.yml` or in the payload's `effort` field. +The effort level can be specified via: +1. Macros in the prompt (`#mini`, `#auto`, `#max`) +2. The `effort` input in `action.yml` +3. The payload's `effort` field --- @@ -16,8 +19,8 @@ Claude Code uses model selection based on effort level. | Effort | Model | Description | |--------|-------|-------------| -| `nothink` | `haiku` | Fast, efficient | -| `think` | `opusplan` | Opus for planning, Sonnet for execution | +| `mini` | `haiku` | Fast, efficient | +| `auto` | `opusplan` | Opus for planning, Sonnet for execution | | `max` | `opus` | Full Opus | > **Future direction:** Anthropic's beta `effort` parameter (`low`/`medium`/`high`) could replace model selection, using Opus 4.5 for all tasks with effort controlling token spend. See [Anthropic Effort Docs](https://platform.claude.com/docs/en/build-with-claude/effort). @@ -30,8 +33,8 @@ Codex uses both model selection and the `modelReasoningEffort` parameter from `T | Effort | Model | `modelReasoningEffort` | Description | |--------|-------|------------------------|-------------| -| `nothink` | `gpt-5.1-codex-mini` | `"low"` | Smaller model, reduced reasoning | -| `think` | `gpt-5.1-codex` | default | Standard model, default reasoning | +| `mini` | `gpt-5.1-codex-mini` | `"low"` | Smaller model, reduced reasoning | +| `auto` | `gpt-5.1-codex` | default | Standard model, default reasoning | | `max` | `gpt-5.1-codex-max` | `"high"` | Largest model, maximum reasoning | Valid values for `modelReasoningEffort`: `"minimal"` | `"low"` | `"medium"` | `"high"` @@ -46,8 +49,8 @@ Gemini uses a combination of model selection and `thinkingLevel` configuration v | Effort | Model | `thinkingLevel` | Description | |--------|-------|-----------------|-------------| -| `nothink` | `gemini-2.5-flash` | `LOW` | Fast model, minimal thinking | -| `think` | `gemini-2.5-flash` | `HIGH` | Fast model, deep thinking | +| `mini` | `gemini-2.5-flash` | `LOW` | Fast model, minimal thinking | +| `auto` | `gemini-2.5-flash` | `HIGH` | Fast model, deep thinking | | `max` | `gemini-2.5-pro` | `HIGH` | Most capable model, deep thinking | The `thinkingLevel` is configured via: @@ -73,8 +76,8 @@ Cursor uses model selection via the `--model` CLI flag. Project-level configurat | Effort | Model | Description | |--------|-------|-------------| -| `nothink` | `auto` (default) | Let Cursor select optimal model | -| `think` | `auto` (default) | Let Cursor select optimal model | +| `mini` | `auto` (default) | Let Cursor select optimal model | +| `auto` | `auto` (default) | Let Cursor select optimal model | | `max` | `opus-4.5-thinking` | Claude 4.5 Opus with thinking | **Note:** If the project has `.cursor/cli.json` with a `model` field, that model is used regardless of effort level. @@ -87,6 +90,6 @@ OpenCode does not currently have affordances for effort-level configuration. The | Effort | Behavior | |--------|----------| -| `nothink` | No effect | -| `think` | No effect | +| `mini` | No effect | +| `auto` | No effect | | `max` | No effect | diff --git a/entry b/entry index 3b0b081..a9a42d0 100755 --- a/entry +++ b/entry @@ -83424,7 +83424,7 @@ var schema = ark.schema; var define2 = ark.define; var declare = ark.declare; -// node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.77_zod@4.3.5/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs +// node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.2.7_zod@4.3.5/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs import { join as join5 } from "path"; import { fileURLToPath as fileURLToPath2 } from "url"; import { setMaxListeners } from "events"; @@ -90212,6 +90212,7 @@ function getInitialState() { } return { originalCwd: resolvedCwd, + projectRoot: resolvedCwd, totalCostUSD: 0, totalAPIDuration: 0, totalAPIDurationWithoutRetries: 0, @@ -90260,6 +90261,7 @@ function getInitialState() { inMemoryErrorLog: [], inlinePlugins: [], sessionBypassPermissionsMode: false, + sessionTrustAccepted: false, sessionPersistenceDisabled: false, hasExitedPlanMode: false, needsPlanModeExitAttachment: false, @@ -90272,25 +90274,14 @@ function getInitialState() { teleportedSessionInfo: null, invokedSkills: /* @__PURE__ */ new Map(), slowOperations: [], - sdkBetas: void 0 + sdkBetas: void 0, + mainThreadAgentType: void 0 }; } var STATE = getInitialState(); function getSessionId() { return STATE.sessionId; } -var MAX_SLOW_OPERATIONS = 10; -var SLOW_OPERATION_TTL_MS = 1e4; -function addSlowOperation(operation, durationMs) { - if (true) - return; - const now = Date.now(); - STATE.slowOperations = STATE.slowOperations.filter((op) => now - op.timestamp < SLOW_OPERATION_TTL_MS); - STATE.slowOperations.push({ operation, durationMs, timestamp: now }); - if (STATE.slowOperations.length > MAX_SLOW_OPERATIONS) { - STATE.slowOperations = STATE.slowOperations.slice(-MAX_SLOW_OPERATIONS); - } -} function createBufferedWriter({ writeFn, flushIntervalMs = 1e3, @@ -90362,9 +90353,7 @@ function withSlowLogging(operation, fn2) { return fn2(); } finally { const duration6 = performance.now() - startTime; - if (duration6 > SLOW_OPERATION_THRESHOLD_MS) { - logForDebugging(`[SLOW OPERATION DETECTED] ${operation} (${duration6.toFixed(1)}ms)`); - addSlowOperation(operation, duration6); + if (duration6 > SLOW_OPERATION_THRESHOLD_MS && false) { } } } @@ -90420,7 +90409,7 @@ function getDebugWriter() { } return debugWriter; } -function logForDebugging(message, { level } = { +function logForDebugging2(message, { level } = { level: "debug" }) { if (!shouldLogDebugMessage(message)) { @@ -90463,15 +90452,14 @@ var updateLatestDebugLogSymlink = memoize_default(() => { } catch { } }); +var isLoggingSlowOperation = false; function withSlowLogging2(operation, fn2) { const startTime = performance.now(); try { return fn2(); } finally { const duration6 = performance.now() - startTime; - if (duration6 > SLOW_OPERATION_THRESHOLD_MS) { - logForDebugging(`[SLOW OPERATION DETECTED] fs.${operation} (${duration6.toFixed(1)}ms)`); - addSlowOperation(`fs.${operation}`, duration6); + if (duration6 > SLOW_OPERATION_THRESHOLD_MS && !isLoggingSlowOperation && false) { } } } @@ -91254,7 +91242,7 @@ var Query = class { this.firstResultReceivedResolve(); } if (this.isSingleUserTurn) { - logForDebugging(`[Query.readMessages] First result received for single-turn query, closing stdin`); + logForDebugging2(`[Query.readMessages] First result received for single-turn query, closing stdin`); this.transport.endInput(); } } @@ -91498,23 +91486,23 @@ var Query = class { return (await this.initialization).account; } async streamInput(stream) { - logForDebugging(`[Query.streamInput] Starting to process input stream`); + logForDebugging2(`[Query.streamInput] Starting to process input stream`); try { let messageCount = 0; for await (const message of stream) { messageCount++; - logForDebugging(`[Query.streamInput] Processing message ${messageCount}: ${message.type}`); + logForDebugging2(`[Query.streamInput] Processing message ${messageCount}: ${message.type}`); if (this.abortController?.signal.aborted) break; await Promise.resolve(this.transport.write(jsonStringify(message) + ` `)); } - logForDebugging(`[Query.streamInput] Finished processing ${messageCount} messages from input stream`); + logForDebugging2(`[Query.streamInput] Finished processing ${messageCount} messages from input stream`); if (messageCount > 0 && this.hasBidirectionalNeeds()) { - logForDebugging(`[Query.streamInput] Has bidirectional needs, waiting for first result`); + logForDebugging2(`[Query.streamInput] Has bidirectional needs, waiting for first result`); await this.waitForFirstResult(); } - logForDebugging(`[Query] Calling transport.endInput() to close stdin to CLI process`); + logForDebugging2(`[Query] Calling transport.endInput() to close stdin to CLI process`); this.transport.endInput(); } catch (error50) { if (!(error50 instanceof AbortError)) { @@ -91524,7 +91512,7 @@ var Query = class { } waitForFirstResult() { if (this.firstResultReceived) { - logForDebugging(`[Query.waitForFirstResult] Result already received, returning immediately`); + logForDebugging2(`[Query.waitForFirstResult] Result already received, returning immediately`); return Promise.resolve(); } return new Promise((resolve2) => { @@ -99836,7 +99824,7 @@ function query({ const dirname2 = join5(filename, ".."); pathToClaudeCodeExecutable = join5(dirname2, "cli.js"); } - process.env.CLAUDE_AGENT_SDK_VERSION = "0.1.77"; + process.env.CLAUDE_AGENT_SDK_VERSION = "0.2.7"; const { abortController = createAbortController(), additionalDirectories = [], @@ -99992,13 +99980,13 @@ var package_default = { dependencies: { "@actions/core": "^1.11.1", "@actions/github": "^6.0.1", - "@anthropic-ai/claude-agent-sdk": "0.1.77", + "@anthropic-ai/claude-agent-sdk": "0.2.7", "@ark/fs": "0.53.0", "@ark/util": "0.53.0", "@octokit/plugin-throttling": "^11.0.3", "@octokit/rest": "^22.0.0", "@octokit/webhooks-types": "^7.6.1", - "@openai/codex-sdk": "0.58.0", + "@openai/codex-sdk": "0.80.0", "@opencode-ai/sdk": "^1.0.143", "@standard-schema/spec": "1.0.0", "@toon-format/toon": "^1.0.0", @@ -100342,7 +100330,7 @@ var agentsManifest = { } }; var AgentName = type.enumerated(...Object.keys(agentsManifest)); -var Effort = type.enumerated("nothink", "think", "max"); +var Effort = type.enumerated("mini", "auto", "max"); // modes.ts var ModeSchema = type({ @@ -104740,8 +104728,8 @@ var agent = (input) => { // agents/claude.ts var claudeEffortModels = { - nothink: "haiku", - think: "opusplan", + mini: "haiku", + auto: "opusplan", max: "opus" }; var claude = agent({ @@ -104887,7 +104875,7 @@ var messageHandlers = { import { mkdirSync as mkdirSync3, writeFileSync } from "node:fs"; import { join as join6 } from "node:path"; -// node_modules/.pnpm/@openai+codex-sdk@0.58.0/node_modules/@openai/codex-sdk/dist/index.js +// node_modules/.pnpm/@openai+codex-sdk@0.80.0/node_modules/@openai/codex-sdk/dist/index.js import { promises as fs2 } from "fs"; import os from "os"; import path from "path"; @@ -104958,9 +104946,11 @@ var Thread = class { skipGitRepoCheck: options?.skipGitRepoCheck, outputSchemaFile: schemaPath, modelReasoningEffort: options?.modelReasoningEffort, + signal: turnOptions.signal, networkAccessEnabled: options?.networkAccessEnabled, webSearchEnabled: options?.webSearchEnabled, - approvalPolicy: options?.approvalPolicy + approvalPolicy: options?.approvalPolicy, + additionalDirectories: options?.additionalDirectories }); try { for await (const item of generator) { @@ -105024,8 +105014,10 @@ var INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE"; var TYPESCRIPT_SDK_ORIGINATOR = "codex_sdk_ts"; var CodexExec = class { executablePath; - constructor(executablePath = null) { + envOverride; + constructor(executablePath = null, env3) { this.executablePath = executablePath || findCodexPath(); + this.envOverride = env3; } async *run(args3) { const commandArgs = ["exec", "--experimental-json"]; @@ -105038,6 +105030,11 @@ var CodexExec = class { if (args3.workingDirectory) { commandArgs.push("--cd", args3.workingDirectory); } + if (args3.additionalDirectories?.length) { + for (const dir of args3.additionalDirectories) { + commandArgs.push("--add-dir", dir); + } + } if (args3.skipGitRepoCheck) { commandArgs.push("--skip-git-repo-check"); } @@ -105048,7 +105045,10 @@ var CodexExec = class { commandArgs.push("--config", `model_reasoning_effort="${args3.modelReasoningEffort}"`); } if (args3.networkAccessEnabled !== void 0) { - commandArgs.push("--config", `sandbox_workspace_write.network_access=${args3.networkAccessEnabled}`); + commandArgs.push( + "--config", + `sandbox_workspace_write.network_access=${args3.networkAccessEnabled}` + ); } if (args3.webSearchEnabled !== void 0) { commandArgs.push("--config", `features.web_search_request=${args3.webSearchEnabled}`); @@ -105064,9 +105064,16 @@ var CodexExec = class { if (args3.threadId) { commandArgs.push("resume", args3.threadId); } - const env3 = { - ...process.env - }; + const env3 = {}; + if (this.envOverride) { + Object.assign(env3, this.envOverride); + } else { + for (const [key, value2] of Object.entries(process.env)) { + if (value2 !== void 0) { + env3[key] = value2; + } + } + } if (!env3[INTERNAL_ORIGINATOR_ENV]) { env3[INTERNAL_ORIGINATOR_ENV] = TYPESCRIPT_SDK_ORIGINATOR; } @@ -105077,7 +105084,8 @@ var CodexExec = class { env3.CODEX_API_KEY = args3.apiKey; } const child = spawn2(this.executablePath, commandArgs, { - env: env3 + env: env3, + signal: args3.signal }); let spawnError = null; child.once("error", (err) => spawnError = err); @@ -105097,6 +105105,13 @@ var CodexExec = class { stderrChunks.push(data); }); } + const exitPromise = new Promise( + (resolve2) => { + child.once("exit", (code, signal) => { + resolve2({ code, signal }); + }); + } + ); const rl = readline.createInterface({ input: child.stdout, crlfDelay: Infinity @@ -105105,20 +105120,13 @@ var CodexExec = class { for await (const line of rl) { yield line; } - const exitCode = new Promise((resolve2, reject) => { - child.once("exit", (code) => { - if (code === 0) { - resolve2(code); - } else { - const stderrBuffer = Buffer.concat(stderrChunks); - reject( - new Error(`Codex Exec exited with code ${code}: ${stderrBuffer.toString("utf8")}`) - ); - } - }); - }); if (spawnError) throw spawnError; - await exitCode; + const { code, signal } = await exitPromise; + if (code !== 0 || signal) { + const stderrBuffer = Buffer.concat(stderrChunks); + const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`; + throw new Error(`Codex Exec exited with ${detail}: ${stderrBuffer.toString("utf8")}`); + } } finally { rl.close(); child.removeAllListeners(); @@ -105188,7 +105196,7 @@ var Codex = class { exec; options; constructor(options = {}) { - this.exec = new CodexExec(options.codexPathOverride); + this.exec = new CodexExec(options.codexPathOverride, options.env); this.options = options; } /** @@ -105212,13 +105220,15 @@ var Codex = class { // agents/codex.ts var codexModel = { - nothink: "gpt-5.1-codex-mini", - think: "gpt-5.1-codex", + mini: "gpt-5.1-codex-mini", + // https://developers.openai.com/codex/models/ + // gpt-5.2-codex is not yet available via api key (even through codex cli) + auto: "gpt-5.1-codex", max: "gpt-5.1-codex-max" }; var codexReasoningEffort = { - nothink: "low", - think: void 0, + mini: "low", + auto: void 0, // use default max: "high" }; @@ -105416,9 +105426,9 @@ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as rea import { homedir as homedir2 } from "node:os"; import { join as join7 } from "node:path"; var cursorEffortModels = { - nothink: null, + mini: null, // use default (auto) - think: null, + auto: null, // use default (auto) max: "opus-4.5-thinking" }; @@ -105727,9 +105737,13 @@ async function spawn4(options) { // agents/gemini.ts var geminiEffortConfig = { - nothink: { model: "gemini-2.5-flash", thinkingLevel: "LOW" }, - think: { model: "gemini-2.5-flash", thinkingLevel: "HIGH" }, - max: { model: "gemini-2.5-pro", thinkingLevel: "HIGH" } + // https://ai.google.dev/gemini-api/docs/models + // the docs mention needing to enable preview features for these models but if you + // pass the model directly it works if we ever did need to do something like this, + // we could write to .gemini/settings.json + mini: { model: "gemini-3-flash-preview", thinkingLevel: "LOW" }, + auto: { model: "gemini-3-flash-preview", thinkingLevel: "HIGH" }, + max: { model: "gemini-3-pro-preview", thinkingLevel: "HIGH" } }; var assistantMessageBuffer = ""; var messageHandlers3 = { @@ -138688,7 +138702,7 @@ function parsePayload(inputs) { prompt: inputs.prompt, event: inputs.event, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox, disableProgressComment: inputs.disableProgressComment, comment_id: inputs.comment_id, @@ -138703,7 +138717,7 @@ function parsePayload(inputs) { } return { ...parsedPrompt, - effort: parsedPrompt.effort ?? inputs.effort ?? "think" + effort: parsedPrompt.effort ?? inputs.effort ?? "auto" }; } catch { return { @@ -138714,7 +138728,7 @@ function parsePayload(inputs) { trigger: "unknown" }, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox }; } @@ -138761,7 +138775,7 @@ function validateApiKey(params) { }; } async function runAgent(ctx) { - const effort = ctx.payload.effort ?? "think"; + const effort = ctx.payload.effort ?? "auto"; log.info(`Running ${ctx.agent.name} with effort=${effort}...`); const { context: _context, ...eventWithoutContext } = ctx.payload.event; const promptContent = `${ctx.payload.prompt} @@ -138804,7 +138818,7 @@ async function run() { try { const inputs = Inputs.assert({ prompt: core4.getInput("prompt", { required: true }), - effort: core4.getInput("effort") || "think", + effort: core4.getInput("effort") || "auto", cwd: core4.getInput("cwd") || null }); const result = await main(inputs); diff --git a/entry.ts b/entry.ts index ae909fd..fc78d47 100644 --- a/entry.ts +++ b/entry.ts @@ -11,7 +11,7 @@ async function run(): Promise { try { const inputs = Inputs.assert({ prompt: core.getInput("prompt", { required: true }), - effort: core.getInput("effort") || "think", + effort: core.getInput("effort") || "auto", cwd: core.getInput("cwd") || null, }); diff --git a/external.ts b/external.ts index c0b9599..6695f00 100644 --- a/external.ts +++ b/external.ts @@ -52,7 +52,8 @@ export const AgentName = type.enumerated(...Object.keys(agentsManifest)); export type AgentApiKeyName = (typeof agentsManifest)[AgentName]["apiKeyNames"][number]; // effort level type - controls model selection and thinking level -export const Effort = type.enumerated("nothink", "think", "max"); +// mini = fast/minimal, auto = balanced/default, max = maximum capability +export const Effort = type.enumerated("mini", "auto", "max"); export type Effort = typeof Effort.infer; // base interface for common payload event fields @@ -284,8 +285,8 @@ export interface Payload extends DispatchOptions { modes: readonly Mode[]; /** - * Effort level for model selection (nothink, think, max) - * Defaults to "think" if not specified + * Effort level for model selection (mini, auto, max) + * Defaults to "auto" if not specified */ readonly effort?: Effort; diff --git a/fixtures/claude-effort.ts b/fixtures/claude-effort.ts new file mode 100644 index 0000000..04c6f70 --- /dev/null +++ b/fixtures/claude-effort.ts @@ -0,0 +1,27 @@ +import type { Effort, Payload } from "../external.ts"; + +/** + * Test fixture for Claude effort levels. + * Runs all three effort levels in sequence. + * + * Run with: + * AGENT_OVERRIDE=claude pnpm play claude-effort.ts + * + * Effort levels: + * - "mini": haiku (fast, efficient) + * - "auto": opusplan (Opus for planning, Sonnet for execution) + * - "max": opus (full Opus capability) + */ + +const efforts: Effort[] = ["mini", "auto", "max"]; + +export default efforts.map((effort) => ({ + "~pullfrog": true, + agent: "claude", + prompt: "What is 2 + 2? Reply with just the number.", + event: { + trigger: "workflow_dispatch", + }, + modes: [], + effort, +})) satisfies Payload[]; diff --git a/fixtures/codex-effort.ts b/fixtures/codex-effort.ts new file mode 100644 index 0000000..5821578 --- /dev/null +++ b/fixtures/codex-effort.ts @@ -0,0 +1,27 @@ +import type { Effort, Payload } from "../external.ts"; + +/** + * Test fixture for Codex effort levels. + * Runs all three effort levels in sequence. + * + * Run with: + * AGENT_OVERRIDE=codex pnpm play codex-effort.ts + * + * Effort levels: + * - "mini": gpt-5.1-codex-mini + modelReasoningEffort: "low" + * - "auto": gpt-5.1-codex + default reasoning + * - "max": gpt-5.1-codex-max + modelReasoningEffort: "high" + */ + +const efforts: Effort[] = ["mini", "auto", "max"]; + +export default efforts.map((effort) => ({ + "~pullfrog": true, + agent: "codex", + prompt: "What is 2 + 2? Reply with just the number.", + event: { + trigger: "workflow_dispatch", + }, + modes: [], + effort, +})) satisfies Payload[]; diff --git a/fixtures/cursor-effort.ts b/fixtures/cursor-effort.ts index b6b72b8..7e08fd5 100644 --- a/fixtures/cursor-effort.ts +++ b/fixtures/cursor-effort.ts @@ -8,15 +8,15 @@ import type { Effort, Payload } from "../external.ts"; * AGENT_OVERRIDE=cursor pnpm play cursor-effort.ts * * Effort levels: - * - "nothink": auto (default model) - * - "think": auto (default model) + * - "mini": auto (default model) + * - "auto": auto (default model) * - "max": opus-4.5-thinking * * Note: If project has .cursor/cli.json with "model" specified, * that takes precedence over effort-based model selection. */ -const efforts: Effort[] = ["nothink", "think", "max"]; +const efforts: Effort[] = ["mini", "auto", "max"]; export default efforts.map((effort) => ({ "~pullfrog": true, diff --git a/fixtures/gemini-effort.ts b/fixtures/gemini-effort.ts index 727d5b2..b72df94 100644 --- a/fixtures/gemini-effort.ts +++ b/fixtures/gemini-effort.ts @@ -8,12 +8,12 @@ import type { Effort, Payload } from "../external.ts"; * AGENT_OVERRIDE=gemini pnpm play gemini-effort.ts * * Effort levels: - * - "nothink": gemini-2.5-flash + LOW thinking - * - "think": gemini-2.5-flash + HIGH thinking + * - "mini": gemini-2.5-flash + LOW thinking + * - "auto": gemini-2.5-flash + HIGH thinking * - "max": gemini-2.5-pro + HIGH thinking */ -const efforts: Effort[] = ["nothink", "think", "max"]; +const efforts: Effort[] = ["mini", "auto", "max"]; export default efforts.map((effort) => ({ "~pullfrog": true, diff --git a/main.ts b/main.ts index 657e2ab..2efb87a 100644 --- a/main.ts +++ b/main.ts @@ -430,7 +430,7 @@ function parsePayload(inputs: Inputs): Payload { prompt: inputs.prompt, event: inputs.event as Payload["event"], modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox, disableProgressComment: inputs.disableProgressComment, comment_id: inputs.comment_id, @@ -445,10 +445,10 @@ function parsePayload(inputs: Inputs): Payload { if (!("~pullfrog" in parsedPrompt)) { throw new Error(); } - // internal invocation: use effort from payload, fallback to input, default to "think" + // internal invocation: use effort from payload, fallback to input, default to "auto" return { ...parsedPrompt, - effort: parsedPrompt.effort ?? inputs.effort ?? "think", + effort: parsedPrompt.effort ?? inputs.effort ?? "auto", } as Payload; } catch { // external invocation: use effort from input @@ -460,7 +460,7 @@ function parsePayload(inputs: Inputs): Payload { trigger: "unknown", }, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox, } as Payload; } @@ -519,7 +519,7 @@ function validateApiKey(params: { agent: Agent; owner: string; name: string }): } async function runAgent(ctx: AgentContext): Promise { - const effort = ctx.payload.effort ?? "think"; + const effort = ctx.payload.effort ?? "auto"; log.info(`Running ${ctx.agent.name} with effort=${effort}...`); // strip context from event - it's already available via MCP tools const { context: _context, ...eventWithoutContext } = ctx.payload.event; diff --git a/package.json b/package.json index 1ec3030..616ee44 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,13 @@ "dependencies": { "@actions/core": "^1.11.1", "@actions/github": "^6.0.1", - "@anthropic-ai/claude-agent-sdk": "0.1.77", + "@anthropic-ai/claude-agent-sdk": "0.2.7", "@ark/fs": "0.53.0", "@ark/util": "0.53.0", "@octokit/plugin-throttling": "^11.0.3", "@octokit/rest": "^22.0.0", "@octokit/webhooks-types": "^7.6.1", - "@openai/codex-sdk": "0.58.0", + "@openai/codex-sdk": "0.80.0", "@opencode-ai/sdk": "^1.0.143", "@standard-schema/spec": "1.0.0", "@toon-format/toon": "^1.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 36be51f..940ff7e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^6.0.1 version: 6.0.1 '@anthropic-ai/claude-agent-sdk': - specifier: 0.1.77 - version: 0.1.77(zod@4.3.5) + specifier: 0.2.7 + version: 0.2.7(zod@4.3.5) '@ark/fs': specifier: 0.53.0 version: 0.53.0 @@ -33,8 +33,8 @@ importers: specifier: ^7.6.1 version: 7.6.1 '@openai/codex-sdk': - specifier: 0.58.0 - version: 0.58.0 + specifier: 0.80.0 + version: 0.80.0 '@opencode-ai/sdk': specifier: ^1.0.143 version: 1.0.143 @@ -99,11 +99,11 @@ packages: '@actions/io@1.1.3': resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} - '@anthropic-ai/claude-agent-sdk@0.1.77': - resolution: {integrity: sha512-ZEjWQtkoB2MEY6K16DWMmF+8OhywAynH0m08V265cerbZ8xPD/2Ng2jPzbbO40mPeFSsMDJboShL+a3aObP0Jg==} + '@anthropic-ai/claude-agent-sdk@0.2.7': + resolution: {integrity: sha512-I1/zcnLah74kZeRkj/1QnDaC6ItJ2m/Bftlm25uoaRkZx7i7SkcpqM9jGE/r2A8PMxnw5WpabP60Xgj99CrTuw==} engines: {node: '>=18.0.0'} peerDependencies: - zod: ^3.25.0 || ^4.0.0 + zod: ^4.0.0 '@ark/fs@0.53.0': resolution: {integrity: sha512-XL0EbBAZgyy+j9aPhftYaBsbKAW5PTNSKCN6oLRRdrHuHPSAZgR6765/z0YZGhPxHEUNmq0vBoSk8yOLk91dNQ==} @@ -653,8 +653,8 @@ packages: '@octokit/webhooks-types@7.6.1': resolution: {integrity: sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==} - '@openai/codex-sdk@0.58.0': - resolution: {integrity: sha512-Z5vK294gUS9cn7bpU/lJtgzqJy1UqIGee7WMP+1Z4a6AxDcTxFCLZI4YkH9praJfrgoj5bFeu+3V9HIoBBTzcw==} + '@openai/codex-sdk@0.80.0': + resolution: {integrity: sha512-4+/bZOSjJAPsuM6yceQoVbNUK7UTS03QMKxCrFClObxD1j6n5oh7OSJniyff2MmF0DI7yHnf9omzfFL7RoLWnQ==} engines: {node: '>=18'} '@opencode-ai/sdk@1.0.143': @@ -1697,7 +1697,7 @@ snapshots: '@actions/io@1.1.3': {} - '@anthropic-ai/claude-agent-sdk@0.1.77(zod@4.3.5)': + '@anthropic-ai/claude-agent-sdk@0.2.7(zod@4.3.5)': dependencies: zod: 4.3.5 optionalDependencies: @@ -2101,7 +2101,7 @@ snapshots: '@octokit/webhooks-types@7.6.1': {} - '@openai/codex-sdk@0.58.0': {} + '@openai/codex-sdk@0.80.0': {} '@opencode-ai/sdk@1.0.143': {} diff --git a/run/action.yml b/run/action.yml index b374dc5..75be09b 100644 --- a/run/action.yml +++ b/run/action.yml @@ -13,9 +13,9 @@ inputs: description: "Prompt to send to the agent" required: true effort: - description: "Effort level: nothink (fast), think (default), max (most capable)" + description: "Effort level: mini (fast), auto (default), max (most capable)" required: false - default: "think" + default: "auto" agent: description: "Agent to use: claude, codex, gemini, cursor, opencode" required: false diff --git a/run/entry b/run/entry index 774d4de..0f94a8c 100755 --- a/run/entry +++ b/run/entry @@ -83424,7 +83424,7 @@ var schema = ark.schema; var define2 = ark.define; var declare = ark.declare; -// node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.77_zod@4.3.5/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs +// node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.2.7_zod@4.3.5/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs import { join as join5 } from "path"; import { fileURLToPath as fileURLToPath2 } from "url"; import { setMaxListeners } from "events"; @@ -90212,6 +90212,7 @@ function getInitialState() { } return { originalCwd: resolvedCwd, + projectRoot: resolvedCwd, totalCostUSD: 0, totalAPIDuration: 0, totalAPIDurationWithoutRetries: 0, @@ -90260,6 +90261,7 @@ function getInitialState() { inMemoryErrorLog: [], inlinePlugins: [], sessionBypassPermissionsMode: false, + sessionTrustAccepted: false, sessionPersistenceDisabled: false, hasExitedPlanMode: false, needsPlanModeExitAttachment: false, @@ -90272,25 +90274,14 @@ function getInitialState() { teleportedSessionInfo: null, invokedSkills: /* @__PURE__ */ new Map(), slowOperations: [], - sdkBetas: void 0 + sdkBetas: void 0, + mainThreadAgentType: void 0 }; } var STATE = getInitialState(); function getSessionId() { return STATE.sessionId; } -var MAX_SLOW_OPERATIONS = 10; -var SLOW_OPERATION_TTL_MS = 1e4; -function addSlowOperation(operation, durationMs) { - if (true) - return; - const now = Date.now(); - STATE.slowOperations = STATE.slowOperations.filter((op) => now - op.timestamp < SLOW_OPERATION_TTL_MS); - STATE.slowOperations.push({ operation, durationMs, timestamp: now }); - if (STATE.slowOperations.length > MAX_SLOW_OPERATIONS) { - STATE.slowOperations = STATE.slowOperations.slice(-MAX_SLOW_OPERATIONS); - } -} function createBufferedWriter({ writeFn, flushIntervalMs = 1e3, @@ -90362,9 +90353,7 @@ function withSlowLogging(operation, fn2) { return fn2(); } finally { const duration6 = performance.now() - startTime; - if (duration6 > SLOW_OPERATION_THRESHOLD_MS) { - logForDebugging(`[SLOW OPERATION DETECTED] ${operation} (${duration6.toFixed(1)}ms)`); - addSlowOperation(operation, duration6); + if (duration6 > SLOW_OPERATION_THRESHOLD_MS && false) { } } } @@ -90420,7 +90409,7 @@ function getDebugWriter() { } return debugWriter; } -function logForDebugging(message, { level } = { +function logForDebugging2(message, { level } = { level: "debug" }) { if (!shouldLogDebugMessage(message)) { @@ -90463,15 +90452,14 @@ var updateLatestDebugLogSymlink = memoize_default(() => { } catch { } }); +var isLoggingSlowOperation = false; function withSlowLogging2(operation, fn2) { const startTime = performance.now(); try { return fn2(); } finally { const duration6 = performance.now() - startTime; - if (duration6 > SLOW_OPERATION_THRESHOLD_MS) { - logForDebugging(`[SLOW OPERATION DETECTED] fs.${operation} (${duration6.toFixed(1)}ms)`); - addSlowOperation(`fs.${operation}`, duration6); + if (duration6 > SLOW_OPERATION_THRESHOLD_MS && !isLoggingSlowOperation && false) { } } } @@ -91254,7 +91242,7 @@ var Query = class { this.firstResultReceivedResolve(); } if (this.isSingleUserTurn) { - logForDebugging(`[Query.readMessages] First result received for single-turn query, closing stdin`); + logForDebugging2(`[Query.readMessages] First result received for single-turn query, closing stdin`); this.transport.endInput(); } } @@ -91498,23 +91486,23 @@ var Query = class { return (await this.initialization).account; } async streamInput(stream) { - logForDebugging(`[Query.streamInput] Starting to process input stream`); + logForDebugging2(`[Query.streamInput] Starting to process input stream`); try { let messageCount = 0; for await (const message of stream) { messageCount++; - logForDebugging(`[Query.streamInput] Processing message ${messageCount}: ${message.type}`); + logForDebugging2(`[Query.streamInput] Processing message ${messageCount}: ${message.type}`); if (this.abortController?.signal.aborted) break; await Promise.resolve(this.transport.write(jsonStringify(message) + ` `)); } - logForDebugging(`[Query.streamInput] Finished processing ${messageCount} messages from input stream`); + logForDebugging2(`[Query.streamInput] Finished processing ${messageCount} messages from input stream`); if (messageCount > 0 && this.hasBidirectionalNeeds()) { - logForDebugging(`[Query.streamInput] Has bidirectional needs, waiting for first result`); + logForDebugging2(`[Query.streamInput] Has bidirectional needs, waiting for first result`); await this.waitForFirstResult(); } - logForDebugging(`[Query] Calling transport.endInput() to close stdin to CLI process`); + logForDebugging2(`[Query] Calling transport.endInput() to close stdin to CLI process`); this.transport.endInput(); } catch (error50) { if (!(error50 instanceof AbortError)) { @@ -91524,7 +91512,7 @@ var Query = class { } waitForFirstResult() { if (this.firstResultReceived) { - logForDebugging(`[Query.waitForFirstResult] Result already received, returning immediately`); + logForDebugging2(`[Query.waitForFirstResult] Result already received, returning immediately`); return Promise.resolve(); } return new Promise((resolve2) => { @@ -99836,7 +99824,7 @@ function query({ const dirname2 = join5(filename, ".."); pathToClaudeCodeExecutable = join5(dirname2, "cli.js"); } - process.env.CLAUDE_AGENT_SDK_VERSION = "0.1.77"; + process.env.CLAUDE_AGENT_SDK_VERSION = "0.2.7"; const { abortController = createAbortController(), additionalDirectories = [], @@ -99992,13 +99980,13 @@ var package_default = { dependencies: { "@actions/core": "^1.11.1", "@actions/github": "^6.0.1", - "@anthropic-ai/claude-agent-sdk": "0.1.77", + "@anthropic-ai/claude-agent-sdk": "0.2.7", "@ark/fs": "0.53.0", "@ark/util": "0.53.0", "@octokit/plugin-throttling": "^11.0.3", "@octokit/rest": "^22.0.0", "@octokit/webhooks-types": "^7.6.1", - "@openai/codex-sdk": "0.58.0", + "@openai/codex-sdk": "0.80.0", "@opencode-ai/sdk": "^1.0.143", "@standard-schema/spec": "1.0.0", "@toon-format/toon": "^1.0.0", @@ -100342,7 +100330,7 @@ var agentsManifest = { } }; var AgentName = type.enumerated(...Object.keys(agentsManifest)); -var Effort = type.enumerated("nothink", "think", "max"); +var Effort = type.enumerated("mini", "auto", "max"); // modes.ts var ModeSchema = type({ @@ -104740,8 +104728,8 @@ var agent = (input) => { // agents/claude.ts var claudeEffortModels = { - nothink: "haiku", - think: "opusplan", + mini: "haiku", + auto: "opusplan", max: "opus" }; var claude = agent({ @@ -104887,7 +104875,7 @@ var messageHandlers = { import { mkdirSync as mkdirSync3, writeFileSync } from "node:fs"; import { join as join6 } from "node:path"; -// node_modules/.pnpm/@openai+codex-sdk@0.58.0/node_modules/@openai/codex-sdk/dist/index.js +// node_modules/.pnpm/@openai+codex-sdk@0.80.0/node_modules/@openai/codex-sdk/dist/index.js import { promises as fs2 } from "fs"; import os from "os"; import path from "path"; @@ -104958,9 +104946,11 @@ var Thread = class { skipGitRepoCheck: options?.skipGitRepoCheck, outputSchemaFile: schemaPath, modelReasoningEffort: options?.modelReasoningEffort, + signal: turnOptions.signal, networkAccessEnabled: options?.networkAccessEnabled, webSearchEnabled: options?.webSearchEnabled, - approvalPolicy: options?.approvalPolicy + approvalPolicy: options?.approvalPolicy, + additionalDirectories: options?.additionalDirectories }); try { for await (const item of generator) { @@ -105024,8 +105014,10 @@ var INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE"; var TYPESCRIPT_SDK_ORIGINATOR = "codex_sdk_ts"; var CodexExec = class { executablePath; - constructor(executablePath = null) { + envOverride; + constructor(executablePath = null, env3) { this.executablePath = executablePath || findCodexPath(); + this.envOverride = env3; } async *run(args3) { const commandArgs = ["exec", "--experimental-json"]; @@ -105038,6 +105030,11 @@ var CodexExec = class { if (args3.workingDirectory) { commandArgs.push("--cd", args3.workingDirectory); } + if (args3.additionalDirectories?.length) { + for (const dir of args3.additionalDirectories) { + commandArgs.push("--add-dir", dir); + } + } if (args3.skipGitRepoCheck) { commandArgs.push("--skip-git-repo-check"); } @@ -105048,7 +105045,10 @@ var CodexExec = class { commandArgs.push("--config", `model_reasoning_effort="${args3.modelReasoningEffort}"`); } if (args3.networkAccessEnabled !== void 0) { - commandArgs.push("--config", `sandbox_workspace_write.network_access=${args3.networkAccessEnabled}`); + commandArgs.push( + "--config", + `sandbox_workspace_write.network_access=${args3.networkAccessEnabled}` + ); } if (args3.webSearchEnabled !== void 0) { commandArgs.push("--config", `features.web_search_request=${args3.webSearchEnabled}`); @@ -105064,9 +105064,16 @@ var CodexExec = class { if (args3.threadId) { commandArgs.push("resume", args3.threadId); } - const env3 = { - ...process.env - }; + const env3 = {}; + if (this.envOverride) { + Object.assign(env3, this.envOverride); + } else { + for (const [key, value2] of Object.entries(process.env)) { + if (value2 !== void 0) { + env3[key] = value2; + } + } + } if (!env3[INTERNAL_ORIGINATOR_ENV]) { env3[INTERNAL_ORIGINATOR_ENV] = TYPESCRIPT_SDK_ORIGINATOR; } @@ -105077,7 +105084,8 @@ var CodexExec = class { env3.CODEX_API_KEY = args3.apiKey; } const child = spawn2(this.executablePath, commandArgs, { - env: env3 + env: env3, + signal: args3.signal }); let spawnError = null; child.once("error", (err) => spawnError = err); @@ -105097,6 +105105,13 @@ var CodexExec = class { stderrChunks.push(data); }); } + const exitPromise = new Promise( + (resolve2) => { + child.once("exit", (code, signal) => { + resolve2({ code, signal }); + }); + } + ); const rl = readline.createInterface({ input: child.stdout, crlfDelay: Infinity @@ -105105,20 +105120,13 @@ var CodexExec = class { for await (const line of rl) { yield line; } - const exitCode = new Promise((resolve2, reject) => { - child.once("exit", (code) => { - if (code === 0) { - resolve2(code); - } else { - const stderrBuffer = Buffer.concat(stderrChunks); - reject( - new Error(`Codex Exec exited with code ${code}: ${stderrBuffer.toString("utf8")}`) - ); - } - }); - }); if (spawnError) throw spawnError; - await exitCode; + const { code, signal } = await exitPromise; + if (code !== 0 || signal) { + const stderrBuffer = Buffer.concat(stderrChunks); + const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`; + throw new Error(`Codex Exec exited with ${detail}: ${stderrBuffer.toString("utf8")}`); + } } finally { rl.close(); child.removeAllListeners(); @@ -105188,7 +105196,7 @@ var Codex = class { exec; options; constructor(options = {}) { - this.exec = new CodexExec(options.codexPathOverride); + this.exec = new CodexExec(options.codexPathOverride, options.env); this.options = options; } /** @@ -105212,13 +105220,15 @@ var Codex = class { // agents/codex.ts var codexModel = { - nothink: "gpt-5.1-codex-mini", - think: "gpt-5.1-codex", + mini: "gpt-5.1-codex-mini", + // https://developers.openai.com/codex/models/ + // gpt-5.2-codex is not yet available via api key (even through codex cli) + auto: "gpt-5.1-codex", max: "gpt-5.1-codex-max" }; var codexReasoningEffort = { - nothink: "low", - think: void 0, + mini: "low", + auto: void 0, // use default max: "high" }; @@ -105416,9 +105426,9 @@ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as rea import { homedir as homedir2 } from "node:os"; import { join as join7 } from "node:path"; var cursorEffortModels = { - nothink: null, + mini: null, // use default (auto) - think: null, + auto: null, // use default (auto) max: "opus-4.5-thinking" }; @@ -105727,9 +105737,13 @@ async function spawn4(options) { // agents/gemini.ts var geminiEffortConfig = { - nothink: { model: "gemini-2.5-flash", thinkingLevel: "LOW" }, - think: { model: "gemini-2.5-flash", thinkingLevel: "HIGH" }, - max: { model: "gemini-2.5-pro", thinkingLevel: "HIGH" } + // https://ai.google.dev/gemini-api/docs/models + // the docs mention needing to enable preview features for these models but if you + // pass the model directly it works if we ever did need to do something like this, + // we could write to .gemini/settings.json + mini: { model: "gemini-3-flash-preview", thinkingLevel: "LOW" }, + auto: { model: "gemini-3-flash-preview", thinkingLevel: "HIGH" }, + max: { model: "gemini-3-pro-preview", thinkingLevel: "HIGH" } }; var assistantMessageBuffer = ""; var messageHandlers3 = { @@ -138688,7 +138702,7 @@ function parsePayload(inputs) { prompt: inputs.prompt, event: inputs.event, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox, disableProgressComment: inputs.disableProgressComment, comment_id: inputs.comment_id, @@ -138703,7 +138717,7 @@ function parsePayload(inputs) { } return { ...parsedPrompt, - effort: parsedPrompt.effort ?? inputs.effort ?? "think" + effort: parsedPrompt.effort ?? inputs.effort ?? "auto" }; } catch { return { @@ -138714,7 +138728,7 @@ function parsePayload(inputs) { trigger: "unknown" }, modes: inputs.modes ?? modes, - effort: inputs.effort ?? "think", + effort: inputs.effort ?? "auto", sandbox: inputs.sandbox }; } @@ -138761,7 +138775,7 @@ function validateApiKey(params) { }; } async function runAgent(ctx) { - const effort = ctx.payload.effort ?? "think"; + const effort = ctx.payload.effort ?? "auto"; log.info(`Running ${ctx.agent.name} with effort=${effort}...`); const { context: _context, ...eventWithoutContext } = ctx.payload.event; const promptContent = `${ctx.payload.prompt} @@ -138804,7 +138818,7 @@ async function run() { try { const inputs = Inputs.assert({ prompt: core4.getInput("prompt", { required: true }), - effort: core4.getInput("effort") || "think", + effort: core4.getInput("effort") || "auto", agent: core4.getInput("agent") || null, sandbox: core4.getInput("sandbox") === "true" ? true : void 0, cwd: core4.getInput("cwd") || null diff --git a/run/entry.ts b/run/entry.ts index ed8c488..ecee557 100644 --- a/run/entry.ts +++ b/run/entry.ts @@ -11,7 +11,7 @@ async function run(): Promise { try { const inputs = Inputs.assert({ prompt: core.getInput("prompt", { required: true }), - effort: core.getInput("effort") || "think", + effort: core.getInput("effort") || "auto", agent: core.getInput("agent") || null, sandbox: core.getInput("sandbox") === "true" ? true : undefined, cwd: core.getInput("cwd") || null,