fix: upgrade turbo to 2.6.1 and fix pre-push hook hangs (PRD-5356)#951
Conversation
- Automatically detect server URL from request headers (x-forwarded-host, x-forwarded-proto, host) - Fallback to existing AGENTS_MANAGE_API_URL and AGENTS_RUN_API_URL environment variables - Enables valid OpenAPI specs with correct server URLs in deployed environments
- Upgrade turbo from ^2.5.5 to ^2.6.1 - Add timeout detection (5 minutes) to pre-push hook - Automatically clear turbo cache and retry on timeout - Improve error handling and process group termination - Fix clean:turbo command (was using non-existent turbo clean) - Add explicit outputs to check:husky task in turbo.json Fixes PRD-5356
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @amikofalvy's task —— View job PR Review: Turbo Upgrade and Pre-Push Hook ImprovementsTodo List:
Review SummaryThis PR addresses a critical developer experience issue by upgrading Turbo and implementing robust timeout handling in the pre-push hook. The changes are well-architected and follow defensive programming principles. 🟢 What Works WellTurbo Upgrade (2.5.5 → 2.6.1)
Pre-Push Hook Improvements
🟡 Areas for ConsiderationCritical: Process Group ManagementIssue: Lines 70-84 in .husky/pre-push have a potential race condition if [ -n "$pgid" ] && [ "$pgid" != "1" ]; then
kill -TERM -$pgid 2>/dev/null || kill $cmd_pid 2>/dev/null || trueRisk: If Recommendation: Add additional validation: if [ -n "$pgid" ] && [ "$pgid" != "1" ] && [ "$pgid" != "" ]; then
kill -TERM "-$pgid" 2>/dev/null || kill $cmd_pid 2>/dev/null || trueSecurity: Process Termination ScopeConcern: The process group termination ( Recommendation: Consider adding a safeguard to verify the process group contains only expected processes before termination. System Design: Timeout ConfigurationCurrent: Hard-coded 5-minute timeout and single retry TIMEOUT_SECONDS=${TURBO_TIMEOUT:-300}
RETRY_COUNT=${TURBO_RETRY_COUNT:-1}🔴 Required ActionsChangeset MissingThe changeset-bot indicates no changeset was created. This is a patch-level change that should include:
Testing GapsMissing: No automated tests for the new timeout/retry logic 🏗️ Architectural ConsiderationsConsistency with Existing Patterns
ExtensibilityThe timeout/retry framework could be extracted into a reusable utility function for other long-running commands in the codebase. Performance Impact
🎯 RecommendationsHigh Priority
Medium Priority
Low Priority
Overall AssessmentThis is a well-executed solution to a real developer pain point. The implementation shows good understanding of shell scripting best practices and defensive programming. The timeout/retry logic is sophisticated and the user experience improvements are excellent. The code quality is high with proper error handling, clear documentation, and thoughtful UX. The only significant concerns are the process group race condition and missing changeset. Recommendation: Approve with minor fixes for the process group handling and changeset addition. |
…ep#3305) * spec(agents-core): sub-agent output contract — decisions locked Locks D-A through D-F on specs/2026-05-12-sub-agent-output-contract/: - D-A: outputContract object on SubAgentConfig (Option B over flat allowText) - D-B: onViolation 'retry' default with retryBudget 1 - D-C: new output_contract jsonb column on sub_agents (additive migration) - D-D: per-invocation override deferred to Future Work (NG1) - D-E: inferred allowText:false default when any structured capability declared - D-F: stopWhen stays iteration-budget; structured-emission stop derived at runtime Cascade-resolves Q-E (streaming partial frames structurally prevented), Q-F (contract is per-config across A2A), Q-G (init-time validation). Status: Decisions locked — pending audit (Steps 6-7). No code changes. * spec: incorporate PR inkeep#951 review on sub-agent output contract Reverse D-E to explicit-only. allowText now defaults to true and allowText: false is an explicit author opt-in. The framework no longer infers it from declared capabilities, so the feature is purely additive. This resolves the review's D-E scope and deprecation-phase findings. Add FR10 for the transfer/delegate-only enforcement hole. hasStructuredOutput is derived from dataComponents alone, so violation detection was unreachable for transfer/delegate-only agents. A broadened hasContractEnforcement flag fixes it. Move the durable-workflow path into scope, define the ContractViolationError client error shape, retype requireTransfer to a string id, and correct the SubAgentApiInsertSchema citation. * spec: add requireArtifact to the output contract Add requireArtifact to OutputContract so a sub-agent can require an artifact component as its terminal output, alongside the existing requireComponent (data) and requireTransfer. Lock decision D-G: the require* fields cover terminal output shapes (data component, artifact component, transfer) and not workflow steps (delegate, tool call). Add FR11 for init-time validation and broaden FR4 so an unsatisfied require* field is a runtime violation routed through onViolation. Add a STOP_IF for the artifact-only-agent schema-injection caveat. * spec: widen FR10 enforcement flag for require* fields The hasContractEnforcement flag only fired for allowText: false or agents with data components. An allowText: true agent constrained solely by requireTransfer or requireArtifact would have its require* constraint silently unenforced. Widen the flag to also fire when any require* field is set. Also document that allowText and require* are orthogonal: allowText governs whether prose is permitted, require* mandates a terminal emission. allowText: true with requireComponent is a valid combination. * spec: clarify the two contract enforcement modes Make explicit that allowText: false is structural prevention (the schema drops the Text variant, so it cannot be violated) while the require* fields are detection-based (the framework inspects the emitted structured parts after generation and applies onViolation on a miss). The presence of a text part does not affect the require* check, which inspects structured parts rather than parsing prose. * spec: add plain-language summary section Add an unnumbered Summary at the top of SPEC.md giving a plain-language overview of the contract fields, the two enforcement modes, and the opt-in backwards-compatibility guarantee, so a reader is oriented before the dense numbered sections. Update the status line to D-A through D-G. * spec: incorporate claude re-review precision items The re-review (Approve with Suggestions) confirmed all five Major findings resolved. Take the remaining Minor/Consider items: - FR4 gains clause (c): an empty turn under allowText: false is a violation; resolves the open "is empty allowed" matrix cell. - New shadow path: structured output plus prelude text takes the structured-success path, text discarded, not a violation. - Fix the executionHandler catch citation (676-680 was a logger.warn); re-anchor to the iteration-loop try at 183 as a new catch branch. - Note that contract retries are inner to runGenerate. - requireTransfer accepts string or SubAgentInterface, normalized to id. - Enumerate the durable-path threading steps. - Document the two enforcement paths under allowText: false. * feat(agents-core,agents-sdk): output contract data layer Add the OutputContract type, Zod schema, DB column, and SDK field for the sub-agent output contract (spec specs/2026-05-12-sub-agent-output-contract). - agents-core: OutputContractSchema (looseObject, forward-compatible) and OutputContract type; output_contract jsonb column on sub_agents; SubAgentInsertSchema and the DAL upsert carry the field. - agents-sdk: OutputContract interface on SubAgentConfig; requireTransfer accepts a string id or a SubAgentInterface, normalized to the id on persist. - Drizzle migration 0021 adds output_contract (nullable). It also drops a stale default on webhook_destinations.headers, pre-existing schema drift on main that drizzle-kit swept into this migration. * feat(agents-api): output contract structural enforcement Wire the sub-agent output contract into the runtime structural-prevention path (spec FR2, FR3, FR10). - agent-types.ts: outputContract on AgentConfig; resolvedAllowText on AgentRunContext. - Agent.ts: resolve resolvedAllowText in the constructor and gate the synthetic Text data component on it (FR2) - allowText: false drops Text from the response schema. - model-config.ts: derive hasContractEnforcement (FR10) so the violation path reaches transfer/delegate-only and require-only agents. - generate.ts: set toolChoice 'required' for a transfer/delegate-only agent under allowText: false (FR3). - generateTaskHandler.ts and agentExecutionSteps.ts: thread outputContract from the sub-agent schema into both Agent construction paths. - New ContractViolationError class for the onViolation reject path. * feat(agents-api,agents-sdk): output contract violation handling Implement onViolation routing (FR4) and init-time validation (FR6/FR7/FR11). - generate.ts: detect a contract violation after generation (isContractViolation) and route through onViolation - 'warn' logs and surfaces fallback text, 'reject' and 'retry' throw ContractViolationError. OTel attributes agent.output_contract.{violated,policy_applied} are set. - executionHandler.ts: a ContractViolationError is surfaced as an error operation carrying the code CONTRACT_VIOLATION. - subAgent.ts: SubAgent.init() validates requireComponent / requireArtifact / requireTransfer against the declared components and transfers, throwing before persistence. The 'retry' policy currently rejects immediately (zero retries); the bounded retry re-invocation loop is a tracked follow-up. * test(agents-api,agents-sdk): output contract unit tests + changeset - isContractViolation detection matrix (allowText:false, requireComponent). - ContractViolationError structured fields. - SubAgent.init() fail-fast for undeclared requireComponent / requireArtifact / requireTransfer (FR6/FR7/FR11). - Changeset: minor bump for agents-core, agents-sdk, agents-api. * docs(spec): record output contract implementation status Note what landed on PR inkeep#951 (data layer, structural runtime, violation handling, init validation, unit tests) and what is a tracked follow-up (FR4 retry loop, integration suite, docs/cookbook). * refactor(agents-api): consolidate output contract logic, complete detection Extract all output-contract runtime logic into a dedicated agents/output-contract.ts module (thematic with model-config.ts): resolveAllowText, deriveContractEnforcement, resolveContractToolChoice, isContractViolation, enforceOutputContract. Agent.ts, model-config.ts, and generate.ts now delegate to it instead of inlining the logic. Complete the runtime violation detection (previously partial): - requireArtifact, via the ArtifactCreate_<name> data component. - requireTransfer, via the transfer_to_<id> tool call. - transfer/delegate-only agents emitting text instead of a tool call. Extract the ArtifactCreate_ data-component name prefix as a shared ARTIFACT_CREATE_PREFIX constant so the convention is single-sourced. * docs(spec): document requireArtifact create-only limit requireArtifact runtime detection is satisfied by creating the artifact (the ArtifactCreate_<name> data component), not by emitting a generic Artifact reference to a pre-existing artifact. The reference component does not carry the artifact type, so type-precise reference matching needs artifact-registry resolution and is recorded as Future Work. Also notes the recommended step-loop approach for the deferred retry. * spec: design the FR4 retry mechanism (D-H), defer implementation /spec pass on the output-contract retry loop. Source-verified ai@6.0.14's multi-step loop: the do/while continues only after a tool-call step and stopWhen can only stop early, never force continuation. The headline violation is a no-tool-call terminal step, so prepareStep/stopWhen cannot drive the retry. The retry must be a bounded outer re-invocation loop. Adds decision D-H, the retry design under §15 Future Work (Explored), and evidence/ai-sdk-loop-semantics.md. Implementation deferred to its own PR; onViolation:'retry' rejects immediately until then. * fix(agents-api): contract violation surfacing + CI test fixture CI fix: the new output_contract column makes SubAgentSelectSchema require the key; the schema-wrappers test fixture was missing it. Major (review): a ContractViolationError thrown from runGenerate is caught at the generation-wrapping boundary (generateTaskHandler standard path, agentExecutionSteps durable path), never at executionHandler, so the executionHandler instanceof branch was dead code. generateTaskHandler now sets a contract_violation A2ATaskErrorType on the failed result; agentExecutionSteps emits an SSE error op with CONTRACT_VIOLATION; the dead executionHandler branch is removed. Also: tests for enforceOutputContract / deriveContractEnforcement / resolveContractToolChoice; remove the JSDoc block (No Comments); warn log carries conversationId + policy; spec updated to the real mechanism. * fix(agents-api): update OpenAPI snapshot, resolve review inkeep#5 findings CI: the outputContract field changed the generated OpenAPI spec; the committed __snapshots__/openapi.json is regenerated. Full agents-core / agents-api / agents-sdk suites run clean. - enforceOutputContract throws and reports the effective policy (reject) rather than the misleading configured 'retry' + attemptedRetries 0, since retry rejects immediately until the retry loop lands (D-H). - generateTaskHandler's durable-approval catch no longer swallows a ContractViolationError that co-occurs with a pending approval. - Added the missing deriveContractEnforcement / resolveContractToolChoice / enforceOutputContract test cases (output-contract.test.ts now 26). * feat(agents-manage-ui): output contract section in the sub-agent editor Adds an Output contract section to the sub-agent editor so no-code builders can declare structured-only emission: - allowText as a "Structured output only" checkbox. - requireComponent / requireArtifact / requireTransfer inputs. - onViolation select offering Reject and Warn only - retry is not selectable while it rejects immediately (D-H), noted in the field description. retryBudget is omitted (meaningless without retry). The field round-trips through the existing spread-based form and full-agent upsert path. OutputContractFormSchema + form validation tests added; agents-manage-ui changeset. * docs(agents-docs): add the Output Contract SDK doc page New typescript-sdk/output-contract.mdx covering the contract fields, the two enforcement modes (structural allowText vs detection-based require*), onViolation, init-time validation, and the requireArtifact create-only / retry-deferred notes. Added to the typescript-sdk nav. Completes PR inkeep#951 as a full-stack change: SDK, core, DB, runtime, Manage UI, docs, tests, changesets. * fix(agents-manage-ui): cohesive Output section + dirty-state fix The bolted-on output-contract section made the sub-agent form spuriously dirty on load (apiToFormValues carried outputContract as the DB null, but the registered fields materialized it as an object), breaking the agent.cy.ts dirty-state E2E. - apiToFormValues normalizes outputContract to a consistent 6-key object and OutputContractFormSchema is a z.strictObject with z.preprocess null->undefined per field - mirroring how stopWhen is handled. - dataComponents, artifactComponents, and the contract are now one cohesive "Output" section instead of three independent peers. - requireComponent / requireArtifact / requireTransfer are selects driven by the declared components / transfer targets, not free-text inputs - removing the typo-to-init-error footgun. * fix(agents-manage-ui): serialize outputContract on save (BLOCKING) editorToPayload (the form->API serializer) never included outputContract in the sub-agent payload, so every contract configured through the UI was silently discarded on save. - editorToPayload now serializes outputContract via a buildOutputContract helper that drops unset/default fields (allowText kept only when false) and omits the contract when empty - mirroring the conditional stopWhen spread. 3 round-trip tests added to serialize.test.ts. - docs: output-contract.mdx onViolation type corrected to include 'retry' (the SDK type accepts it); added a "Handling a rejection" section on the contract_violation task type / CONTRACT_VIOLATION code. * refactor(agents-manage-ui): consolidate Output section into Guardrails modal Collapse the seven stacked controls in the sub-agent editor's Output section into a single modal behind a compact summary card, and rename the section to Guardrails. The modal holds the component and artifact pickers plus the contract rules (structured-only emission, require component/artifact/transfer, on-violation). Form fields edit the agent form live, consistent with the rest of the sidepane. * feat(agents): output contract require-all lists + spec amendment Amend the sub-agent output contract per spec decisions D-I and D-J. requireComponent and requireArtifact become string[] with require-all semantics: every named component or artifact must appear in the response. requireTransfer becomes a boolean, since a turn transfers exactly once and cannot name a target. Updates the agents-core OutputContractSchema, the SDK OutputContract type and SubAgent.init() validation, runtime violation detection in output-contract.ts, the OpenAPI snapshot, and the Guardrails editor (multi-select require rows, transfer toggle, "Text-free responses" rename). SPEC.md records D-I, D-J, and FR12. The FR12 prompt-injection surface is specced but not yet implemented. * feat(agents-api): surface output contract in the system prompt (FR12) Implements spec decision D-J. When a sub-agent has a resolved output contract, PromptConfig renders an <output_contract> section into the system prompt stating the active rules: no free-text narration when allowText is false, the required data components and artifacts, and a required transfer. The section is omitted entirely when no contract is set, so the common path pays no prompt-size cost. This is a prevention layer that steers the model on attempt 1; it complements, and does not replace, the runtime detection-and-retry in output-contract.ts. The resolved contract and resolvedAllowText thread from AgentRunContext through SystemPromptV1 into PromptConfig.assemble. * refactor(agents): dedup OutputContract type and contract helpers OutputContract was defined twice — a hand-written interface in the SDK and the Zod-inferred type in agents-core. After D-I made them field-identical, the SDK now re-exports the agents-core type so there is a single definition. Also collapses repetition in the contract code: a shared optionalContractBoolean preprocessor for allowText and requireTransfer in the form schema, and an allRequiredPresent helper for the two require-all checks in output-contract.ts. * feat(agents-manage-ui): require components via chip toggle in Guardrails Reworks the Guardrails modal so requirements are expressed on the inventory chips themselves instead of separate dropdowns. Clicking a selected component or artifact chip toggles whether it is required; required chips are highlighted in the primary color. The separate "Require component" / "Require artifact" selects are removed. The structured-output control becomes an "Include text" checkbox (checked by default) — unchecking it is the text-free contract. ComponentSelector and SelectedComponents gain two opt-in props (requiredComponents, onComponentClick) so the chip highlight and click behavior are additive — existing callers are unaffected. The two inventory fields are rendered from one config-driven map rather than duplicated blocks. * fix(agents-manage-ui): make the required-chip highlight solid The 10%-tint fill read as too subtle against the dark panel. A required chip now uses a solid primary fill so it is unmistakable. * fix(agents-manage-ui): required chip invisible in dark mode The code Badge variant carries dark:bg-muted/50; tailwind-merge keeps it alongside an unprefixed bg-primary, so in dark mode the required chip stayed grey and the dark primary-foreground text disappeared into it. Add dark:bg-primary to override the variant's dark background. * fix(agents-manage-ui): bolder required chip with a visible remove icon The ghost Button variant hard-codes text-muted-foreground, so the × stayed low-contrast grey on the solid primary chip. Required chips now use semibold text and force the × to the chip's foreground color. * fix(agents-core): persist sub-agent outputContract on full-agent save The full-agent upsert path builds each sub-agent's data field by field and never included outputContract, so every contract configured in the editor was silently dropped on save — the UI serialized it correctly but the DAL orchestrator discarded it. Pass outputContract through to upsertSubAgent. * fix(agents-core): return sub-agent outputContract on full-agent read getFullAgentDefinition rebuilds each sub-agent object field by field and omitted outputContract, so a saved contract was dropped on read-back even after the write path was fixed. Return it from the assembled sub-agent object. * fix(agents-core): persist outputContract on full-agent UPDATE path There are two full-agent server functions — createFullAgentServerSide and updateFullAgentServerSide — each with its own sub-agent loop. Commit b10c26d54 fixed the create loop; this fixes the update loop, which is the one editing an existing agent actually runs. Its upsertSubAgent call also omitted outputContract. * fix(agents-core): allow clearing a sub-agent outputContract Removing the last requirement (or the whole contract) sent no outputContract, so the full-agent update passed undefined to upsertSubAgent — and Drizzle's .set() skips undefined, leaving the old contract in the column. A contract could be set but never unset. Coerce the full-agent upsert to write null when the contract is absent, and make SubAgentInsertSchema.outputContract nullable to match the nullable column so null type-checks through the chain. * feat(agents-api): report which rule an output-contract violation broke The violation error said only "violated its output contract" — it never named the offending rule, so a failure was undiagnosable. Add getContractViolation, which returns a human-readable reason: which require* rule failed, what was expected, and what the response actually emitted (or that free text was disallowed). The reason is threaded into ContractViolationError's message, the warn log, and a span attribute. isContractViolation stays as a boolean wrapper. * fix(agents-core): drop require* entries for undeclared components A requirement could outlive the component it pointed at: delete a data component from a sub-agent and outputContract.requireComponent kept the stale name, leaving an unsatisfiable contract that rejected every turn. On full-agent save, reconcile each sub-agent's outputContract — drop requireComponent / requireArtifact entries that name a component or artifact the sub-agent no longer declares. This self-heals stale contracts (any re-save fixes them) and covers every removal path, not just the editor's in-modal prune. * refactor(agents-core): extract loadComponentNameMaps helper The component/artifact id-to-name map building was duplicated verbatim in both createFullAgentServerSide and updateFullAgentServerSide. Extract it into one helper, which also fetches the two lists in parallel rather than sequentially. * fix(agents-api): count marker-created artifacts toward requireArtifact requireArtifact only checked for the structured ArtifactCreate_<name> data component, so an artifact created via the <artifact:create> text marker — a first-class, supported path — was missed, and the contract rejected a turn that had genuinely produced the required artifact. getContractViolation now also recognizes <artifact:create> markers, reusing ArtifactParser's own parser (parseCreateAnnotations, exposed statically) rather than re-implementing the marker regex. * docs(spec): amend output-contract spec with D-K and D-L D-K — requireArtifact is satisfied by an artifact reference, not only creation; both the XML markers and the structured data-component forms count. Amends FR11, reverses the 2026-05-21 create-only call, promotes the type-precise reference-matching item out of Future Work. D-L — under allowText: false, artifacts emit as structured data components (ArtifactCreate_ / ArtifactReference) rather than the in-text XML markers. Adds FR13, resolves the open §16 STOP_IF about artifact-only agents having no text-free emission channel. * feat(agents-api): structured artifacts under allowText:false (D-L/FR13) An artifact-only sub-agent (artifactComponents, no dataComponents) had hasStructuredOutput=false, so it never entered structured-output mode and could only emit artifacts via the in-text <artifact:create> marker — which allowText:false excludes, leaving it no text-free channel. Broaden hasStructuredOutput: an artifact-only sub-agent with allowText:false now uses the structured schema, where schema-builder already injects the ArtifactCreate_/ArtifactReference variants. * feat(agents-api): requireArtifact counts references, not just creation (D-K) A requireArtifact entry is now satisfied when the response references an existing artifact, not only when it creates one — covering both the <artifact:ref> text marker and the structured Artifact reference component. A reference carries only an artifact id, resolved to a type against ctx.config.artifacts. Reuses ArtifactParser: a generic parseAttrs is extracted and a static parseRefIds added alongside parseCreateAnnotations, so the marker parse is not re-implemented. * feat: reject requireTransfer combined with requireComponent/requireArtifact (FR14) A transfer and a component/artifact are different terminal output shapes (D-G) — a turn ends one way, so requiring both is unsatisfiable. Reject the combination in two layers: an OutputContractSchema refine in agents-core (the API path) and validateOutputContract in agents-sdk (init-time fail-fast with a clear message). requireComponent + requireArtifact together stay valid. Amends the spec with FR14. * fix(agents-api): restore template file imports lost in FR12 The FR12 commit inlined the six prompt-template files as huge string constants so the {{OUTPUT_CONTRACT_SECTION}} placeholder could be added without touching system-prompt.xml. That left templates/v1/ as dead files diverged from the live source. Restore the ?raw imports and add the placeholder to system-prompt.xml so the template directory is the source of truth again. Also drop artifact-retrieval-guidance.xml, a pre-existing dead duplicate of the .md variant. * fix(agents): address PR review findings on output contract - output-contract.ts: include data-component artifacts (ArtifactCreate_<name>) in the requireArtifact violation diagnostic so the message no longer reports "produced [none]" when the artifact was created via the structured path. - selected-components.tsx: add aria-pressed to the chip toggle and an aria-label on the remove button so the chip's required state and remove affordance are exposed to assistive tech. - guardrails-section.tsx: drop "Retry is not yet available" from the on-violation description so the UI does not advertise an absent option. - validation.ts: align OutputContractFormSchema with core: looseObject for forward compatibility, nullish wrapper so API null round-trips, and retryBudget bounded with .int().nonnegative(). serialize.ts widens buildOutputContract to accept null alongside undefined. - agentFull.ts: skip the listDataComponents / listArtifactComponents pair when no sub-agent has an outputContract; reconcileOutputContract already early-returns null in that case so empty maps are safe. Export reconcileOutputContract for direct testing and drop the orphan stale JSDoc that was left above loadComponentNameMaps. * test(agents): cover reconcile + allowText reason and fix stale Agent assertions - agentFull.reconcileOutputContract.test.ts: new file with 7 tests covering the function's branches (null contract, retained/partial/full-drop for requireComponent and requireArtifact, allowText/onViolation pass-through, and an input-mutation guard). - output-contract.test.ts: add a getContractViolation test asserting the reason names allowText when free-text-only output violates allowText:false. - Agent.test.ts: update four buildSystemPrompt .toHaveBeenCalledWith assertions that pre-dated the FR12 / appPrompt additions and were already failing on this branch. * docs(spec): correct stale catch-site citation in §11 The §11 file list pointed at handlers/executionHandler.ts as the catch site for ContractViolationError, but that file does not reference the error. The standard-path catch lives in generateTaskHandler.ts (which maps it to a 'contract_violation' task failure); the durable-path catch in agentExecutionSteps.ts was already listed correctly on the next line. * fix(agents-api): tolerate NoObjectGeneratedError when the model transferred Agents that declare dataComponents set Output.object() on the AI SDK call, which forces every turn to emit a structured object. When such an agent transfers or delegates instead, the AI SDK rejects with NoObjectGenerated- Error and the run crashes — even though the transfer was the legitimate alternative the model was instructed to take (e.g. requireTransfer: true). resolveGenerationResponse now treats that specific rejection as "output is undefined" when the steps include a transfer_to_* or delegate_to_* tool call. Every other rejection (parse errors, schema mismatches, streaming faults, network errors) still throws. The thrown error is also reworked into a GenerationResponseError that leads with an action-oriented hint, preserves the original error as cause, and appends field / finishReason / toolCalls for triage. The hint varies by failure mode: - "no structured output, no transfer/delegate" -> points at outputContract.requireComponent and allowText:false as the way to enforce structured output. - "non-routing tool call but no object" -> points at removing dataComponents or routing via transfer/delegate. - "schema mismatch / parse failure" -> points at simplifying the schema or using a more capable model. - other fields rejecting -> calls out streaming/network/SDK fault. Adds tolerance tests for transfer + delegate, plus tests for each hint branch and for non-output-field failures. Existing tests updated to the new diagnostic format (field=X cause=Y). * test(agents-api): cover D-L/FR13, D-K edge cases, and parseRefIds Three coverage gaps surfaced in PR inkeep#951 review inkeep#18. model-config.hasStructuredOutput.test.ts (new): pins the D-L/FR13 branch in configureModelSettings — hasStructuredOutput becomes true for artifact-only sub-agents under allowText:false. Five tests cover both sides of the && and confirm the legacy dataComponents path still applies. Guards against a regression where the && becomes || or the resolvedAllowText check is dropped, which would silently route artifact-only agents to the wrong model. output-contract.test.ts: two new getContractViolation cases pin the D-K guards — a ref to an artifact id absent from ctx.config.artifacts and a structured Artifact data component with artifact_id: null should both still fail requireArtifact. The guards live at output-contract.ts:88-91 and would be easy to "broaden" by accident. ArtifactParser.parseRefIds.test.ts (new): six standalone tests for the D-K reference-detection regex — no refs, single ref (self-closing and non), multi-ref, missing id attribute, single-quoted attrs. The multi-ref case is the primary D-K use case (multiple citations in one response) and was previously only exercised indirectly with one ref. * test(agents-api): cover remaining hint/diagnostic branches from review inkeep#19 - resolveGenerationResponse.test.ts: add a test for the generic-output fallback hint (unrecognized error name → "See the cause for details"), plus a tolerance test using the bare NoObjectGeneratedError name to exercise the no-prefix branch of isNoObjectGeneratedError. - output-contract.test.ts: add a getContractViolation case asserting the requireArtifact diagnostic includes the produced artifact type after stripping the ArtifactCreate_ prefix; plus an enforceOutputContract case for explicit onViolation: "retry" (currently aliased to reject until D-H lands). - agent-types.ts: document why isNoObjectGeneratedError compares names by string rather than instanceof, and which AI SDK version supplies the current name set — so a future SDK upgrade triggers a review of this guard. * docs(agents-docs): align output-contract page with shipped behavior - Drop "retry" from documented onViolation values and remove the retryBudget row. Retry semantics are not implemented (the runtime aliases "retry" to "reject" today), so documenting them misleads users into thinking they get retries when they do not. onViolation is now documented as "reject" | "warn" defaulting to "reject". - Fix the stale requireArtifact note: D-K landed in this branch and reference paths (<artifact:ref> markers and structured Artifact data components) now satisfy requireArtifact alongside creation. - Document FR14: requireTransfer cannot be combined with requireComponent or requireArtifact. Mention it both in the field table and the Notes section so users do not stumble onto the validation error blind. - Update the rejection-handling paragraph to mention that error messages now include the specific rule that was violated (matches the ContractViolationError.message shape on this branch). - Add cross-links from the data-components and artifact-components SDK pages to the output-contract page so the discovery path "I declared a component; how do I make the model actually use it?" is one click. * docs(agents-docs): drop internal mechanism details from output-contract page The page is for SDK users; they shouldn't have to know about Output.object(), schema unions, "Text variants", artifact markers, or the artifact-id registry. Rewrite the two sections that leaked these: - Drop the "Two enforcement modes" section. The structural-vs-detection- based framing was an implementation distinction, not something a user acts on. Keep one sentence in its place clarifying that allowText and the require* fields are independent. - In Notes, rewrite the requireArtifact bullet to say "creating or referencing the named artifact" without naming the internal markers (<artifact:create>, <artifact:ref>) or data-component prefix (ArtifactCreate_). Users just declare the artifact component; the framework recognises both forms. - In Validation and Notes, replace "SubAgent.init()" and "the underlying schema" with "registration time" so the doc doesn't bind to internal function names. No behavior change. No schema change. * docs(agents-docs): nest output-contract under structured-outputs and link bidirectionally Placement: move output-contract.mdx into structured-outputs/ so the page lives in the section a reader is in when they discover the need for it. The page covers transfers and prose too, but every discovery path runs through declaring components/artifacts first, and the section nav now reads: data-components, artifact-components, status-updates, output-contract. Links: - output-contract field-table entries now link out to data-components, artifact-components, and agent-relationships so each require* field points at the concept it constrains. - data-components and artifact-components keep their "Enforcing X emission" sections but the link now resolves to the new nested URL. - agent-relationships gets a "Requiring a transfer" closing section pointing back at the output contract for the requireTransfer pattern, closing the loop from the transfer/delegate side. Nav metadata updated in both typescript-sdk/meta.json (output-contract removed from the top-level list) and structured-outputs/meta.json (output-contract added after status-updates). No content rewrites; pure structural + linking. GitOrigin-RevId: fbb40487628ce533955c1ee207755926057b75e1 Co-authored-by: tim-inkeep <132074086+tim-inkeep@users.noreply.github.com>
Summary
This PR upgrades turbo to 2.6.1 and implements automatic timeout detection and cache clearing in the pre-push hook to fix hangs that previously required manual terminal restarts and cache clearing.
Changes
^2.5.5to^2.6.1(latest stable)clean:turbocommand: Changed from non-existentturbo cleantorm -rf .turbooutputs: []tocheck:huskytaskHow It Works
pnpm check:huskywith timeout monitoringTesting
Related
Fixes PRD-5356