export type SessionState = 'idle' | 'running' | 'requires_action'/*** Context carried with requires_action transitions so downstream* surfaces (CCR sidebar, push notifications) can show what the* session is blocked on, not just that it's blocked.** Two delivery paths:* - tool_name + action_description → RequiresActionDetails proto* (webhook payload, typed, logged in Datadog)* - full object → external_metadata.pending_action (queryable JSON* on the Session, lets the frontend iterate on shape without* proto round-trips)*/export type RequiresActionDetails = {tool_name: string/** Human-readable summary, e.g. "Editing src/foo.ts", "Running npm test" */action_description: stringtool_use_id: stringrequest_id: string/** Raw tool input — the frontend reads from external_metadata.pending_action.input* to parse question options / plan content without scanning the event stream. */input?: Record<string, unknown>}import { isEnvTruthy } from './envUtils.js'import type { PermissionMode } from './permissions/PermissionMode.js'import { enqueueSdkEvent } from './sdkEventQueue.js'// CCR external_metadata keys — push in onChangeAppState, restore in// externalMetadataToAppState.export type SessionExternalMetadata = {permission_mode?: string | nullis_ultraplan_mode?: boolean | nullmodel?: string | nullpending_action?: RequiresActionDetails | null// Opaque — typed at the emit site. Importing PostTurnSummaryOutput here// would leak the import path string into sdk.d.ts via agentSdkBridge's// re-export of SessionState.post_turn_summary?: unknown// Mid-turn progress line from the forked-agent summarizer — fires every// ~5 steps / 2min so long-running turns still surface "what's happening// right now" before post_turn_summary arrives.task_summary?: string | null}type SessionStateChangedListener = (state: SessionState,details?: RequiresActionDetails,) => voidtype SessionMetadataChangedListener = (metadata: SessionExternalMetadata,) => voidtype PermissionModeChangedListener = (mode: PermissionMode) => voidlet stateListener: SessionStateChangedListener | null = nulllet metadataListener: SessionMetadataChangedListener | null = nulllet permissionModeListener: PermissionModeChangedListener | null = nullexport function setSessionStateChangedListener(cb: SessionStateChangedListener | null,): void {stateListener = cb}export function setSessionMetadataChangedListener(cb: SessionMetadataChangedListener | null,): void {metadataListener = cb}/*** Register a listener for permission-mode changes from onChangeAppState.* Wired by print.ts to emit an SDK system:status message so CCR/IDE clients* see mode transitions in real time — regardless of which code path mutated* toolPermissionContext.mode (Shift+Tab, ExitPlanMode dialog, slash command,* bridge set_permission_mode, etc.).*/export function setPermissionModeChangedListener(cb: PermissionModeChangedListener | null,): void {permissionModeListener = cb}let hasPendingAction = falselet currentState: SessionState = 'idle'export function getSessionState(): SessionState {return currentState}export function notifySessionStateChanged(state: SessionState,details?: RequiresActionDetails,): void {currentState = statestateListener?.(state, details)// Mirror details into external_metadata so GetSession carries the// pending-action context without proto changes. Cleared via RFC 7396// null on the next non-blocked transition.if (state === 'requires_action' && details) {hasPendingAction = truemetadataListener?.({pending_action: details,})} else if (hasPendingAction) {hasPendingAction = falsemetadataListener?.({ pending_action: null })}// task_summary is written mid-turn by the forked summarizer; clear it at// idle so the next turn doesn't briefly show the previous turn's progress.if (state === 'idle') {metadataListener?.({ task_summary: null })}// Mirror to the SDK event stream so non-CCR consumers (scmuxd, VS Code)// see the same authoritative idle/running signal the CCR bridge does.// 'idle' fires after heldBackResult flushes — lets scmuxd flip IDLE and// show the bg-task dot instead of a stuck generating spinner.//// Opt-in until CCR web + mobile clients learn to ignore this subtype in// their isWorking() last-message heuristics — the trailing idle event// currently pins them at "Running...".// https://anthropic.slack.com/archives/C093BJBD1CP/p1774152406752229if (isEnvTruthy(process.env.CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS)) {enqueueSdkEvent({type: 'system',subtype: 'session_state_changed',state,})}}export function notifySessionMetadataChanged(metadata: SessionExternalMetadata,): void {metadataListener?.(metadata)}/*** Fired by onChangeAppState when toolPermissionContext.mode changes.* Downstream listeners (CCR external_metadata PUT, SDK status stream) are* both wired through this single choke point so no mode-mutation path can* silently bypass them.*/export function notifyPermissionModeChanged(mode: PermissionMode): void {permissionModeListener?.(mode)}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。