feat(delegate-task): emit subagent_type enum when subagent list is known#3719
feat(delegate-task): emit subagent_type enum when subagent list is known#3719WarGloom wants to merge 1 commit intocode-yeongyu:devfrom
Conversation
|
Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement (CLA). To sign the CLA, please comment on this PR with: This is a one-time requirement. Once signed, all your future contributions will be automatically accepted. I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3633c836c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
7 issues found across 144 files
Confidence score: 3/5
- There is some meaningful regression risk here: several medium-severity, high-confidence findings (6/10 with 8–9/10 confidence) indicate concrete runtime behavior issues rather than just style or cleanup concerns.
- In
src/hooks/compaction-context-injector/recovery.ts, exceptions in thecatchpath do not incrementconsecutiveRecoveryFailures, so the intended consecutive-failure cutoff can be bypassed and recovery loops may persist longer than expected. - Multiple config/capability mismatches could surface user-facing failures:
src/config/schema/experimental.tsallows empty advisor identifiers,src/shared/model-capabilities/supplemental-entries.tssetsgpt-5.5output above provider limits, andsrc/shared/serena-availability.tsmay mis-detect Opencode/JSONC availability. - Pay close attention to
src/hooks/compaction-context-injector/recovery.ts,src/config/schema/experimental.ts,src/shared/model-capabilities/supplemental-entries.ts, andsrc/shared/serena-availability.ts- these paths carry the highest likelihood of functional misbehavior at runtime.
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed. cubic prioritises the most important files to review.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/hooks/compaction-context-injector/recovery.ts">
<violation number="1" location="src/hooks/compaction-context-injector/recovery.ts:51">
P2: Exception failures bypass the new consecutive-failure cutoff because the `catch` path does not increment `consecutiveRecoveryFailures`.</violation>
</file>
<file name="src/cli/run/agent-profile-colors.ts">
<violation number="1" location="src/cli/run/agent-profile-colors.ts:19">
P2: Timeout cleanup runs only on the success path; a fast rejection leaves the timer pending until it fires.</violation>
</file>
<file name="src/config/schema/experimental.ts">
<violation number="1" location="src/config/schema/experimental.ts:6">
P2: New advisor schema accepts empty strings for model/agent identifiers, allowing invalid values to propagate into routing and advisor option construction.</violation>
</file>
<file name="src/shared/model-capabilities/supplemental-entries.ts">
<violation number="1" location="src/shared/model-capabilities/supplemental-entries.ts:33">
P2: `gpt-5.5` max output is configured above documented provider limit (130,000 vs 128,000), which can cause oversized requests and runtime API failures.</violation>
</file>
<file name="src/plugin/tool-registry.ts">
<violation number="1" location="src/plugin/tool-registry.ts:207">
P2: `availableSubagentNames` is built from unsorted discovered agent sources, so subagent enum/list ordering can vary between runs. Sort the final names list to keep tool schema output deterministic.</violation>
</file>
<file name="src/shared/serena-availability.ts">
<violation number="1" location="src/shared/serena-availability.ts:20">
P2: Custom agent: **Opencode Compatibility**
`.jsonc` configs are treated as candidates but parsed with `JSON.parse`, so valid OpenCode JSONC files can be silently ignored.</violation>
<violation number="2" location="src/shared/serena-availability.ts:22">
P2: Custom agent: **Opencode Compatibility**
Serena availability detection is based only on MCP key presence and ignores Opencode MCP disable semantics (e.g., `enabled: false`), causing false positives versus actual Opencode behavior.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| } from "./recovery-prompt-config" | ||
| import { validateCheckpointModel } from "./validated-model" | ||
| import { | ||
| resolveLatestSessionPromptConfig, |
There was a problem hiding this comment.
P2: Exception failures bypass the new consecutive-failure cutoff because the catch path does not increment consecutiveRecoveryFailures.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/compaction-context-injector/recovery.ts, line 51:
<comment>Exception failures bypass the new consecutive-failure cutoff because the `catch` path does not increment `consecutiveRecoveryFailures`.</comment>
<file context>
@@ -41,7 +41,18 @@ export function createRecoveryLogic(
+ return false
+ }
+
+ if (tailState.consecutiveRecoveryFailures >= MAX_CONSECUTIVE_RECOVERY_FAILURES) {
+ log(`[compaction-context-injector] Skipping recovery after ${tailState.consecutiveRecoveryFailures} consecutive failures`, {
+ sessionID,
</file context>
d3633c8 to
12e0a81
Compare
Builds the `task` tool argument `subagent_type` as a `zod.enum(...)` when the runtime can enumerate available subagents, instead of a free-form string. Falls back to plain string when no list is available, preserving current behavior. - New optional `availableSubagentNames?: readonly string[]` field on `DelegateTaskToolOptions`. - `createDelegateTask` builds its args schema dynamically: - non-empty list → `tool.schema.enum(names).optional()` - empty / undefined → existing `tool.schema.string().optional()`. - `tool-registry.ts` runs `mergeWithClaudeCodeAgents([], ctx.directory)` and forwards filtered subagent names (mode === "subagent" | "all" | undefined) to `createDelegateTask`. - 3 new schema tests covering the enum-on, enum-empty, and missing cases. Net effect: the JSON Schema sent to the model carries an `enum` for `subagent_type`, which is the canonical place every standard tooling pipeline (validators, proxies, harness adapters, observability tools) already knows how to read. Description text and execution path are unchanged.
12e0a81 to
f142b13
Compare
Review statusIn-scope (this PR's diff) — addressed in
|
|
Hi @WarGloom, thanks for your contribution! This PR is being closed because the CLA check has been failing and the PR has been inactive for 7+ days. The CLA is a requirement for all contributions to this project. To resolve this:
If you believe this was closed in error, feel free to comment and we'll take another look. Thanks again for your time and contribution! |
Summary
tasktool argumentsubagent_typeas azod.enum(...)when the runtime can enumerate available subagents, instead of a free-form string.Changes
DelegateTaskToolOptions:availableSubagentNames?: readonly string[].createDelegateTaskbuilds its args schema dynamically:tool.schema.enum(names).optional().describe(...)tool.schema.string().optional().describe(...)tool-registry.tsplumbs the discovery: union ofBUILTIN_SUBAGENT_TYPES+ agents fromloadUserAgents,loadProjectAgents,loadOpencodeGlobalAgents,loadOpencodeProjectAgents,readOpencodeConfigAgents. Filters bymode === "subagent" | "all" | undefined. Removes entries listed inpluginConfig.disabled_agents. Deduplicated.The description text, runtime branches, category resolution, and execution paths are unchanged.
Motivation
Today
subagent_typeistool.schema.string().optional(). The resulting JSON Schema only carries{"type":"string"}— there is no machine-readable list of valid agent names anywhere in the tool definition. Downstream consumers that do not parse the description text (LLM proxies, validators, harness adapters, observability tools) cannot discover the user's configured subagents.JSON Schema's
enumis the canonical place to declare a closed set of string values, and it is what every standard tooling pipeline already understands.Backward compatibility
availableSubagentNamesis omitted or empty, the schema is byte-identical to before.category,subagent_type, andtask_idruntime branches in the tool body are untouched.Testing
bun run typecheck bun test src/tools/delegate-task/task-schema.test.ts3 new tests:
availableSubagentNames→subagent_typestays plain string.availableSubagentNames: ["oracle", "librarian", "dev"]→subagent_typeis enum and contains those names.Token impact
Each agent name adds ~3-5 input tokens to the tool definition. The tool definition lives in the cached prompt prefix, so the cost is paid once and amortizes to near-zero across a session.
Why this matters
Without an enum on
subagent_type, any harness sitting between OpenCode and the model has to parse natural-language description text to discover the agent list — fragile and version-dependent. With it, the canonical JSON Schema field carries the list, which is what every standard tooling pipeline already knows how to consume.Need help on this PR? Tag
@codesmithwith what you need.Summary by cubic
Makes
task.subagent_typea constrained enum when the runtime knows available subagents, improving validation and tooling. Falls back to a plain string when unknown; the registry now discovers, filters, and passes subagent names.zod.enum(...)forsubagent_typewhenavailableSubagentNamesis non-empty; otherwise use a string.loadUserAgents,loadProjectAgents,loadOpencodeGlobalAgents,loadOpencodeProjectAgents,readOpencodeConfigAgents, andloadAgentDefinitions. RespectpluginConfig.claude_code?.agents, filter bymode, excludepluginConfig.disabled_agents, dedupe/sort, and pass viaavailableSubagentNamestocreateDelegateTask.availableSubagentNames?: readonly string[]toDelegateTaskToolOptions; add tests for enum, empty, and missing cases.Written for commit f142b13. Summary will update on new commits. Review in cubic