Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ import {
formatOpenCodeProviderErrorRetryNoticeText,
getOpenCodeProviderErrorRecovery,
isOpenCodeContextOverflowError,
isOpenCodeRetryableTransportError,
isOpenCodeTerminalProviderError,
resolveOpenCodeProviderErrorRetryDelayMs,
summarizeOpenCodeProviderError,
Expand Down Expand Up @@ -3995,6 +3996,7 @@ export class OpenCodeServerHarness
(isTerminalProviderError
? 'Provider request failed with a non-retryable error.'
: 'Provider retry limit exceeded.'),
!isTerminalProviderError && isOpenCodeRetryableTransportError(status),
);
return;
}
Expand Down Expand Up @@ -4073,6 +4075,7 @@ export class OpenCodeServerHarness
private async terminateOpenCodeProviderRetry(
sessionId: string,
message: string,
retryable: boolean,
): Promise<void> {
this.logger.error(
`OpenCode reported a terminal provider error as retryable sessionId=${sessionId}: ${message}`,
Expand Down Expand Up @@ -4100,7 +4103,7 @@ export class OpenCodeServerHarness
sessionID: sessionId,
error: {
name: 'APIError',
data: { message, isRetryable: false },
data: { message, isRetryable: retryable },
},
},
});
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type OpenCodeProviderErrorRecovery = {
// client-side before or instead of an HTTP response.
const TERMINAL_ERROR_NAMES = new Set(['contextoverflowerror']);
const POLICY_ERROR_NAMES = new Set(['contentfiltererror']);
const CONNECTION_RESET_MESSAGE = 'connection reset by server';

// Client errors are terminal because replaying the same request cannot
// succeed, except timeouts (408) and rate limits (429) which are transient.
Expand Down Expand Up @@ -134,6 +135,12 @@ export function isOpenCodeContextOverflowError(error: unknown): boolean {
return hasErrorName(collectProviderErrorValues(error), TERMINAL_ERROR_NAMES);
}

export function isOpenCodeRetryableTransportError(error: unknown): boolean {
return collectProviderErrorValues(error).some(
(value) => normalizeIdentifier(value) === CONNECTION_RESET_MESSAGE,
);
}

function isExplicitlyTerminal(values: unknown[]): boolean {
if (values.some((value) => asRecord(value)?.isRetryable === false)) {
return true;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ ${emailCadenceGuidance}- Prefer one direct closeout over an acknowledgement foll
- Do not offer or schedule checks that duplicate existing task, PR lifecycle/review, or other notifications and monitors. Offer at most once for the same unresolved outcome; do not repeat an ignored or declined offer or append boilerplate after every fix or update. Do not make proactive offers on automation or scheduled-wakeup turns. Presentation-only events remain presentation-only: do not inspect or schedule from them. This is conversation-scoped follow-up, not an offer to save work as a deployment automation; the automation rule against pitching one-off fixes does not suppress an otherwise eligible check of a deployed fix's unresolved observable outcome.

## Own Coding Task Follow-Through
- After "launch_task" successfully creates a coding task for a human-authored request, use "manage_wakeups" before the closeout to list active wakeups and silently ensure this conversation has exactly one session-wide one-shot check with name "Follow through on session tasks", prompt "Run the Own Coding Task Follow-Through session check for all tasks in this conversation. Follow that system policy exactly, including inspection, reporting, correction, stopping, and rearming.", schedule "in 10m", reportPolicy "only_when_notable", and internal true. Reuse an equivalent active check instead of creating another. This is authorized follow-through on your own work, not external-process monitoring, so do not ask for monitoring consent. Do not schedule after a failed launch. The name and prompt are intentionally task-independent so concurrent or successive launches deduplicate to one monitor for the Session.
- After "launch_task" successfully creates a coding task for a human-authored request, the runtime silently ensures this conversation has exactly one internal session-wide one-shot check for Own Coding Task Follow-Through. Do not create another wakeup for this purpose. This is authorized follow-through on your own work, not external-process monitoring, so do not ask for monitoring consent. Failed launches do not schedule follow-through.
- Do not mention this automatic monitor, its setup, cadence, or next run in the acknowledgement or closeout. This exception overrides generic wakeup-creation confirmation instructions only for automatic own-task follow-through; continue to confirm reminders and monitoring that the user requested.
- On that session check, inspect every task currently listed in this prompt as active or resumable for this conversation: get each current summary and recent messages, then compare the evidence with the user's goals and accepted instructions in this conversation. Count a task as still running only when current evidence shows it is booting or actively executing. A task that is stopped, waiting for input, completed, failed, canceled, or merely resumable does not keep the monitor alive. Never treat an inspection failure or missing evidence as success; report a concise capability blocker when useful, do not rearm, and stop the monitor on capability loss.
- When concrete evidence shows drift, a missed requirement, or an actionable blocker a running task can resolve within the accepted scope, use "send_task_message" to send one specific corrective instruction to that task, naming the evidence and expected correction. Before sending, verify the same correction is not already queued, accepted, recorded, addressed, or superseded. Do not steer on silence alone, invent progress or problems, expand scope, or reactivate stopped, waiting, finished, failed, or canceled work.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import packageJson from '../../../../../package.json';

import { appendAttachmentTextsToPromptText } from '../../file-attachments';
import {
ensureOwnTaskFollowThroughWakeup,
handleManageWakeupsToolCall,
normalizeManageWakeupsArgs,
} from '../session-wakeups';
Expand Down Expand Up @@ -4118,6 +4119,18 @@ export async function answerFastAgentQuestion({
}
if (result.success) {
currentTasks.set(result.taskId, { taskId: result.taskId });
if (substantiveHumanInput) {
try {
await ensureOwnTaskFollowThroughWakeup({
conversationId: session.id,
userId,
});
} catch (error) {
console.warn(
`[Fast Agent] Failed to schedule own-task follow-through after launch: ${formatErrorForLog(error)}`,
);
}
}
if (result.kickoffDelivered) {
visibleUpdatePosted = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export {
export {
cancelSessionWakeupForConversation,
createSessionWakeup,
ensureOwnTaskFollowThroughWakeup,
getSessionWakeupForConversation,
handleManageWakeupsToolCall,
listSessionWakeupsForConversation,
Expand Down
39 changes: 24 additions & 15 deletions packages/cloud-agents/src/server/session-wakeups/service.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading