@agimon-ai/doompi-plan 0.0.1-alpha.2 → 0.0.1-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -19
- package/dist/adapters/pi/extension.cjs +2 -0
- package/dist/adapters/pi/extension.cjs.map +1 -0
- package/dist/{extension.d.cts → adapters/pi/extension.d.cts} +1 -1
- package/dist/adapters/pi/extension.d.cts.map +1 -0
- package/dist/{extension.d.mts → adapters/pi/extension.d.mts} +1 -1
- package/dist/adapters/pi/extension.d.mts.map +1 -0
- package/dist/adapters/pi/extension.mjs +2 -0
- package/dist/adapters/pi/extension.mjs.map +1 -0
- package/dist/adapters/telemetry/logSinkTelemetry.cjs +2 -0
- package/dist/adapters/telemetry/logSinkTelemetry.cjs.map +1 -0
- package/dist/adapters/telemetry/logSinkTelemetry.d.cts +34 -0
- package/dist/adapters/telemetry/logSinkTelemetry.d.cts.map +1 -0
- package/dist/adapters/telemetry/logSinkTelemetry.d.mts +34 -0
- package/dist/adapters/telemetry/logSinkTelemetry.d.mts.map +1 -0
- package/dist/adapters/telemetry/logSinkTelemetry.mjs +2 -0
- package/dist/adapters/telemetry/logSinkTelemetry.mjs.map +1 -0
- package/dist/config.cjs +1 -2
- package/dist/config.d.cts +2 -14
- package/dist/config.d.mts +2 -14
- package/dist/config.mjs +1 -2
- package/dist/extensions/doom.cjs +1 -1
- package/dist/extensions/doom.cjs.map +1 -1
- package/dist/extensions/doom.mjs +1 -1
- package/dist/extensions/doom.mjs.map +1 -1
- package/dist/extensions/pi.cjs +1 -1
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.cts +1 -1
- package/dist/extensions/pi.d.mts +1 -1
- package/dist/extensions/pi.mjs +1 -1
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/fableFlow.cjs +1 -3
- package/dist/fableFlow.d.cts +2 -66
- package/dist/fableFlow.d.mts +2 -66
- package/dist/fableFlow.mjs +1 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +1 -1
- package/dist/logSinkTelemetry.cjs +1 -2
- package/dist/logSinkTelemetry.d.cts +2 -24
- package/dist/logSinkTelemetry.d.mts +2 -24
- package/dist/logSinkTelemetry.mjs +1 -2
- package/dist/planConfig.cjs +1 -2
- package/dist/planConfig.d.cts +2 -0
- package/dist/planConfig.d.mts +2 -0
- package/dist/planConfig.mjs +1 -2
- package/dist/planMode.cjs +1 -6
- package/dist/planMode.d.cts +3 -75
- package/dist/planMode.d.mts +3 -75
- package/dist/planMode.mjs +1 -6
- package/dist/prompts.cjs +1 -3
- package/dist/prompts.d.cts +2 -24
- package/dist/prompts.d.mts +2 -24
- package/dist/prompts.mjs +1 -3
- package/dist/schemas/plan/config.cjs +2 -0
- package/dist/schemas/plan/config.cjs.map +1 -0
- package/dist/schemas/plan/config.d.cts +14 -0
- package/dist/schemas/plan/config.d.cts.map +1 -0
- package/dist/schemas/plan/config.d.mts +14 -0
- package/dist/schemas/plan/config.d.mts.map +1 -0
- package/dist/schemas/plan/config.mjs +2 -0
- package/dist/schemas/plan/config.mjs.map +1 -0
- package/dist/schemas/plan/planConfig.cjs +2 -0
- package/dist/schemas/plan/planConfig.cjs.map +1 -0
- package/dist/schemas/plan/planConfig.d.cts +21 -0
- package/dist/schemas/plan/planConfig.d.cts.map +1 -0
- package/dist/schemas/plan/planConfig.d.mts +21 -0
- package/dist/schemas/plan/planConfig.d.mts.map +1 -0
- package/dist/schemas/plan/planConfig.mjs +2 -0
- package/dist/schemas/plan/planConfig.mjs.map +1 -0
- package/dist/services/plan/fableFlow.cjs +3 -0
- package/dist/services/plan/fableFlow.cjs.map +1 -0
- package/dist/services/plan/fableFlow.d.cts +66 -0
- package/dist/services/plan/fableFlow.d.cts.map +1 -0
- package/dist/services/plan/fableFlow.d.mts +66 -0
- package/dist/services/plan/fableFlow.d.mts.map +1 -0
- package/dist/services/plan/fableFlow.mjs +3 -0
- package/dist/services/plan/fableFlow.mjs.map +1 -0
- package/dist/services/plan/planMode.cjs +6 -0
- package/dist/services/plan/planMode.cjs.map +1 -0
- package/dist/services/plan/planMode.d.cts +79 -0
- package/dist/services/plan/planMode.d.cts.map +1 -0
- package/dist/services/plan/planMode.d.mts +79 -0
- package/dist/services/plan/planMode.d.mts.map +1 -0
- package/dist/services/plan/planMode.mjs +6 -0
- package/dist/services/plan/planMode.mjs.map +1 -0
- package/dist/services/plan/prompts.cjs +3 -0
- package/dist/services/plan/prompts.cjs.map +1 -0
- package/dist/services/plan/prompts.d.cts +24 -0
- package/dist/services/plan/prompts.d.cts.map +1 -0
- package/dist/services/plan/prompts.d.mts +24 -0
- package/dist/services/plan/prompts.d.mts.map +1 -0
- package/dist/services/plan/prompts.mjs +3 -0
- package/dist/services/plan/prompts.mjs.map +1 -0
- package/package.json +16 -8
- package/dist/config.cjs.map +0 -1
- package/dist/config.d.cts.map +0 -1
- package/dist/config.d.mts.map +0 -1
- package/dist/config.mjs.map +0 -1
- package/dist/extension.cjs +0 -2
- package/dist/extension.cjs.map +0 -1
- package/dist/extension.d.cts.map +0 -1
- package/dist/extension.d.mts.map +0 -1
- package/dist/extension.mjs +0 -2
- package/dist/extension.mjs.map +0 -1
- package/dist/fableFlow.cjs.map +0 -1
- package/dist/fableFlow.d.cts.map +0 -1
- package/dist/fableFlow.d.mts.map +0 -1
- package/dist/fableFlow.mjs.map +0 -1
- package/dist/logSinkTelemetry.cjs.map +0 -1
- package/dist/logSinkTelemetry.d.cts.map +0 -1
- package/dist/logSinkTelemetry.d.mts.map +0 -1
- package/dist/logSinkTelemetry.mjs.map +0 -1
- package/dist/planConfig.cjs.map +0 -1
- package/dist/planConfig.mjs.map +0 -1
- package/dist/planMode.cjs.map +0 -1
- package/dist/planMode.d.cts.map +0 -1
- package/dist/planMode.d.mts.map +0 -1
- package/dist/planMode.mjs.map +0 -1
- package/dist/prompts.cjs.map +0 -1
- package/dist/prompts.d.cts.map +0 -1
- package/dist/prompts.d.mts.map +0 -1
- package/dist/prompts.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planMode.mjs","names":["loadDoomConfig","CONTRACT_FABLE_PLAN_REQUESTER","custom"],"sources":["../../../src/services/plan/planMode.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { createHash, randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { globalDoomConfigPath } from '@agimon-ai/doompi-config';\nimport { setDoomConfigValue, unsetDoomConfigValue } from '@agimon-ai/doompi-config/configWriter';\nimport {\n FABLE_PLAN_REQUESTER as CONTRACT_FABLE_PLAN_REQUESTER,\n createFablePlanBrokerClient,\n} from '@agimon-ai/doompi-extension-contracts/fable-plan';\nimport {\n MINOR_MODE_TOOL_NAME,\n type MinorModeOwnerHandle,\n type MinorModeState,\n registerMinorModeOwner,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport {\n registerSubagentPolicy,\n type SubagentPolicyHandle,\n} from '@agimon-ai/doompi-extension-contracts/subagent-policy';\nimport { isSubagentAction, subagentActionAcceptsField } from '@agimon-ai/doompi-extension-contracts/subagent-tool';\nimport {\n registerVoiceToolContribution,\n VOICE_MODE_TOOL_NAMES,\n type VoiceToolDefinition,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport { CONFIG_ACTION, registerDoomConfigContribution } from '@agimon-ai/doompi-ui/config';\nimport {\n createDoomLeaderContribution,\n type DoomLeaderBinding,\n registerDoomLeaderActionHandlers,\n} from '@agimon-ai/doompi-ui/leader';\nimport {\n buildVoiceToolResult,\n createVoiceQuestionHandoff,\n type QuestionParams,\n type VoiceQuestionHandoffHandle,\n} from '@agimon-ai/doompi-user-feedback/voice-question-handoff';\nimport type { ExtensionAPI, ExtensionContext, ToolCallEvent } from '@earendil-works/pi-coding-agent';\nimport { createPlanTelemetry, PLAN_EVENT, type PlanTelemetry } from '../../adapters/telemetry/logSinkTelemetry.ts';\nimport {\n getHarnessState,\n loadDoomConfig,\n loadHarnessState,\n type PlanningAgentConfig,\n type PlanningModeConfig,\n type PlanningThinkingLevel,\n resolvePlanningPlansDirectory,\n} from '../../schemas/plan/config.ts';\nimport { planConfigSections, planSettingByFieldId } from '../../schemas/plan/planConfig.ts';\nimport {\n createFablePlanFlow,\n FABLE_PLAN_PROFILE,\n type FablePlanBroker,\n type FablePlanResult,\n type FableStage,\n} from './fableFlow.ts';\nimport { buildFlavorPlanningPrompt, type DebugEvidencePacket, type PlanningFlavor } from './prompts.ts';\n\nconst PLAN_MODE_ENTRY = 'agent-harness-plan-mode';\nconst PLAN_MODE_CONTEXT = 'agent-harness-plan-mode-context';\nconst PLAN_DOCUMENT_ENTRY = 'agent-harness-plan-document';\nconst COMPLETE_PLAN_TOOL = 'complete_plan';\nconst WRITE_PLAN_TOOL = 'write_plan';\nconst ASK_USER_TOOL = 'ask_user_question';\nconst BASH_TOOL = 'bash';\nconst FIND_TOOL = 'find';\nconst GREP_TOOL = 'grep';\nconst LIST_TOOL = 'ls';\nconst MCP_TOOL = 'mcp';\nconst READ_TOOL = 'read';\nconst SUBAGENT_TOOL = 'subagent';\nconst TASK_TOOL = 'task';\nconst RECORD_DEBUG_EVIDENCE_TOOL = 'record_debug_evidence';\nconst RUN_FABLE_PLAN_TOOL = 'run_fable_plan';\nconst DEFAULT_PLAN_TITLE = 'implementation-plan';\nconst PLAN_TITLE_MAX_LENGTH = 64;\nconst SESSION_ID_MAX_LENGTH = 48;\nconst PLAN_MODE_STATUS_KEY = 'plan-mode';\nconst PLAN_LEADER_SOURCE = '@agimon-ai/doompi-plan';\nconst PLAN_LEADER_GROUP_ORDER = 60;\nconst MODE_ID = 'plan';\nconst MODE_LABEL = 'Plan';\nconst READ_ONLY_DETAIL = 'read only';\nconst MODE_ORDER = 40;\nconst MODE_ACTIVATE_ACTION = 'activate';\nconst MODE_DEACTIVATE_ACTION = 'deactivate';\nconst WARNING_STYLE = 'warning';\nconst INFO_STYLE = 'info';\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst PLAN_ALLOCATION_ATTEMPTS = 3;\nconst INVALID_PLAN_DESTINATION = 'Refused to write the plan because its destination is not a regular file.';\nconst PLAN_TRIGGER_ATTRIBUTE = 'plan.trigger';\nconst PLAN_MODEL_ATTRIBUTE = 'plan.model';\nconst PLAN_FLAVOR_ATTRIBUTE = 'plan.flavor';\nconst MODEL_NOT_FOUND_REASON = 'not_found';\nconst MODEL_UNAUTHENTICATED_REASON = 'unauthenticated';\nconst MODEL_RESTORE_FAILED_REASON = 'restore_failed';\nconst DEBUG_EVIDENCE_MAX_BYTES = 32 * 1024;\nconst DEBUG_EVIDENCE_MAX_TEXT_BYTES = 4 * 1024;\nconst DEBUG_EVIDENCE_MAX_ITEMS = 32;\nconst DEBUG_DIAGNOSTIC_TOOLS = new Set<string>();\nexport const WRITE_PLAN_TIMEOUT_MS = 5_000;\nconst EXIT_PLAN_MODE_CHOICE = 'Exit plan mode and start implementation';\nconst CONTINUE_PLANNING_CHOICE = 'Continue planning';\nconst EXIT_PLAN_DECISION = 'exit';\nconst CONTINUE_PLAN_DECISION = 'continue';\nconst PLAN_REVIEW_QUESTION = {\n questions: [\n {\n question: 'Plan complete. What would you like to do?',\n header: 'Plan review',\n options: [\n {\n label: EXIT_PLAN_MODE_CHOICE,\n description: 'Leave read-only plan mode and begin implementing the approved plan.',\n },\n {\n label: CONTINUE_PLANNING_CHOICE,\n description: 'Remain in read-only plan mode and refine the implementation plan.',\n },\n ],\n },\n ],\n} satisfies QuestionParams;\nconst PLAN_MODE_PARENT_TOOLS = new Set([\n 'add_directory',\n ASK_USER_TOOL,\n BASH_TOOL,\n COMPLETE_PLAN_TOOL,\n FIND_TOOL,\n GREP_TOOL,\n 'intercom',\n LIST_TOOL,\n MINOR_MODE_TOOL_NAME,\n ...VOICE_MODE_TOOL_NAMES,\n READ_TOOL,\n 'search_external_files',\n SUBAGENT_TOOL,\n 'subagent_supervisor',\n 'subagent_wait',\n TASK_TOOL,\n WRITE_PLAN_TOOL,\n]);\nconst PLAN_MODE_EXCLUDED_TOOLS = new Set(['edit', 'write', MCP_TOOL]);\nconst PLAN_MODE_EXPLORATION_TOOLS = [READ_TOOL, BASH_TOOL, GREP_TOOL, FIND_TOOL, LIST_TOOL] as const;\nconst CHILD_EXPLORATION_TOOLS = [...PLAN_MODE_EXPLORATION_TOOLS, MCP_TOOL] as const;\nconst PLAN_MODE_TRIGGER_LEADER = 'leader' as const;\nconst PLAN_MODE_TRIGGER_SESSION_RESTORE = 'session_restore' as const;\nconst PLAN_MODE_TRIGGER_PLAN_APPROVED = 'plan_approved' as const;\nconst PLAN_MODE_TRIGGER_SESSION_SHUTDOWN = 'session_shutdown' as const;\nconst PLAN_MODE_TRIGGER_VOICE_TOOL = 'voice_tool' as const;\nconst PLAN_STATE_VERSION = 2 as const;\nconst VALID_THINKING_LEVELS: readonly PlanningThinkingLevel[] = [\n 'off',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n];\nconst VALID_FABLE_STAGES: readonly FableStage[] = [\n 'idle',\n 'draft',\n 'review',\n 'completed',\n 'failed',\n 'cancelled',\n 'interrupted',\n];\nconst PLAN_VOICE_SOURCE = '@agimon-ai/doompi-plan';\nconst PLAN_VOICE_ACTIVATE_ID = 'plan-activate';\nconst PLAN_VOICE_EXIT_ID = 'plan-exit';\nconst PLAN_VOICE_ACTIVATE_NAME = 'activate_plan';\nconst PLAN_VOICE_EXIT_NAME = 'exit_plan';\nconst PLAN_VOICE_FLAVORS = ['normal', 'debug', 'fable'] as const;\nconst PLAN_VOICE_FLAVOR_SCHEMA = { type: 'string', enum: [...PLAN_VOICE_FLAVORS] } as const;\nconst PLAN_VOICE_ACTIVATE_INPUT_SCHEMA = {\n type: 'object',\n properties: { flavor: PLAN_VOICE_FLAVOR_SCHEMA },\n required: ['flavor'],\n additionalProperties: false,\n} as const;\nconst PLAN_VOICE_EXIT_INPUT_SCHEMA = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n} as const;\nconst PLAN_VOICE_RESULT_SCHEMA = {\n type: 'object',\n properties: {\n active: { type: 'boolean' },\n flavor: { anyOf: [{ ...PLAN_VOICE_FLAVOR_SCHEMA }, { type: 'null' }] },\n changed: { type: 'boolean' },\n },\n required: ['active', 'flavor', 'changed'],\n additionalProperties: false,\n} as const;\nconst PLAN_TRANSIENT_TOOL_NAMES = new Set([\n COMPLETE_PLAN_TOOL,\n WRITE_PLAN_TOOL,\n RECORD_DEBUG_EVIDENCE_TOOL,\n RUN_FABLE_PLAN_TOOL,\n MINOR_MODE_TOOL_NAME,\n ...VOICE_MODE_TOOL_NAMES,\n]);\n\nexport type { PlanningFlavor } from './prompts.ts';\n\nexport interface ModelIdentity {\n provider: string;\n id: string;\n}\n\nexport interface PlanSnapshot {\n tools: string[];\n model?: ModelIdentity;\n thinking: PlanningThinkingLevel;\n}\n\ninterface PersistedPlanModeState {\n version: typeof PLAN_STATE_VERSION;\n activeFlavor?: PlanningFlavor;\n originalSnapshot?: PlanSnapshot;\n planId?: string;\n interruptedFableStage?: FableStage;\n}\n\ninterface PlanDocument {\n content: string;\n path: string;\n sessionId: string;\n planId?: string;\n title: string;\n writtenAt: string;\n}\n\ntype PlanWritePhase = 'checking' | 'writing';\n\n/** Why plan mode changed state, so the sink can tell a user toggle from a session restore. */\ntype PlanModeTrigger =\n | typeof PLAN_MODE_TRIGGER_LEADER\n | typeof PLAN_MODE_TRIGGER_SESSION_RESTORE\n | typeof PLAN_MODE_TRIGGER_PLAN_APPROVED\n | typeof PLAN_MODE_TRIGGER_SESSION_SHUTDOWN\n | typeof PLAN_MODE_TRIGGER_VOICE_TOOL;\n\nexport interface PlanModeExtensionOptions {\n fableBroker?: FablePlanBroker;\n debugDiagnosticTools?: readonly string[];\n doomIntegrations?: boolean;\n}\n\nexport function planTitleSlug(markdown: string): string {\n const heading = markdown.match(/^#\\s+(.+?)\\s*$/m)?.[1] ?? DEFAULT_PLAN_TITLE;\n return (\n heading\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, PLAN_TITLE_MAX_LENGTH) || DEFAULT_PLAN_TITLE\n );\n}\n\nexport function planSessionIdentifier(sessionId: string): string {\n const readable = encodeURIComponent(sessionId).slice(0, SESSION_ID_MAX_LENGTH) || 'session';\n const digest = createHash('sha256').update(sessionId).digest('hex');\n return `${readable}--${digest}`;\n}\n\nexport function createPlanIdentifier(now = new Date(), id = randomUUID()): string {\n const timestamp = now\n .toISOString()\n .replace(/[-:]/g, '')\n .replace(/\\.\\d{3}Z$/, 'Z');\n return `${timestamp}--${id}`;\n}\n\nexport function visiblePlanForToolCall(entries: readonly unknown[], toolCallId: string): string | undefined {\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index];\n if (!entry || typeof entry !== 'object') continue;\n const candidate = entry as {\n type?: string;\n message?: { role?: string; content?: unknown };\n };\n if (candidate.type !== 'message' || candidate.message?.role !== 'assistant') continue;\n if (!Array.isArray(candidate.message.content)) continue;\n\n const toolIndex = candidate.message.content.findIndex((block) => {\n if (!block || typeof block !== 'object') return false;\n const content = block as { type?: string; id?: string; name?: string };\n return content.type === 'toolCall' && content.id === toolCallId && content.name === WRITE_PLAN_TOOL;\n });\n if (toolIndex < 0) continue;\n\n const plan = candidate.message.content\n .slice(0, toolIndex)\n .flatMap((block) => {\n if (!block || typeof block !== 'object') return [];\n const content = block as { type?: string; text?: unknown };\n return content.type === 'text' && typeof content.text === 'string' ? [content.text] : [];\n })\n .join('\\n\\n')\n .trim();\n return plan || undefined;\n }\n return undefined;\n}\n\nfunction abortReason(signal: AbortSignal): Error {\n return signal.reason instanceof Error ? signal.reason : new Error('Plan write cancelled.');\n}\n\nasync function waitForAbortable<T>(operation: () => Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) throw abortReason(signal);\n let onAbort: (() => void) | undefined;\n const aborted = new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(abortReason(signal));\n signal.addEventListener('abort', onAbort, { once: true });\n });\n try {\n return await Promise.race([operation(), aborted]);\n } finally {\n if (onAbort) signal.removeEventListener('abort', onAbort);\n }\n}\n\ntype MutableSubagentStep = {\n model?: string;\n output?: string | boolean;\n progress?: boolean;\n worktree?: boolean;\n parallel?: MutableSubagentStep | MutableSubagentStep[];\n};\n\ntype MutableSubagentRunRequest = {\n [key: string]: unknown;\n model?: string;\n};\n\ntype MutableSubagentInput = MutableSubagentStep & {\n action?: string;\n artifacts?: boolean;\n outputSchema?: Record<string, unknown>;\n share?: boolean;\n tasks?: MutableSubagentStep[];\n chain?: MutableSubagentStep[];\n chainDir?: string;\n sessionDir?: string;\n requests?: MutableSubagentRunRequest[];\n};\n\ntype MutableTaskAssignment = {\n [key: string]: unknown;\n model?: string;\n};\n\ntype MutableTaskInput = {\n action?: string;\n assignments?: MutableTaskAssignment[];\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction parseModelIdentity(value: unknown): ModelIdentity | undefined {\n if (!isRecord(value) || !isString(value.provider) || !isString(value.id)) return undefined;\n if (!value.provider || !value.id || value.provider.length > 128 || value.id.length > 128) return undefined;\n return { provider: value.provider, id: value.id };\n}\n\nfunction parseThinkingLevel(value: unknown): PlanningThinkingLevel | undefined {\n return isString(value) && VALID_THINKING_LEVELS.includes(value as PlanningThinkingLevel)\n ? (value as PlanningThinkingLevel)\n : undefined;\n}\n\nfunction parseFableStage(value: unknown): FableStage | undefined {\n return isString(value) && VALID_FABLE_STAGES.includes(value as FableStage) ? (value as FableStage) : undefined;\n}\n\nfunction parseStringArray(value: unknown): string[] | undefined {\n if (!Array.isArray(value) || value.some((item) => !isString(item))) return undefined;\n return value.map((item) => item);\n}\n\nfunction parsePlanSnapshot(value: unknown): PlanSnapshot | undefined {\n if (!isRecord(value)) return undefined;\n const tools = parseStringArray(value.tools);\n const thinking = parseThinkingLevel(value.thinking);\n if (!tools || thinking === undefined) return undefined;\n const model = value.model === undefined ? undefined : parseModelIdentity(value.model);\n if (value.model !== undefined && !model) return undefined;\n return { tools, ...(model ? { model } : {}), thinking };\n}\n\nfunction parsePlanningFlavor(value: unknown): PlanningFlavor | undefined {\n return value === 'normal' || value === 'debug' || value === 'fable' ? value : undefined;\n}\n\nfunction parseVersionedPlanState(value: Record<string, unknown>): PersistedPlanModeState | undefined {\n if (value.version !== PLAN_STATE_VERSION) return undefined;\n const activeFlavor = value.activeFlavor === undefined ? undefined : parsePlanningFlavor(value.activeFlavor);\n if (value.activeFlavor !== undefined && !activeFlavor) return undefined;\n const originalSnapshot = value.originalSnapshot === undefined ? undefined : parsePlanSnapshot(value.originalSnapshot);\n if (value.originalSnapshot !== undefined && !originalSnapshot) return undefined;\n const planId = value.planId === undefined ? undefined : isString(value.planId) ? value.planId : undefined;\n if (value.planId !== undefined && planId === undefined) return undefined;\n const interruptedFableStage =\n value.interruptedFableStage === undefined ? undefined : parseFableStage(value.interruptedFableStage);\n if (value.interruptedFableStage !== undefined && !interruptedFableStage) return undefined;\n return {\n version: PLAN_STATE_VERSION,\n ...(activeFlavor ? { activeFlavor } : {}),\n ...(originalSnapshot ? { originalSnapshot } : {}),\n ...(planId ? { planId } : {}),\n ...(interruptedFableStage ? { interruptedFableStage } : {}),\n };\n}\n\nfunction parseLegacyPlanState(value: Record<string, unknown>): PersistedPlanModeState | undefined {\n if (value.enabled !== true && value.enabled !== false) return undefined;\n const tools = value.toolsBeforePlanMode === undefined ? undefined : parseStringArray(value.toolsBeforePlanMode);\n if (value.toolsBeforePlanMode !== undefined && !tools) return undefined;\n const model = value.modelBeforePlanMode === undefined ? undefined : parseModelIdentity(value.modelBeforePlanMode);\n if (value.modelBeforePlanMode !== undefined && !model) return undefined;\n const thinking =\n value.thinkingBeforePlanMode === undefined ? undefined : parseThinkingLevel(value.thinkingBeforePlanMode);\n if (value.thinkingBeforePlanMode !== undefined && thinking === undefined) return undefined;\n const planId = value.planId === undefined ? undefined : isString(value.planId) ? value.planId : undefined;\n if (value.planId !== undefined && planId === undefined) return undefined;\n const originalSnapshot =\n tools && thinking !== undefined ? { tools, ...(model ? { model } : {}), thinking } : undefined;\n return {\n version: PLAN_STATE_VERSION,\n ...(value.enabled ? { activeFlavor: 'normal' as const } : {}),\n ...(originalSnapshot ? { originalSnapshot } : {}),\n ...(planId ? { planId } : {}),\n };\n}\n\nexport function parsePersistedPlanState(value: unknown): PersistedPlanModeState | undefined {\n if (!isRecord(value)) return undefined;\n return parseVersionedPlanState(value) ?? parseLegacyPlanState(value);\n}\n\nfunction parsePlanDocument(value: unknown): PlanDocument | undefined {\n if (!isRecord(value)) return undefined;\n if (!isString(value.content) || !isString(value.path) || !isString(value.sessionId) || !isString(value.title)) {\n return undefined;\n }\n if (!isString(value.writtenAt)) return undefined;\n const planId = value.planId === undefined ? undefined : isString(value.planId) ? value.planId : undefined;\n if (value.planId !== undefined && planId === undefined) return undefined;\n return {\n content: value.content,\n path: value.path,\n sessionId: value.sessionId,\n ...(planId ? { planId } : {}),\n title: value.title,\n writtenAt: value.writtenAt,\n };\n}\n\nfunction boundedDebugText(value: unknown, field: string, required: boolean): string {\n if (!isString(value)) throw new Error(`${field} must be a string.`);\n const text = value.trim();\n if (required && !text) throw new Error(`${field} must not be empty.`);\n if (Buffer.byteLength(text, 'utf8') > DEBUG_EVIDENCE_MAX_TEXT_BYTES) {\n throw new Error(`${field} exceeds the bounded debug evidence limit.`);\n }\n return text;\n}\n\nfunction boundedDebugList(value: unknown, field: string): string[] {\n if (!Array.isArray(value) || value.length > DEBUG_EVIDENCE_MAX_ITEMS) {\n throw new Error(`${field} must be a bounded string array.`);\n }\n return value.map((item, index) => boundedDebugText(item, `${field}[${index}]`, false));\n}\n\nfunction optionalDebugText(value: unknown, field: string): string {\n return value === undefined ? '' : boundedDebugText(value, field, false);\n}\n\nfunction optionalDebugList(value: unknown, field: string): string[] {\n return value === undefined ? [] : boundedDebugList(value, field);\n}\n\nfunction assertExactObjectKeys(value: Record<string, unknown>, keys: readonly string[], field: string): void {\n const allowed = new Set(keys);\n const unexpected = Object.keys(value).find((key) => !allowed.has(key));\n if (unexpected) throw new Error(`${field} contains unsupported field '${unexpected}'.`);\n}\n\nexport function parseDebugEvidencePacket(value: unknown): DebugEvidencePacket {\n if (!isRecord(value)) throw new Error('Debug evidence must be an object.');\n assertExactObjectKeys(\n value,\n [\n 'issue',\n 'expectedBehavior',\n 'reproductionAttempt',\n 'actualBehavior',\n 'logs',\n 'correlatedTraceEvidence',\n 'processOutput',\n 'browserConsoleEvidence',\n 'correlationIds',\n 'timestamps',\n 'verifiedFacts',\n 'hypotheses',\n 'unavailableEvidence',\n ],\n 'Debug evidence',\n );\n const packet: DebugEvidencePacket = {\n issue: boundedDebugText(value.issue, 'issue', true),\n expectedBehavior: optionalDebugText(value.expectedBehavior, 'expectedBehavior'),\n reproductionAttempt: optionalDebugText(value.reproductionAttempt, 'reproductionAttempt'),\n actualBehavior: optionalDebugText(value.actualBehavior, 'actualBehavior'),\n logs: optionalDebugList(value.logs, 'logs'),\n correlatedTraceEvidence: optionalDebugList(value.correlatedTraceEvidence, 'correlatedTraceEvidence'),\n processOutput: optionalDebugList(value.processOutput, 'processOutput'),\n browserConsoleEvidence: optionalDebugList(value.browserConsoleEvidence, 'browserConsoleEvidence'),\n correlationIds: optionalDebugList(value.correlationIds, 'correlationIds'),\n timestamps: optionalDebugList(value.timestamps, 'timestamps'),\n verifiedFacts: optionalDebugList(value.verifiedFacts, 'verifiedFacts'),\n hypotheses: optionalDebugList(value.hypotheses, 'hypotheses'),\n unavailableEvidence: optionalDebugList(value.unavailableEvidence, 'unavailableEvidence'),\n };\n if (Buffer.byteLength(JSON.stringify(packet), 'utf8') > DEBUG_EVIDENCE_MAX_BYTES) {\n throw new Error('Debug evidence exceeds the bounded packet size.');\n }\n return packet;\n}\n\nexport function planModeTools(activeTools: string[], availableTools: string[]): string[] {\n const available = new Set(availableTools);\n const retained = activeTools.filter((name) => PLAN_MODE_PARENT_TOOLS.has(name) && available.has(name));\n const unrelated = activeTools.filter(\n (name) =>\n !PLAN_MODE_PARENT_TOOLS.has(name) &&\n !PLAN_MODE_EXCLUDED_TOOLS.has(name) &&\n !PLAN_TRANSIENT_TOOL_NAMES.has(name) &&\n available.has(name),\n );\n const exploration = PLAN_MODE_EXPLORATION_TOOLS.filter((name) => available.has(name));\n const planTools = [COMPLETE_PLAN_TOOL, TASK_TOOL, WRITE_PLAN_TOOL].filter((name) => available.has(name));\n return [...new Set([...retained, ...unrelated, ...exploration, ...planTools])];\n}\n\nfunction planningToolsForFlavor(\n snapshotTools: string[],\n liveTools: string[],\n availableTools: string[],\n flavor: PlanningFlavor,\n diagnosticTools: ReadonlySet<string>,\n): string[] {\n const available = new Set(availableTools);\n const liveUnrelatedTools = liveTools.filter(\n (name) =>\n !PLAN_MODE_PARENT_TOOLS.has(name) && !PLAN_MODE_EXCLUDED_TOOLS.has(name) && !PLAN_TRANSIENT_TOOL_NAMES.has(name),\n );\n const activeTools = [...new Set([...snapshotTools, ...liveUnrelatedTools])];\n const base = planModeTools(\n activeTools.filter((name) => !PLAN_TRANSIENT_TOOL_NAMES.has(name)),\n availableTools,\n );\n const extras =\n flavor === 'debug' ? [RECORD_DEBUG_EVIDENCE_TOOL, ...diagnosticTools].filter((name) => available.has(name)) : [];\n if (flavor === 'fable' && available.has(RUN_FABLE_PLAN_TOOL)) extras.push(RUN_FABLE_PLAN_TOOL);\n for (const name of [MINOR_MODE_TOOL_NAME, ...VOICE_MODE_TOOL_NAMES]) {\n if (liveTools.includes(name) && available.has(name)) extras.push(name);\n }\n return [...new Set([...base, ...extras])];\n}\n\nfunction restoreSnapshotTools(snapshotTools: string[], liveTools: string[], availableTools: string[]): string[] {\n const available = new Set(availableTools);\n const live = new Set(liveTools);\n const restored = snapshotTools.filter(\n (name) => !PLAN_TRANSIENT_TOOL_NAMES.has(name) && available.has(name) && (name !== ASK_USER_TOOL || live.has(name)),\n );\n const unrelatedLiveTools = liveTools.filter(\n (name) =>\n !PLAN_MODE_PARENT_TOOLS.has(name) &&\n !PLAN_MODE_EXCLUDED_TOOLS.has(name) &&\n !PLAN_TRANSIENT_TOOL_NAMES.has(name) &&\n available.has(name),\n );\n const liveToolsToRestore = [MINOR_MODE_TOOL_NAME, ...VOICE_MODE_TOOL_NAMES].filter(\n (name) => live.has(name) && available.has(name),\n );\n return [...new Set([...restored, ...unrelatedLiveTools, ...liveToolsToRestore])];\n}\n\nfunction disableStepOutput(step: MutableSubagentStep): void {\n step.output = false;\n step.progress = false;\n step.worktree = false;\n if (Array.isArray(step.parallel)) {\n for (const child of step.parallel) disableStepOutput(child);\n } else if (step.parallel) {\n disableStepOutput(step.parallel);\n }\n}\n\nexport function constrainSubagentInput(input: MutableSubagentInput): void {\n if (input.action !== undefined) {\n if (isSubagentAction(input.action) && subagentActionAcceptsField(input.action, 'artifacts')) {\n input.artifacts = false;\n }\n return;\n }\n\n input.artifacts = false;\n input.output = false;\n input.share = false;\n input.progress = false;\n input.worktree = false;\n delete input.chainDir;\n delete input.outputSchema;\n delete input.sessionDir;\n for (const task of input.tasks ?? []) disableStepOutput(task);\n for (const step of input.chain ?? []) disableStepOutput(step);\n}\n\nexport function planningSubagentModel(\n config: PlanningAgentConfig | undefined,\n currentModel: ModelIdentity | undefined,\n): string | undefined {\n if (!config?.model && !config?.thinking) return undefined;\n const baseModel = config.model ?? (currentModel ? `${currentModel.provider}/${currentModel.id}` : undefined);\n if (!baseModel) return undefined;\n if (!config.thinking) return baseModel;\n return `${baseModel.replace(/:(?:off|minimal|low|medium|high|xhigh|max)$/, '')}:${config.thinking}`;\n}\n\nexport function configurePlanningSubagentInput(input: MutableSubagentInput, model: string): void {\n if (input.action !== 'run') return;\n for (const request of input.requests ?? []) request.model = model;\n}\n\nexport function configurePlanningTaskInput(input: MutableTaskInput, model: string): void {\n if (input.action !== 'assign') return;\n for (const assignment of input.assignments ?? []) assignment.model = model;\n}\n\nexport function isBlockedSubagentManagementAction(action: string | undefined): boolean {\n return new Set([\n 'append-step',\n 'create',\n 'delete',\n 'disable',\n 'eject',\n 'enable',\n 'grant-spawn-budget',\n 'reset',\n 'schedule',\n 'schedule-cancel',\n 'update',\n 'watchdog.configure',\n ]).has(action ?? '');\n}\n\nfunction resolvePlanningModel(\n modelSpec: string,\n ctx: ExtensionContext,\n): NonNullable<ExtensionContext['model']> | undefined {\n const separator = modelSpec.indexOf('/');\n if (separator > 0) {\n return ctx.modelRegistry.find(modelSpec.slice(0, separator), modelSpec.slice(separator + 1));\n }\n\n const matches = ctx.modelRegistry.getAvailable().filter((model) => model.id === modelSpec);\n return (\n matches.find((model) => model.provider === ctx.model?.provider) ?? (matches.length === 1 ? matches[0] : undefined)\n );\n}\n\nexport type PlanningConfigProvider = () => PlanningModeConfig | undefined;\n\n/** Reads Doom settings from disk so each plan-mode activation sees current configuration. */\nexport function loadPlanningModeConfig(\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n): PlanningModeConfig | undefined {\n return loadDoomConfig(loadHarnessState(environment).state.root ?? currentDirectory).modes?.planning;\n}\n\n/**\n * The plan menu as it stands with the mode on or off.\n *\n * `exit` is published only while the mode is on. It is the one entry that can\n * do nothing otherwise, and a menu offering a way out of a mode reads as\n * though you are in it.\n */\nfunction planLeaderBindings(active: boolean): DoomLeaderBinding[] {\n const group = { key: 'p', label: 'plan', order: PLAN_LEADER_GROUP_ORDER } as const;\n return [\n {\n id: 'plan.normal',\n path: [group, { key: 'p', label: 'normal', detail: 'read-only planning' }],\n action: { name: 'plan.normal' },\n },\n {\n id: 'plan.debug',\n path: [group, { key: 'd', label: 'debug', detail: 'adaptive debug planning' }],\n action: { name: 'plan.debug' },\n },\n {\n id: 'plan.fable',\n path: [group, { key: 'f', label: 'fable', detail: 'repository-aware draft' }],\n action: { name: 'plan.fable' },\n },\n ...(active\n ? [\n {\n id: 'plan.exit',\n path: [group, { key: 'e', label: 'exit', detail: 'restore and exit' }] as DoomLeaderBinding['path'],\n action: { name: 'plan.exit' },\n },\n ]\n : []),\n ];\n}\n\nexport function planModeExtension(\n pi: ExtensionAPI,\n planningConfigProvider: PlanningConfigProvider = loadPlanningModeConfig,\n telemetry: PlanTelemetry = createPlanTelemetry(),\n options: PlanModeExtensionOptions = {},\n): void {\n let enabled = false;\n let activeFlavor: PlanningFlavor | undefined;\n let planSnapshot: PlanSnapshot | undefined;\n let activePlanningConfig: PlanningModeConfig | undefined;\n let capabilityCeiling: SubagentPolicyHandle | undefined;\n let currentPlan: PlanDocument | undefined;\n let activePlanId: string | undefined;\n let planReadyForReview = false;\n let awaitingVoicePlanDecision = false;\n let voiceQuestionHandoff: VoiceQuestionHandoffHandle | undefined;\n let debugEvidence: DebugEvidencePacket | undefined;\n let fableStage: FableStage = 'idle';\n let interruptedFableStage: FableStage | undefined;\n let activeContext: ExtensionContext | undefined;\n let activeFableRun: Promise<FablePlanResult> | undefined;\n let transitionQueue: Promise<void> = Promise.resolve();\n const doomIntegrations = options.doomIntegrations ?? true;\n const diagnosticTools = new Set(options.debugDiagnosticTools ?? DEBUG_DIAGNOSTIC_TOOLS);\n const sessionBroker = createFablePlanBrokerClient(() => activeContext?.sessionManager.getSessionId());\n const fableBroker: FablePlanBroker = options.fableBroker ?? {\n start: (request, signal) => sessionBroker.start(request, signal),\n cancel: (operationId, reason) =>\n sessionBroker.cancel({ requester: CONTRACT_FABLE_PLAN_REQUESTER, operationId, reason }),\n };\n const isFableBrokerAvailable = (): boolean => options.fableBroker !== undefined || sessionBroker.isAvailable();\n const modeOwner: Pick<MinorModeOwnerHandle, 'publish'> = doomIntegrations\n ? registerMinorModeOwner(pi, {\n descriptor: {\n source: PLAN_LEADER_SOURCE,\n id: MODE_ID,\n label: MODE_LABEL,\n description: 'Read-only planning with normal, debug, and Fable flavors.',\n order: MODE_ORDER,\n actions: [\n {\n id: MODE_ACTIVATE_ACTION,\n label: 'Activate',\n description: 'Activate plan mode or switch its planning flavor.',\n contexts: ['tui', 'headless'],\n parameters: [\n {\n name: 'flavor',\n label: 'Flavor',\n kind: 'enum',\n required: true,\n choices: [\n { value: 'normal', label: 'Normal' },\n { value: 'debug', label: 'Debug' },\n { value: 'fable', label: 'Fable' },\n ],\n },\n ],\n },\n {\n id: MODE_DEACTIVATE_ACTION,\n label: 'Deactivate',\n description: 'Exit plan mode and restore the previous agent configuration.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n ],\n },\n initialState: {\n activation: 'inactive',\n condition: 'ready',\n actions: [\n { id: MODE_ACTIVATE_ACTION, enabled: true },\n { id: MODE_DEACTIVATE_ACTION, enabled: false, disabledReason: 'Plan mode is inactive.' },\n ],\n },\n async handleAction(actionId, argumentsValue, execution) {\n if (actionId === MODE_ACTIVATE_ACTION) {\n const flavor = argumentsValue.flavor;\n if (flavor !== 'normal' && flavor !== 'debug' && flavor !== 'fable') {\n throw new Error('A valid plan flavor is required.');\n }\n await queueTransition(() => activateFlavor(execution.context, flavor, PLAN_MODE_TRIGGER_LEADER, false));\n return { message: `Plan mode is active with the ${flavor} flavor.` };\n }\n if (actionId === MODE_DEACTIVATE_ACTION) {\n const exited = await queueTransition(() => exitPlanMode(execution.context, PLAN_MODE_TRIGGER_LEADER));\n return { message: exited ? 'Plan mode deactivated.' : 'Plan mode remains active.' };\n }\n throw new Error(`Unknown plan mode action: ${actionId}`);\n },\n onError: (error) => void telemetry.recordError(PLAN_EVENT.configLoadFailed, error),\n })\n : { publish: () => undefined };\n const leaderContribution = doomIntegrations\n ? createDoomLeaderContribution(pi, {\n source: PLAN_LEADER_SOURCE,\n bindings: planLeaderBindings(false),\n })\n : { update: () => undefined };\n let planConfigNotice: string | undefined;\n const planConfigContribution = doomIntegrations\n ? registerDoomConfigContribution(pi, {\n source: PLAN_LEADER_SOURCE,\n // Read at publish time, not cached: plan mode re-reads this file on every\n // activation anyway, so the panel should show whatever is on disk now.\n listSections: () => {\n try {\n return planConfigSections(planningConfigProvider(), planConfigNotice);\n } catch (error) {\n // A malformed config file must not take session start down with it. The\n // panel is where someone would go to repair it, so it has to still draw.\n return planConfigSections(undefined, error instanceof Error ? error.message : String(error));\n }\n },\n handlers: {\n [CONFIG_ACTION.set]: async ({ fieldId, value }) => {\n const setting = planSettingByFieldId(fieldId);\n if (!setting || !value) return;\n planConfigNotice = undefined;\n await setDoomConfigValue(globalDoomConfigPath(), [...setting.keyPath], value);\n },\n [CONFIG_ACTION.clear]: async ({ fieldId }) => {\n const setting = planSettingByFieldId(fieldId);\n if (!setting) return;\n planConfigNotice = undefined;\n await unsetDoomConfigValue(globalDoomConfigPath(), [...setting.keyPath]);\n },\n },\n onError: (error) => {\n planConfigNotice = error instanceof Error ? error.message : String(error);\n },\n })\n : { dispose: () => undefined, update: () => undefined };\n\n /** Identical bindings are dropped by the handle, so this can ride along with every state change. */\n function updateLeader(): void {\n leaderContribution.update(planLeaderBindings(enabled));\n }\n\n function updateStatus(ctx: ExtensionContext): void {\n updateLeader();\n const flavor = activeFlavor;\n const status = enabled && flavor ? `plan:${flavor}` : undefined;\n const stage = flavor === 'fable' && fableStage !== 'idle' ? ` · ${fableStage}` : '';\n ctx.ui.setStatus(PLAN_MODE_STATUS_KEY, status ? ctx.ui.theme.fg(WARNING_STYLE, status) : undefined);\n const modeState: MinorModeState = {\n activation: enabled ? 'active' : 'inactive',\n condition: fableStage === 'failed' ? 'failed' : fableStage === 'interrupted' ? 'degraded' : 'ready',\n ...(enabled && flavor ? { detail: `${flavor}${stage} - ${READ_ONLY_DETAIL}`, color: WARNING_STYLE } : {}),\n actions: [\n { id: MODE_ACTIVATE_ACTION, enabled: true },\n ...(enabled\n ? [{ id: MODE_DEACTIVATE_ACTION, enabled: true } as const]\n : [{ id: MODE_DEACTIVATE_ACTION, enabled: false, disabledReason: 'Plan mode is inactive.' } as const]),\n ],\n };\n modeOwner.publish(modeState);\n }\n\n function updateCapabilityCeiling(): void {\n if (!doomIntegrations || !enabled || !activeFlavor || !activeContext) return;\n const allowedTools = [...CHILD_EXPLORATION_TOOLS];\n const allowedExternalProfiles = activeFlavor === 'fable' ? [FABLE_PLAN_PROFILE] : [];\n const policy = {\n owner: PLAN_LEADER_SOURCE,\n allowedTools,\n requiredTools: [BASH_TOOL, MCP_TOOL],\n allowMcpTools: true,\n allowedExternalProfiles,\n denyExtensions: false,\n };\n if (capabilityCeiling) capabilityCeiling.update(policy);\n else {\n capabilityCeiling = registerSubagentPolicy(\n createProtocolRuntime({\n bus: pi.events,\n source: PLAN_LEADER_SOURCE,\n sessionId: activeContext.sessionManager.getSessionId(),\n }),\n policy,\n );\n }\n }\n\n function persistState(): void {\n pi.appendEntry(PLAN_MODE_ENTRY, {\n version: PLAN_STATE_VERSION,\n ...(enabled && activeFlavor ? { activeFlavor } : {}),\n ...(planSnapshot\n ? {\n originalSnapshot: {\n tools: [...planSnapshot.tools],\n ...(planSnapshot.model ? { model: { ...planSnapshot.model } } : {}),\n thinking: planSnapshot.thinking,\n },\n }\n : {}),\n ...(activePlanId ? { planId: activePlanId } : {}),\n ...(interruptedFableStage ? { interruptedFableStage } : {}),\n } satisfies PersistedPlanModeState);\n }\n\n function reportModelFailure(\n phase: 'apply' | 'restore',\n model: string,\n reason: typeof MODEL_NOT_FOUND_REASON | typeof MODEL_UNAUTHENTICATED_REASON | typeof MODEL_RESTORE_FAILED_REASON,\n ): void {\n void telemetry.recordWarning(PLAN_EVENT.modelResolveFailed, `Planning model ${reason}: ${model}`, {\n [PLAN_MODEL_ATTRIBUTE]: model,\n 'plan.model.phase': phase,\n 'plan.model.reason': reason,\n });\n }\n\n async function applyMainPlanningConfig(ctx: ExtensionContext): Promise<void> {\n const config = activePlanningConfig?.main;\n if (!config) return;\n if (config.model) {\n const model = resolvePlanningModel(config.model, ctx);\n if (!model) {\n ctx.ui.notify(`Planning model not found: ${config.model}`, WARNING_STYLE);\n reportModelFailure('apply', config.model, MODEL_NOT_FOUND_REASON);\n } else if (!(await pi.setModel(model))) {\n ctx.ui.notify(`Planning model is unavailable without authentication: ${config.model}`, WARNING_STYLE);\n reportModelFailure('apply', config.model, MODEL_UNAUTHENTICATED_REASON);\n }\n }\n if (config.thinking) pi.setThinkingLevel(config.thinking);\n }\n\n async function restoreMainAgent(ctx: ExtensionContext, snapshot: PlanSnapshot | undefined): Promise<boolean> {\n if (!snapshot) return false;\n if (snapshot.model) {\n const identity = `${snapshot.model.provider}/${snapshot.model.id}`;\n const model = ctx.modelRegistry.find(snapshot.model.provider, snapshot.model.id);\n if (!model) {\n ctx.ui.notify(`Previous model not found: ${identity}`, WARNING_STYLE);\n reportModelFailure('restore', identity, MODEL_NOT_FOUND_REASON);\n return false;\n }\n try {\n if (!(await pi.setModel(model))) {\n ctx.ui.notify(`Previous model is unavailable without authentication: ${identity}`, WARNING_STYLE);\n reportModelFailure('restore', identity, MODEL_UNAUTHENTICATED_REASON);\n return false;\n }\n } catch (error) {\n ctx.ui.notify(`Previous model could not be restored: ${identity}`, WARNING_STYLE);\n reportModelFailure('restore', identity, MODEL_RESTORE_FAILED_REASON);\n void telemetry.recordError(PLAN_EVENT.modelResolveFailed, error, {\n [PLAN_MODEL_ATTRIBUTE]: identity,\n 'plan.model.phase': 'restore',\n 'plan.model.reason': MODEL_RESTORE_FAILED_REASON,\n });\n return false;\n }\n }\n pi.setThinkingLevel(snapshot.thinking);\n return true;\n }\n\n function reportCurrentFlavor(ctx: ExtensionContext): void {\n if (enabled && activeFlavor) ctx.ui.notify(`Already in plan:${activeFlavor}.`, INFO_STYLE);\n else ctx.ui.notify('Plan mode is inactive.', INFO_STYLE);\n }\n\n function queueTransition<T>(transition: () => Promise<T>): Promise<T> {\n const queued = transitionQueue.then(transition, transition);\n transitionQueue = queued.then(\n () => undefined,\n () => undefined,\n );\n return queued;\n }\n\n async function cancelFableOperation(reason: string): Promise<void> {\n if (!activeFableRun && !fableStage.match(/^(draft|review)$/u)) return;\n if (fableStage === 'draft' || fableStage === 'review') interruptedFableStage = fableStage;\n fableFlow.cancel(reason);\n const pending = activeFableRun;\n if (pending) {\n try {\n await pending;\n } catch (error) {\n void telemetry.recordError(PLAN_EVENT.modeDisabled, error, {\n [PLAN_FLAVOR_ATTRIBUTE]: 'fable',\n 'plan.fable.reason': 'cancel_failed',\n });\n }\n }\n activeFableRun = undefined;\n if (interruptedFableStage) fableStage = 'interrupted';\n if (activeContext) updateStatus(activeContext);\n persistState();\n }\n\n async function activateFlavor(\n ctx: ExtensionContext,\n flavor: PlanningFlavor,\n trigger: PlanModeTrigger,\n restoring: boolean,\n ): Promise<void> {\n activeContext = ctx;\n if (enabled) {\n if (activeFlavor === flavor) {\n reportCurrentFlavor(ctx);\n return;\n }\n if (activeFlavor === 'fable') await cancelFableOperation(`Leaving Fable for plan:${flavor}.`);\n activeFlavor = flavor;\n updateCapabilityCeiling();\n pi.setActiveTools(\n planningToolsForFlavor(\n planSnapshot?.tools ?? [],\n pi.getActiveTools(),\n pi.getAllTools().map((tool) => tool.name),\n flavor,\n diagnosticTools,\n ),\n );\n updateStatus(ctx);\n persistState();\n void telemetry.recordEvent(PLAN_EVENT.modeEnabled, {\n [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n [PLAN_FLAVOR_ATTRIBUTE]: flavor,\n 'plan.tool.count': pi.getActiveTools().length,\n });\n return;\n }\n\n let nextPlanningConfig: PlanningModeConfig | undefined;\n try {\n nextPlanningConfig = planningConfigProvider();\n } catch (error) {\n void telemetry.recordError(PLAN_EVENT.configLoadFailed, error, { [PLAN_TRIGGER_ATTRIBUTE]: trigger });\n throw error;\n }\n\n if (!restoring) {\n currentPlan = undefined;\n planReadyForReview = false;\n awaitingVoicePlanDecision = false;\n activePlanId = createPlanIdentifier();\n interruptedFableStage = undefined;\n fableStage = 'idle';\n } else {\n activePlanId ??= createPlanIdentifier();\n }\n activePlanningConfig = nextPlanningConfig;\n planSnapshot ??= {\n tools: [...pi.getActiveTools()],\n ...(ctx.model ? { model: { provider: ctx.model.provider, id: ctx.model.id } } : {}),\n thinking: pi.getThinkingLevel(),\n };\n enabled = true;\n activeFlavor = flavor;\n pi.setActiveTools(\n planningToolsForFlavor(\n planSnapshot.tools,\n pi.getActiveTools(),\n pi.getAllTools().map((tool) => tool.name),\n flavor,\n diagnosticTools,\n ),\n );\n updateCapabilityCeiling();\n await applyMainPlanningConfig(ctx);\n updateStatus(ctx);\n persistState();\n void telemetry.recordEvent(PLAN_EVENT.modeEnabled, {\n [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n [PLAN_FLAVOR_ATTRIBUTE]: flavor,\n 'plan.tool.count': pi.getActiveTools().length,\n ...(activePlanningConfig?.main?.model ? { [PLAN_MODEL_ATTRIBUTE]: activePlanningConfig.main.model } : {}),\n ...(activePlanningConfig?.main?.thinking ? { 'plan.thinking': activePlanningConfig.main.thinking } : {}),\n });\n }\n\n async function exitPlanMode(ctx: ExtensionContext, trigger: PlanModeTrigger): Promise<boolean> {\n if (!enabled) {\n reportCurrentFlavor(ctx);\n return false;\n }\n await cancelFableOperation('Plan mode is exiting.');\n const snapshot = planSnapshot;\n const restored = await restoreMainAgent(ctx, snapshot);\n if (!restored) {\n ctx.ui.notify('Previous model was not restored. Plan mode remains read-only.', WARNING_STYLE);\n updateStatus(ctx);\n persistState();\n void telemetry.recordWarning(PLAN_EVENT.modeDisabled, 'Plan mode restoration failed.', {\n [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n [PLAN_FLAVOR_ATTRIBUTE]: activeFlavor ?? 'unknown',\n 'plan.restored': false,\n });\n return false;\n }\n\n const hadPlan = Boolean(currentPlan);\n pi.setActiveTools(\n restoreSnapshotTools(\n snapshot?.tools ?? [],\n pi.getActiveTools(),\n pi.getAllTools().map((tool) => tool.name),\n ),\n );\n capabilityCeiling?.dispose();\n capabilityCeiling = undefined;\n enabled = false;\n activeFlavor = undefined;\n activePlanningConfig = undefined;\n awaitingVoicePlanDecision = false;\n planSnapshot = undefined;\n debugEvidence = undefined;\n fableStage = 'idle';\n interruptedFableStage = undefined;\n updateStatus(ctx);\n persistState();\n void telemetry.recordEvent(PLAN_EVENT.modeDisabled, {\n [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n [PLAN_FLAVOR_ATTRIBUTE]: 'normal',\n 'plan.written': hadPlan,\n 'plan.restored': true,\n });\n return true;\n }\n\n const planVoiceContributions: Array<{ dispose(): void }> = [];\n if (doomIntegrations) {\n const voiceHost = pi as unknown as Parameters<typeof registerVoiceToolContribution<ExtensionContext>>[0];\n const assertVoiceTransitionNotCancelled = (signal: AbortSignal): void => {\n if (signal.aborted) {\n throw signal.reason instanceof Error ? signal.reason : new Error('Plan voice transition was cancelled.');\n }\n };\n const activatePlanVoiceTool: VoiceToolDefinition<ExtensionContext> = {\n descriptor: {\n source: PLAN_VOICE_SOURCE,\n id: PLAN_VOICE_ACTIVATE_ID,\n name: PLAN_VOICE_ACTIVATE_NAME,\n label: 'Activate Plan',\n description: 'Activate or switch the serialized read-only planning mode flavor.',\n order: 10,\n inputSchema: PLAN_VOICE_ACTIVATE_INPUT_SCHEMA,\n resultSchema: PLAN_VOICE_RESULT_SCHEMA,\n },\n execute(input, execution) {\n const flavor = parsePlanningFlavor(isRecord(input) ? input.flavor : undefined);\n if (!flavor) throw new Error('A valid plan flavor is required.');\n assertVoiceTransitionNotCancelled(execution.signal);\n return queueTransition(async () => {\n assertVoiceTransitionNotCancelled(execution.signal);\n const previousEnabled = enabled;\n const previousFlavor = activeFlavor;\n await activateFlavor(execution.context, flavor, PLAN_MODE_TRIGGER_VOICE_TOOL, false);\n return {\n active: enabled,\n flavor: activeFlavor ?? flavor,\n changed: previousEnabled !== enabled || previousFlavor !== activeFlavor,\n };\n });\n },\n };\n const exitPlanVoiceTool: VoiceToolDefinition<ExtensionContext> = {\n descriptor: {\n source: PLAN_VOICE_SOURCE,\n id: PLAN_VOICE_EXIT_ID,\n name: PLAN_VOICE_EXIT_NAME,\n label: 'Exit Plan',\n description: 'Exit read-only planning mode and restore the previous agent configuration.',\n order: 20,\n inputSchema: PLAN_VOICE_EXIT_INPUT_SCHEMA,\n resultSchema: PLAN_VOICE_RESULT_SCHEMA,\n },\n execute(_input, execution) {\n assertVoiceTransitionNotCancelled(execution.signal);\n return queueTransition(async () => {\n assertVoiceTransitionNotCancelled(execution.signal);\n const previousEnabled = enabled;\n const exited = await exitPlanMode(execution.context, PLAN_MODE_TRIGGER_VOICE_TOOL);\n return {\n active: enabled,\n flavor: activeFlavor ?? null,\n changed: previousEnabled !== enabled || exited,\n };\n });\n },\n };\n planVoiceContributions.push(registerVoiceToolContribution<ExtensionContext>(voiceHost, activatePlanVoiceTool));\n planVoiceContributions.push(registerVoiceToolContribution<ExtensionContext>(voiceHost, exitPlanVoiceTool));\n }\n\n const fableFlow = createFablePlanFlow({\n broker: fableBroker,\n isAuthorized: () => enabled && activeFlavor === 'fable' && isFableBrokerAvailable(),\n onStage: (stage) => {\n fableStage = stage;\n if (stage === 'completed' || stage === 'failed' || stage === 'cancelled') interruptedFableStage = undefined;\n if (activeContext) updateStatus(activeContext);\n if (enabled) persistState();\n },\n onError: (error) => {\n void telemetry.recordError(PLAN_EVENT.modeEnabled, error, {\n [PLAN_FLAVOR_ATTRIBUTE]: 'fable',\n 'plan.fable.reason': 'flow_error',\n });\n },\n });\n\n pi.registerTool({\n name: RECORD_DEBUG_EVIDENCE_TOOL,\n label: 'Record Debug Evidence',\n description: 'Record optional bounded debug evidence while planning a repository fix.',\n promptSnippet: 'Record the issue and any relevant reproduction, logs, traces, process output, or browser evidence',\n parameters: {\n type: 'object',\n properties: {\n issue: { type: 'string' },\n expectedBehavior: { type: 'string' },\n reproductionAttempt: { type: 'string' },\n actualBehavior: { type: 'string' },\n logs: { type: 'array', items: { type: 'string' } },\n correlatedTraceEvidence: { type: 'array', items: { type: 'string' } },\n processOutput: { type: 'array', items: { type: 'string' } },\n browserConsoleEvidence: { type: 'array', items: { type: 'string' } },\n correlationIds: { type: 'array', items: { type: 'string' } },\n timestamps: { type: 'array', items: { type: 'string' } },\n verifiedFacts: { type: 'array', items: { type: 'string' } },\n hypotheses: { type: 'array', items: { type: 'string' } },\n unavailableEvidence: { type: 'array', items: { type: 'string' } },\n },\n required: ['issue'],\n additionalProperties: false,\n },\n async execute(_toolCallId, params) {\n if (!enabled || activeFlavor !== 'debug') {\n return { content: [{ type: 'text', text: 'Debug planning is not active.' }], details: { recorded: false } };\n }\n try {\n debugEvidence = parseDebugEvidencePacket(params);\n } catch (error) {\n void telemetry.recordWarning(PLAN_EVENT.modeEnabled, error, {\n [PLAN_FLAVOR_ATTRIBUTE]: 'debug',\n 'plan.debug.reason': 'invalid_evidence',\n });\n throw error;\n }\n if (activeContext) updateStatus(activeContext);\n return {\n content: [{ type: 'text', text: 'Debug evidence recorded as optional planning context.' }],\n details: { recorded: true },\n };\n },\n });\n\n pi.registerTool({\n name: RUN_FABLE_PLAN_TOOL,\n label: 'Run Fable Plan',\n description: 'Send a bounded, sanitized planning packet to the local Fable broker for one repository-aware draft.',\n promptSnippet: 'Run the local Fable draft with the bounded planning packet',\n parameters: {\n type: 'object',\n properties: {\n goal: { type: 'array', items: { type: 'string' } },\n constraints: { type: 'array', items: { type: 'string' } },\n decisions: { type: 'array', items: { type: 'string' } },\n verifiedFindings: { type: 'array', items: { type: 'object' } },\n inferredFindings: { type: 'array', items: { type: 'string' } },\n unresolvedQuestions: { type: 'array', items: { type: 'string' } },\n currentPlan: { type: 'string' },\n },\n additionalProperties: false,\n },\n async execute(_toolCallId, params, signal) {\n if (!enabled || activeFlavor !== 'fable') {\n return {\n content: [{ type: 'text', text: 'Fable planning is not active.' }],\n details: { started: false } as Record<string, unknown>,\n };\n }\n if (!isFableBrokerAvailable()) {\n return {\n content: [{ type: 'text', text: 'The local Fable broker is unavailable. Fable planning remains disabled.' }],\n details: { started: false, errorCode: 'broker_unavailable' } as Record<string, unknown>,\n };\n }\n const operation = fableFlow.run(params, signal);\n activeFableRun = operation;\n try {\n const result = await operation;\n const text = result.draft\n ? `Fable draft:\\n${result.draft}`\n : `Fable planning ${result.status}: ${result.errorCode ?? 'no output'}.`;\n return {\n content: [{ type: 'text', text }],\n details: { ...result, started: true } as Record<string, unknown>,\n };\n } finally {\n if (activeFableRun === operation) activeFableRun = undefined;\n }\n },\n });\n\n pi.registerTool({\n name: WRITE_PLAN_TOOL,\n label: 'Write Plan',\n description:\n 'After presenting the complete implementation plan as Markdown in chat, save that visible plan to a unique Markdown file in the configured plans directory.',\n promptSnippet: 'Save the implementation plan already presented in chat to the configured plans directory',\n parameters: { type: 'object', properties: {}, additionalProperties: false },\n async execute(toolCallId, _params, signal, onUpdate, ctx) {\n if (!enabled) {\n return {\n content: [{ type: 'text', text: 'Plan mode is disabled. Use normal file tools instead.' }],\n details: { written: false },\n };\n }\n const content = visiblePlanForToolCall(ctx.sessionManager.getBranch(), toolCallId);\n if (!content) {\n const error = new Error(\n 'Present the complete implementation plan as visible Markdown in chat before calling write_plan.',\n );\n void telemetry.recordError(PLAN_EVENT.writePlanFailed, error, { 'plan.reason': 'missing_visible_plan' });\n throw error;\n }\n\n const startedAt = Date.now();\n const repoRoot = getHarnessState().root ?? ctx.cwd;\n const plansDirectory = resolvePlanningPlansDirectory(\n activePlanningConfig?.plansDirectory,\n repoRoot,\n os.homedir(),\n );\n const sessionId = planSessionIdentifier(ctx.sessionManager.getSessionId());\n activePlanId ??= createPlanIdentifier();\n const storedPlanPath =\n currentPlan?.planId === activePlanId && path.dirname(currentPlan.path) === plansDirectory\n ? currentPlan.path\n : undefined;\n const title = planTitleSlug(content);\n let planId = activePlanId;\n let planPath = storedPlanPath ?? path.join(plansDirectory, `${title}--${planId}.md`);\n const timeoutController = new AbortController();\n const timeoutError = new Error(`Writing ${planPath} timed out after ${WRITE_PLAN_TIMEOUT_MS}ms.`);\n const timeout = setTimeout(() => timeoutController.abort(timeoutError), WRITE_PLAN_TIMEOUT_MS);\n const writeSignal = signal ? AbortSignal.any([signal, timeoutController.signal]) : timeoutController.signal;\n let phase: PlanWritePhase = 'checking';\n const reportPhase = (): void => {\n onUpdate?.({\n content: [{ type: 'text', text: `${phase === 'checking' ? 'Checking' : 'Writing'} ${planPath}...` }],\n details: { phase, path: planPath, startedAt },\n });\n };\n const recordRefusal = (refusal: string, message: string): void => {\n void telemetry.recordWarning(PLAN_EVENT.writePlanUnsafePath, message, {\n 'plan.phase': phase,\n 'plan.refusal': refusal,\n });\n };\n\n try {\n reportPhase();\n try {\n await waitForAbortable(\n () => fs.promises.mkdir(plansDirectory, { recursive: true, mode: PRIVATE_DIRECTORY_MODE }),\n writeSignal,\n );\n } catch (error) {\n if (writeSignal.aborted) throw abortReason(writeSignal);\n throw new Error(`Could not create the configured plans directory ${plansDirectory}.`, { cause: error });\n }\n const directoryStats = await waitForAbortable(() => fs.promises.lstat(plansDirectory), writeSignal);\n const resolvedPlansDirectory = await waitForAbortable(() => fs.promises.realpath(plansDirectory), writeSignal);\n if (directoryStats.isSymbolicLink() || !directoryStats.isDirectory()) {\n recordRefusal('unsafe_plans_directory', 'Refused to write the plan because the configured path is unsafe.');\n return {\n content: [{ type: 'text', text: 'Refused to write the plan because the configured path is unsafe.' }],\n details: { written: false, path: planPath, phase, durationMs: Date.now() - startedAt },\n };\n }\n\n phase = 'writing';\n reportPhase();\n let planFile: Awaited<ReturnType<typeof fs.promises.open>> | undefined;\n try {\n for (let attempt = 0; attempt < PLAN_ALLOCATION_ATTEMPTS; attempt += 1) {\n try {\n const createFlags = storedPlanPath ? 0 : fs.constants.O_EXCL;\n planFile = await waitForAbortable(\n () =>\n fs.promises.open(\n planPath,\n fs.constants.O_CREAT |\n fs.constants.O_WRONLY |\n fs.constants.O_NONBLOCK |\n fs.constants.O_NOFOLLOW |\n createFlags,\n PRIVATE_FILE_MODE,\n ),\n writeSignal,\n );\n break;\n } catch (error) {\n const collision =\n !storedPlanPath && error instanceof Error && 'code' in error && String(error.code) === 'EEXIST';\n if (!collision || attempt === PLAN_ALLOCATION_ATTEMPTS - 1) throw error;\n planId = createPlanIdentifier();\n activePlanId = planId;\n planPath = path.join(plansDirectory, `${title}--${planId}.md`);\n persistState();\n }\n }\n if (!planFile) throw new Error(`Could not allocate a unique plan filename in ${plansDirectory}.`);\n const resolvedAfterOpen = await waitForAbortable(() => fs.promises.realpath(plansDirectory), writeSignal);\n const stats = await waitForAbortable(() => planFile!.stat(), writeSignal);\n if (resolvedAfterOpen !== resolvedPlansDirectory || !stats.isFile() || stats.nlink !== 1) {\n recordRefusal('invalid_destination', INVALID_PLAN_DESTINATION);\n return {\n content: [{ type: 'text', text: INVALID_PLAN_DESTINATION }],\n details: { written: false, path: planPath, phase, durationMs: Date.now() - startedAt },\n };\n }\n await waitForAbortable(() => planFile!.truncate(0), writeSignal);\n await waitForAbortable(\n () => planFile!.writeFile(content, { encoding: 'utf8', signal: writeSignal }),\n writeSignal,\n );\n } catch (error) {\n if (error instanceof Error && 'code' in error && ['EISDIR', 'ELOOP', 'ENXIO'].includes(String(error.code))) {\n recordRefusal('invalid_destination', INVALID_PLAN_DESTINATION);\n return {\n content: [{ type: 'text', text: INVALID_PLAN_DESTINATION }],\n details: { written: false, path: planPath, phase, durationMs: Date.now() - startedAt },\n };\n }\n throw error;\n } finally {\n await planFile?.close();\n }\n currentPlan = { content, path: planPath, sessionId, planId, title, writtenAt: new Date().toISOString() };\n pi.appendEntry(PLAN_DOCUMENT_ENTRY, currentPlan);\n planReadyForReview = true;\n awaitingVoicePlanDecision = false;\n void telemetry.recordEvent(PLAN_EVENT.planWritten, {\n 'plan.written': true,\n 'plan.bytes': Buffer.byteLength(content, 'utf8'),\n 'plan.duration_ms': Date.now() - startedAt,\n 'plan.revised': Boolean(storedPlanPath),\n });\n return {\n content: [{ type: 'text', text: `Wrote implementation plan to ${planPath}.` }],\n details: { written: true, path: planPath, phase, durationMs: Date.now() - startedAt },\n };\n } catch (error) {\n const attributes = {\n 'plan.phase': phase,\n 'plan.duration_ms': Date.now() - startedAt,\n };\n if (timeoutController.signal.aborted && !signal?.aborted) {\n const timedOut = new Error(`write_plan timed out during ${phase} for ${planPath}.`, { cause: error });\n void telemetry.recordError(PLAN_EVENT.writePlanTimedOut, timedOut, {\n ...attributes,\n 'plan.timeout_ms': WRITE_PLAN_TIMEOUT_MS,\n });\n throw timedOut;\n }\n void telemetry.recordError(PLAN_EVENT.writePlanFailed, error, {\n ...attributes,\n 'plan.cancelled': signal?.aborted ?? false,\n });\n throw error;\n } finally {\n clearTimeout(timeout);\n }\n },\n });\n\n async function applyPlanReviewDecision(\n decision: typeof EXIT_PLAN_DECISION | typeof CONTINUE_PLAN_DECISION,\n ctx: ExtensionContext,\n ) {\n void telemetry.recordEvent(PLAN_EVENT.planReviewCompleted, {\n 'plan.outcome': decision === EXIT_PLAN_DECISION ? 'exited' : 'continued',\n });\n if (decision === EXIT_PLAN_DECISION) {\n const exited = await queueTransition(() => exitPlanMode(ctx, PLAN_MODE_TRIGGER_PLAN_APPROVED));\n return {\n content: [\n {\n type: 'text' as const,\n text: exited\n ? 'The user approved exiting plan mode. Full tool access is restored. Begin implementing the approved plan.'\n : 'The previous model could not be restored. Plan mode remains read-only.',\n },\n ],\n details: { exited },\n };\n }\n\n planReadyForReview = false;\n return {\n content: [\n { type: 'text' as const, text: 'The user chose to continue planning. Remain read-only and refine the plan.' },\n ],\n details: { exited: false },\n };\n }\n\n pi.registerTool({\n name: COMPLETE_PLAN_TOOL,\n label: 'Complete Plan',\n description:\n 'Present the saved implementation plan for exit-or-continue approval. Interactive sessions use the normal selector; autonomous voice narrates a plain-text handoff and waits for the next user message.',\n promptSnippet: 'Request explicit exit-or-continue approval after the saved plan has been presented',\n promptGuidelines: [\n 'After write_plan succeeds, call complete_plan without a decision so it can present the review question.',\n 'When autonomous voice returns an awaiting-response result, stop. Interpret the next ordinary user message, then call complete_plan again with decision \"exit\" or \"continue\".',\n `Never pass decision \"${EXIT_PLAN_DECISION}\" without the user explicitly choosing \"${EXIT_PLAN_MODE_CHOICE}\".`,\n ],\n parameters: {\n type: 'object',\n properties: {\n decision: { type: 'string', enum: [EXIT_PLAN_DECISION, CONTINUE_PLAN_DECISION] },\n },\n additionalProperties: false,\n },\n async execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n if (!enabled) {\n return {\n content: [{ type: 'text', text: 'Plan mode is already disabled.' }],\n details: { exited: false },\n };\n }\n if (!planReadyForReview) {\n return {\n content: [\n {\n type: 'text',\n text: 'Present the complete plan in chat and save it with write_plan before requesting approval.',\n },\n ],\n details: { exited: false },\n };\n }\n if (!ctx.hasUI) {\n void telemetry.recordEvent(PLAN_EVENT.planReviewCompleted, { 'plan.outcome': 'no_ui' });\n return {\n content: [\n {\n type: 'text',\n text: 'The plan is complete, but this run cannot ask the user interactively. Remain in plan mode until the user uses SPC p e.',\n },\n ],\n details: { exited: false },\n };\n }\n\n const decision = isRecord(params) ? params.decision : undefined;\n const hasDecision = decision === EXIT_PLAN_DECISION || decision === CONTINUE_PLAN_DECISION;\n if (awaitingVoicePlanDecision) {\n if (!hasDecision) {\n throw new Error('The narrated plan review is waiting for an explicit exit or continue decision.');\n }\n awaitingVoicePlanDecision = false;\n return applyPlanReviewDecision(decision, ctx);\n }\n if (decision !== undefined) {\n throw new Error('Call complete_plan without a decision before submitting a narrated plan-review answer.');\n }\n\n const voiceResult = voiceQuestionHandoff?.handoff(PLAN_REVIEW_QUESTION);\n if (voiceResult) {\n awaitingVoicePlanDecision = true;\n return buildVoiceToolResult(voiceResult);\n }\n\n const choice = await ctx.ui.select('Plan complete. What would you like to do?', [\n EXIT_PLAN_MODE_CHOICE,\n CONTINUE_PLANNING_CHOICE,\n ]);\n return applyPlanReviewDecision(\n choice === EXIT_PLAN_MODE_CHOICE ? EXIT_PLAN_DECISION : CONTINUE_PLAN_DECISION,\n ctx,\n );\n },\n });\n\n if (doomIntegrations) {\n registerDoomLeaderActionHandlers(pi, {\n source: PLAN_LEADER_SOURCE,\n handlers: {\n 'plan.normal': () => {\n const ctx = activeContext;\n return ctx\n ? queueTransition(() => activateFlavor(ctx, 'normal', PLAN_MODE_TRIGGER_LEADER, false))\n : undefined;\n },\n 'plan.exit': () => {\n const ctx = activeContext;\n return ctx\n ? queueTransition(async () => {\n await exitPlanMode(ctx, PLAN_MODE_TRIGGER_LEADER);\n })\n : undefined;\n },\n 'plan.debug': () => {\n const ctx = activeContext;\n return ctx ? queueTransition(() => activateFlavor(ctx, 'debug', PLAN_MODE_TRIGGER_LEADER, false)) : undefined;\n },\n 'plan.fable': () => {\n const ctx = activeContext;\n return ctx ? queueTransition(() => activateFlavor(ctx, 'fable', PLAN_MODE_TRIGGER_LEADER, false)) : undefined;\n },\n },\n onError: (error, actionName) => {\n if (activeContext?.hasUI) {\n activeContext.ui.notify(`Leader action ${actionName} failed. Plan mode remains read-only.`, WARNING_STYLE);\n }\n void telemetry.recordError(PLAN_EVENT.modeEnabled, error, {\n [PLAN_TRIGGER_ATTRIBUTE]: PLAN_MODE_TRIGGER_LEADER,\n 'plan.action': actionName,\n });\n },\n });\n }\n\n pi.on('tool_call', async (event: ToolCallEvent, ctx) => {\n if (!enabled) return undefined;\n const isFlavorTool =\n (activeFlavor === 'debug' &&\n (event.toolName === RECORD_DEBUG_EVIDENCE_TOOL || diagnosticTools.has(event.toolName))) ||\n (activeFlavor === 'fable' && event.toolName === RUN_FABLE_PLAN_TOOL);\n if (!PLAN_MODE_PARENT_TOOLS.has(event.toolName) && !isFlavorTool) {\n return { block: true, reason: `Plan mode blocks the ${event.toolName} tool. Use SPC p e to restore access.` };\n }\n const model = planningSubagentModel(activePlanningConfig?.subagents, ctx.model);\n if (event.toolName === TASK_TOOL) {\n if (model) configurePlanningTaskInput(event.input as MutableTaskInput, model);\n return undefined;\n }\n if (event.toolName !== SUBAGENT_TOOL) return undefined;\n\n const input = event.input as MutableSubagentInput;\n if (isBlockedSubagentManagementAction(input.action)) {\n return {\n block: true,\n reason: `Plan mode blocks subagent management action '${input.action}'. Use SPC p e first.`,\n };\n }\n constrainSubagentInput(input);\n if (model) configurePlanningSubagentInput(input, model);\n return undefined;\n });\n\n pi.on('before_agent_start', async (event, ctx) => {\n const sections: string[] = [];\n if (enabled) {\n const repoRoot = getHarnessState().root ?? ctx.cwd;\n const plansDirectory = resolvePlanningPlansDirectory(\n activePlanningConfig?.plansDirectory,\n repoRoot,\n os.homedir(),\n );\n sections.push(\n `[PLAN MODE ACTIVE]\\nYou are in repository read-only plan mode. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\nExplore the codebase and produce a concrete implementation plan. For every plan, first call subagent with action \"agents\", cluster the exploration by independent domain, subsystem, or integration boundary, and create a provisional task graph with the task tool. Select specialized agents by matching their names and descriptions to each cluster. Assign every unblocked delegated task through the task tool, and use a one-shot inlineAgent with a focused systemPrompt when no discovered specialist fits. Treat the initial graph as provisional, not as a fixed contract. After findings arrive, review the entire graph at least once and perform one to three review passes in total. In each pass, use the evidence to add, rewrite, delete, cancel, reassign, or change blockedBy relationships for tasks when warranted. Do not keep following tasks that new information has made stale. Stop revising early when the graph is stable, or after the third pass.\\n\\nEvery plan must end with a delegated planning-draft stage blocked by all exploration and decision tasks. A single-boundary plan gets one planning draft. A complex plan spanning multiple subsystems, domains, packages, apps, or integration boundaries gets two planning drafts concurrently. Use three concurrent drafts instead when the work is cross-layer, migration-sensitive, security-sensitive, or similarly high risk. Assign each draft through the task tool to the discovered \"planner\" agent with context \"fork\" so it receives the conversation and gathered evidence. If the planner agent is unavailable, assign the same draft task through the task tool with a focused inlineAgent. All children receive read, Bash, grep, find, ls, and configured MCP tools with artifacts disabled. Bash and MCP tools are for read-only inspection and must not modify files, external systems, or repository state. Doom Team runs asynchronously, so do not poll. After launch, continue non-overlapping exploration or end your turn; completion notifications wake the parent session.\\n\\nAfter all planning drafts complete, the main agent must compare the candidates, pick the strongest draft, cross-check it against the gathered evidence and the other drafts, resolve conflicts and gaps, and ask the user only for product decisions. A child produces the draft, but the main agent owns and synthesizes the final plan. Do not modify files or repository state except through write_plan. Start the final plan with a meaningful Markdown H1 because write_plan derives the filename from it. Present the complete plan as visible Markdown in chat, then call write_plan with no arguments. After write_plan succeeds, clear the completed durable task graph and call complete_plan without a decision. In an interactive text session, complete_plan uses the normal exit-or-continue selector. Under autonomous voice, it displays and narrates the choices without opening a blocking dialog, then ends the turn. Interpret the user's next ordinary message and call complete_plan again with decision \"exit\" or \"continue\". Do not exit plan mode without explicit approval.`,\n buildFlavorPlanningPrompt(activeFlavor!, plansDirectory, debugEvidence, fableStage),\n );\n }\n if (currentPlan) {\n sections.push(`[CURRENT PLAN]\\nSource: ${currentPlan.path}\\n\\n${currentPlan.content}`);\n }\n if (sections.length === 0) return undefined;\n return { systemPrompt: `${event.systemPrompt}\\n\\n${sections.join('\\n\\n')}` };\n });\n\n pi.on('context', async (event) => ({\n messages: event.messages.filter((message) => {\n const custom = message as { customType?: string };\n return custom.customType !== PLAN_MODE_CONTEXT;\n }),\n }));\n\n pi.on('session_start', async (_event, ctx) => {\n const entries = ctx.sessionManager.getEntries();\n const state = entries\n .flatMap((entry) =>\n entry.type === 'custom' && entry.customType === PLAN_MODE_ENTRY ? [parsePersistedPlanState(entry.data)] : [],\n )\n .filter((value): value is PersistedPlanModeState => value !== undefined)\n .at(-1);\n const piSessionId = ctx.sessionManager.getSessionId();\n const sessionId = planSessionIdentifier(piSessionId);\n voiceQuestionHandoff?.dispose();\n voiceQuestionHandoff = doomIntegrations\n ? createVoiceQuestionHandoff({ bus: pi.events, source: PLAN_LEADER_SOURCE, sessionId: piSessionId })\n : undefined;\n const storedPlan = entries\n .flatMap((entry) =>\n entry.type === 'custom' && entry.customType === PLAN_DOCUMENT_ENTRY ? [parsePlanDocument(entry.data)] : [],\n )\n .filter((value): value is PlanDocument => value !== undefined)\n .at(-1);\n\n const snapshotFromPreviousSession = planSnapshot;\n capabilityCeiling?.dispose();\n capabilityCeiling = undefined;\n currentPlan = storedPlan?.sessionId === sessionId ? storedPlan : undefined;\n activePlanId = state?.planId ?? currentPlan?.planId;\n planReadyForReview = false;\n awaitingVoicePlanDecision = false;\n activePlanningConfig = undefined;\n debugEvidence = undefined;\n enabled = false;\n activeFlavor = undefined;\n // A session that restores nothing never reaches updateStatus, and the menu\n // would otherwise still offer the exit the previous session left on it.\n updateLeader();\n planSnapshot = state?.originalSnapshot;\n interruptedFableStage = state?.interruptedFableStage;\n fableStage = interruptedFableStage ? 'interrupted' : 'idle';\n activeContext = ctx;\n if (state?.activeFlavor) {\n await activateFlavor(ctx, state.activeFlavor, PLAN_MODE_TRIGGER_SESSION_RESTORE, true);\n } else {\n const snapshotToRestore = state?.originalSnapshot ?? snapshotFromPreviousSession;\n if (snapshotToRestore) {\n const restored = await restoreMainAgent(ctx, snapshotToRestore);\n if (restored) {\n pi.setActiveTools(\n restoreSnapshotTools(\n snapshotToRestore.tools,\n pi.getActiveTools(),\n pi.getAllTools().map((tool) => tool.name),\n ),\n );\n }\n } else {\n pi.setActiveTools(\n pi\n .getActiveTools()\n .filter(\n (name) =>\n name !== COMPLETE_PLAN_TOOL &&\n name !== WRITE_PLAN_TOOL &&\n name !== RECORD_DEBUG_EVIDENCE_TOOL &&\n name !== RUN_FABLE_PLAN_TOOL,\n ),\n );\n }\n planSnapshot = undefined;\n updateStatus(ctx);\n }\n });\n\n pi.on('session_shutdown', async (_event, ctx) => {\n await cancelFableOperation('Plan host session is shutting down.');\n if (enabled && planSnapshot) {\n const restored = await restoreMainAgent(ctx, planSnapshot);\n if (restored) {\n pi.setActiveTools(\n restoreSnapshotTools(\n planSnapshot.tools,\n pi.getActiveTools(),\n pi.getAllTools().map((tool) => tool.name),\n ),\n );\n }\n }\n capabilityCeiling?.dispose();\n capabilityCeiling = undefined;\n voiceQuestionHandoff?.dispose();\n voiceQuestionHandoff = undefined;\n awaitingVoicePlanDecision = false;\n planConfigContribution.dispose();\n for (const contribution of planVoiceContributions) contribution.dispose();\n activeContext = undefined;\n await telemetry.shutdown();\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const e=[`issue`,`expectedBehavior`,`reproductionAttempt`,`actualBehavior`,`logs`,`correlatedTraceEvidence`,`processOutput`,`browserConsoleEvidence`,`correlationIds`,`timestamps`,`verifiedFacts`,`hypotheses`,`unavailableEvidence`];function t(t){return e.flatMap(e=>{let n=t[e];return Array.isArray(n)&&n.length===0||typeof n==`string`&&n.length===0?[]:`${e}: ${Array.isArray(n)?n.join(` | `):n}`}).join(`
|
|
2
|
+
`)}function n(e){return`[PLAN MODE ACTIVE: NORMAL]\nYou are in repository read-only normal planning. The dedicated write_plan tool may write one unique Markdown plan file under ${e}.\n\nExplore the codebase and produce a concrete implementation plan. For every plan, first call subagent with action "agents", cluster exploration by independent domain, subsystem, or integration boundary, and create a provisional task graph with the task tool. Select specialized agents by matching their names and descriptions to each cluster. Assign every unblocked delegated task through the task tool, and use a one-shot inlineAgent with a focused systemPrompt when no discovered specialist fits. Treat the initial graph as provisional, not as a fixed contract. After findings arrive, review the entire graph at least once and perform one to three review passes in total. In each pass, use evidence to add, rewrite, delete, cancel, reassign, or change blockedBy relationships for tasks when warranted. Do not keep following tasks that new information has made stale. Stop revising early when the graph is stable, or after the third pass.\n\nEvery plan must end with a delegated planning-draft stage blocked by all exploration and decision tasks. A single-boundary plan gets one planning draft. A complex plan spanning multiple subsystems, domains, packages, apps, or integration boundaries gets two planning drafts concurrently. Use three concurrent drafts instead when the work is cross-layer, migration-sensitive, security-sensitive, or similarly high risk. Assign each draft through the task tool to the discovered planner agent with context "fork" so it receives the conversation and gathered evidence. If the planner agent is unavailable, assign the same draft task through the task tool with a focused inlineAgent. All children receive read, Bash, grep, find, ls, and configured MCP tools with artifacts disabled. Bash and MCP tools are for read-only inspection and must not modify files, external systems, or repository state. Doom Team runs asynchronously, so do not poll. After launch, continue non-overlapping exploration or end your turn; completion notifications wake the parent session.\n\nAfter all planning drafts complete, compare the candidates, pick the strongest draft, cross-check it against gathered evidence and the other drafts, resolve conflicts and gaps, and ask the user only for product decisions. A child produces the draft, but the main agent owns and synthesizes the final plan. Do not modify files or repository state except through write_plan. Start the final plan with a meaningful Markdown H1 because write_plan derives the filename from it. Present the complete plan as visible Markdown, then call write_plan with no arguments. After write_plan succeeds, clear the completed durable task graph and call complete_plan so the user can review the plan and choose whether to begin implementation or continue planning. Do not exit plan mode without that approval.`}function r(e,n){return`[PLAN MODE ACTIVE: DEBUG]\nYou are in repository read-only adaptive debug planning. The dedicated write_plan tool may write one unique Markdown plan file under ${e}.\n\n${n?`A bounded debug evidence packet is recorded below. Cite its verified facts when making source findings. Keep verified facts and hypotheses distinct. Do not claim a verified root cause when reproduction or supporting evidence is unavailable.\n\n[DEBUG EVIDENCE]\n${t(n)}`:`No structured debug evidence packet is recorded yet. First understand the reported issue, then gather only the evidence relevant to it. Recording evidence is optional and must not block source exploration, delegation, writing a plan, or completing a plan.`}\n\nUse the exact read-only tools available for the issue. Bash is available for repository inspection, but commands must not modify files or repository state. Treat unavailable evidence as unavailable, never invent its contents, and keep verified facts separate from hypotheses. ${n?`The final plan must separate verified facts from hypotheses and must not present an unsupported root cause as verified.`:`You may call record_debug_evidence when structured notes would help, but continue investigating without it when it is not relevant.`}`}function i(e,t){return`[PLAN MODE ACTIVE: FABLE]\nYou are in repository read-only Fable planning. Pi owns final verification and synthesis. The dedicated write_plan tool may write one unique Markdown plan file under ${e}.\n\nUse Pi read-only exploration first. When the bounded packet is ready, call run_fable_plan. Fable runs one fresh draft with repository inspection access and returns untrusted text. Cross-check every Fable claim against repository evidence, keep verified findings separate from explicitly inferred findings, resolve conflicts yourself, and present the final visible plan before calling write_plan. Never treat Fable output as repository evidence and never expose credentials, transcripts, commands, tools, or session data in the packet.\n\nCurrent Fable stage: ${t}. An interrupted stage is not relaunched automatically.`}function a(e,t,a,o){return e===`debug`?r(t,a):e===`fable`?i(t,o):n(t)}exports.buildDebugPlanningPrompt=r,exports.buildFablePlanningPrompt=i,exports.buildFlavorPlanningPrompt=a,exports.buildNormalPlanningPrompt=n;
|
|
3
|
+
//# sourceMappingURL=prompts.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.cjs","names":[],"sources":["../../../src/services/plan/prompts.ts"],"sourcesContent":["export type PlanningFlavor = 'normal' | 'debug' | 'fable';\n\nexport interface DebugEvidencePacket {\n issue: string;\n expectedBehavior: string;\n reproductionAttempt: string;\n actualBehavior: string;\n logs: string[];\n correlatedTraceEvidence: string[];\n processOutput: string[];\n browserConsoleEvidence: string[];\n correlationIds: string[];\n timestamps: string[];\n verifiedFacts: string[];\n hypotheses: string[];\n unavailableEvidence: string[];\n}\n\nconst EVIDENCE_FIELDS: readonly (keyof DebugEvidencePacket)[] = [\n 'issue',\n 'expectedBehavior',\n 'reproductionAttempt',\n 'actualBehavior',\n 'logs',\n 'correlatedTraceEvidence',\n 'processOutput',\n 'browserConsoleEvidence',\n 'correlationIds',\n 'timestamps',\n 'verifiedFacts',\n 'hypotheses',\n 'unavailableEvidence',\n];\n\nfunction evidenceLines(packet: DebugEvidencePacket): string {\n return EVIDENCE_FIELDS.flatMap((field) => {\n const value = packet[field];\n if (Array.isArray(value) && value.length === 0) return [];\n if (typeof value === 'string' && value.length === 0) return [];\n return `${field}: ${Array.isArray(value) ? value.join(' | ') : value}`;\n }).join('\\n');\n}\n\nexport function buildNormalPlanningPrompt(plansDirectory: string): string {\n return `[PLAN MODE ACTIVE: NORMAL]\\nYou are in repository read-only normal planning. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\nExplore the codebase and produce a concrete implementation plan. For every plan, first call subagent with action \"agents\", cluster exploration by independent domain, subsystem, or integration boundary, and create a provisional task graph with the task tool. Select specialized agents by matching their names and descriptions to each cluster. Assign every unblocked delegated task through the task tool, and use a one-shot inlineAgent with a focused systemPrompt when no discovered specialist fits. Treat the initial graph as provisional, not as a fixed contract. After findings arrive, review the entire graph at least once and perform one to three review passes in total. In each pass, use evidence to add, rewrite, delete, cancel, reassign, or change blockedBy relationships for tasks when warranted. Do not keep following tasks that new information has made stale. Stop revising early when the graph is stable, or after the third pass.\\n\\nEvery plan must end with a delegated planning-draft stage blocked by all exploration and decision tasks. A single-boundary plan gets one planning draft. A complex plan spanning multiple subsystems, domains, packages, apps, or integration boundaries gets two planning drafts concurrently. Use three concurrent drafts instead when the work is cross-layer, migration-sensitive, security-sensitive, or similarly high risk. Assign each draft through the task tool to the discovered planner agent with context \"fork\" so it receives the conversation and gathered evidence. If the planner agent is unavailable, assign the same draft task through the task tool with a focused inlineAgent. All children receive read, Bash, grep, find, ls, and configured MCP tools with artifacts disabled. Bash and MCP tools are for read-only inspection and must not modify files, external systems, or repository state. Doom Team runs asynchronously, so do not poll. After launch, continue non-overlapping exploration or end your turn; completion notifications wake the parent session.\\n\\nAfter all planning drafts complete, compare the candidates, pick the strongest draft, cross-check it against gathered evidence and the other drafts, resolve conflicts and gaps, and ask the user only for product decisions. A child produces the draft, but the main agent owns and synthesizes the final plan. Do not modify files or repository state except through write_plan. Start the final plan with a meaningful Markdown H1 because write_plan derives the filename from it. Present the complete plan as visible Markdown, then call write_plan with no arguments. After write_plan succeeds, clear the completed durable task graph and call complete_plan so the user can review the plan and choose whether to begin implementation or continue planning. Do not exit plan mode without that approval.`;\n}\n\nexport function buildDebugPlanningPrompt(plansDirectory: string, evidence: DebugEvidencePacket | undefined): string {\n const guidance = evidence\n ? `A bounded debug evidence packet is recorded below. Cite its verified facts when making source findings. Keep verified facts and hypotheses distinct. Do not claim a verified root cause when reproduction or supporting evidence is unavailable.\\n\\n[DEBUG EVIDENCE]\\n${evidenceLines(evidence)}`\n : 'No structured debug evidence packet is recorded yet. First understand the reported issue, then gather only the evidence relevant to it. Recording evidence is optional and must not block source exploration, delegation, writing a plan, or completing a plan.';\n return `[PLAN MODE ACTIVE: DEBUG]\\nYou are in repository read-only adaptive debug planning. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\n${guidance}\\n\\nUse the exact read-only tools available for the issue. Bash is available for repository inspection, but commands must not modify files or repository state. Treat unavailable evidence as unavailable, never invent its contents, and keep verified facts separate from hypotheses. ${evidence ? 'The final plan must separate verified facts from hypotheses and must not present an unsupported root cause as verified.' : 'You may call record_debug_evidence when structured notes would help, but continue investigating without it when it is not relevant.'}`;\n}\n\nexport function buildFablePlanningPrompt(plansDirectory: string, stage: string): string {\n return `[PLAN MODE ACTIVE: FABLE]\\nYou are in repository read-only Fable planning. Pi owns final verification and synthesis. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\nUse Pi read-only exploration first. When the bounded packet is ready, call run_fable_plan. Fable runs one fresh draft with repository inspection access and returns untrusted text. Cross-check every Fable claim against repository evidence, keep verified findings separate from explicitly inferred findings, resolve conflicts yourself, and present the final visible plan before calling write_plan. Never treat Fable output as repository evidence and never expose credentials, transcripts, commands, tools, or session data in the packet.\\n\\nCurrent Fable stage: ${stage}. An interrupted stage is not relaunched automatically.`;\n}\n\nexport function buildFlavorPlanningPrompt(\n flavor: PlanningFlavor,\n plansDirectory: string,\n evidence: DebugEvidencePacket | undefined,\n fableStage: string,\n): string {\n if (flavor === 'debug') return buildDebugPlanningPrompt(plansDirectory, evidence);\n if (flavor === 'fable') return buildFablePlanningPrompt(plansDirectory, fableStage);\n return buildNormalPlanningPrompt(plansDirectory);\n}\n"],"mappings":"AAkBA,MAAM,EAA0D,CAC9D,QACA,mBACA,sBACA,iBACA,OACA,0BACA,gBACA,yBACA,iBACA,aACA,gBACA,aACA,sBACD,CAED,SAAS,EAAc,EAAqC,CAC1D,OAAO,EAAgB,QAAS,GAAU,CACxC,IAAM,EAAQ,EAAO,GAGrB,OAFI,MAAM,QAAQ,EAAM,EAAI,EAAM,SAAW,GACzC,OAAO,GAAU,UAAY,EAAM,SAAW,EAAU,EAAE,CACvD,GAAG,EAAM,IAAI,MAAM,QAAQ,EAAM,CAAG,EAAM,KAAK,MAAM,CAAG,KAC/D,CAAC,KAAK;EAAK,CAGf,SAAgB,EAA0B,EAAgC,CACxE,MAAO,4JAA4J,EAAe,ivFAGpL,SAAgB,EAAyB,EAAwB,EAAmD,CAIlH,MAAO,mKAAmK,EAAe,OAHxK,EACb,yQAAyQ,EAAc,EAAS,GAChS,kQACqM,0RAA0R,EAAW,0HAA4H,wIAG5mB,SAAgB,EAAyB,EAAwB,EAAuB,CACtF,MAAO,oMAAoM,EAAe,sjBAAsjB,EAAM,yDAGxxB,SAAgB,EACd,EACA,EACA,EACA,EACQ,CAGR,OAFI,IAAW,QAAgB,EAAyB,EAAgB,EAAS,CAC7E,IAAW,QAAgB,EAAyB,EAAgB,EAAW,CAC5E,EAA0B,EAAe"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/services/plan/prompts.d.ts
|
|
2
|
+
type PlanningFlavor = 'normal' | 'debug' | 'fable';
|
|
3
|
+
interface DebugEvidencePacket {
|
|
4
|
+
issue: string;
|
|
5
|
+
expectedBehavior: string;
|
|
6
|
+
reproductionAttempt: string;
|
|
7
|
+
actualBehavior: string;
|
|
8
|
+
logs: string[];
|
|
9
|
+
correlatedTraceEvidence: string[];
|
|
10
|
+
processOutput: string[];
|
|
11
|
+
browserConsoleEvidence: string[];
|
|
12
|
+
correlationIds: string[];
|
|
13
|
+
timestamps: string[];
|
|
14
|
+
verifiedFacts: string[];
|
|
15
|
+
hypotheses: string[];
|
|
16
|
+
unavailableEvidence: string[];
|
|
17
|
+
}
|
|
18
|
+
declare function buildNormalPlanningPrompt(plansDirectory: string): string;
|
|
19
|
+
declare function buildDebugPlanningPrompt(plansDirectory: string, evidence: DebugEvidencePacket | undefined): string;
|
|
20
|
+
declare function buildFablePlanningPrompt(plansDirectory: string, stage: string): string;
|
|
21
|
+
declare function buildFlavorPlanningPrompt(flavor: PlanningFlavor, plansDirectory: string, evidence: DebugEvidencePacket | undefined, fableStage: string): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt };
|
|
24
|
+
//# sourceMappingURL=prompts.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.cts","names":[],"sources":["../../../src/services/plan/prompts.ts"],"mappings":";KAAY,cAAA;AAAA,UAEK,mBAAA;EACf,KAAA;EACA,gBAAA;EACA,mBAAA;EACA,cAAA;EACA,IAAA;EACA,uBAAA;EACA,aAAA;EACA,sBAAA;EACA,cAAA;EACA,UAAA;EACA,aAAA;EACA,UAAA;EACA,mBAAA;AAAA;AAAA,iBA4Bc,yBAAA,CAA0B,cAAA;AAAA,iBAI1B,wBAAA,CAAyB,cAAA,UAAwB,QAAA,EAAU,mBAAA;AAAA,iBAO3D,wBAAA,CAAyB,cAAA,UAAwB,KAAA;AAAA,iBAIjD,yBAAA,CACd,MAAA,EAAQ,cAAA,EACR,cAAA,UACA,QAAA,EAAU,mBAAA,cACV,UAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/services/plan/prompts.d.ts
|
|
2
|
+
type PlanningFlavor = 'normal' | 'debug' | 'fable';
|
|
3
|
+
interface DebugEvidencePacket {
|
|
4
|
+
issue: string;
|
|
5
|
+
expectedBehavior: string;
|
|
6
|
+
reproductionAttempt: string;
|
|
7
|
+
actualBehavior: string;
|
|
8
|
+
logs: string[];
|
|
9
|
+
correlatedTraceEvidence: string[];
|
|
10
|
+
processOutput: string[];
|
|
11
|
+
browserConsoleEvidence: string[];
|
|
12
|
+
correlationIds: string[];
|
|
13
|
+
timestamps: string[];
|
|
14
|
+
verifiedFacts: string[];
|
|
15
|
+
hypotheses: string[];
|
|
16
|
+
unavailableEvidence: string[];
|
|
17
|
+
}
|
|
18
|
+
declare function buildNormalPlanningPrompt(plansDirectory: string): string;
|
|
19
|
+
declare function buildDebugPlanningPrompt(plansDirectory: string, evidence: DebugEvidencePacket | undefined): string;
|
|
20
|
+
declare function buildFablePlanningPrompt(plansDirectory: string, stage: string): string;
|
|
21
|
+
declare function buildFlavorPlanningPrompt(flavor: PlanningFlavor, plansDirectory: string, evidence: DebugEvidencePacket | undefined, fableStage: string): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt };
|
|
24
|
+
//# sourceMappingURL=prompts.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.mts","names":[],"sources":["../../../src/services/plan/prompts.ts"],"mappings":";KAAY,cAAA;AAAA,UAEK,mBAAA;EACf,KAAA;EACA,gBAAA;EACA,mBAAA;EACA,cAAA;EACA,IAAA;EACA,uBAAA;EACA,aAAA;EACA,sBAAA;EACA,cAAA;EACA,UAAA;EACA,aAAA;EACA,UAAA;EACA,mBAAA;AAAA;AAAA,iBA4Bc,yBAAA,CAA0B,cAAA;AAAA,iBAI1B,wBAAA,CAAyB,cAAA,UAAwB,QAAA,EAAU,mBAAA;AAAA,iBAO3D,wBAAA,CAAyB,cAAA,UAAwB,KAAA;AAAA,iBAIjD,yBAAA,CACd,MAAA,EAAQ,cAAA,EACR,cAAA,UACA,QAAA,EAAU,mBAAA,cACV,UAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const e=[`issue`,`expectedBehavior`,`reproductionAttempt`,`actualBehavior`,`logs`,`correlatedTraceEvidence`,`processOutput`,`browserConsoleEvidence`,`correlationIds`,`timestamps`,`verifiedFacts`,`hypotheses`,`unavailableEvidence`];function t(t){return e.flatMap(e=>{let n=t[e];return Array.isArray(n)&&n.length===0||typeof n==`string`&&n.length===0?[]:`${e}: ${Array.isArray(n)?n.join(` | `):n}`}).join(`
|
|
2
|
+
`)}function n(e){return`[PLAN MODE ACTIVE: NORMAL]\nYou are in repository read-only normal planning. The dedicated write_plan tool may write one unique Markdown plan file under ${e}.\n\nExplore the codebase and produce a concrete implementation plan. For every plan, first call subagent with action "agents", cluster exploration by independent domain, subsystem, or integration boundary, and create a provisional task graph with the task tool. Select specialized agents by matching their names and descriptions to each cluster. Assign every unblocked delegated task through the task tool, and use a one-shot inlineAgent with a focused systemPrompt when no discovered specialist fits. Treat the initial graph as provisional, not as a fixed contract. After findings arrive, review the entire graph at least once and perform one to three review passes in total. In each pass, use evidence to add, rewrite, delete, cancel, reassign, or change blockedBy relationships for tasks when warranted. Do not keep following tasks that new information has made stale. Stop revising early when the graph is stable, or after the third pass.\n\nEvery plan must end with a delegated planning-draft stage blocked by all exploration and decision tasks. A single-boundary plan gets one planning draft. A complex plan spanning multiple subsystems, domains, packages, apps, or integration boundaries gets two planning drafts concurrently. Use three concurrent drafts instead when the work is cross-layer, migration-sensitive, security-sensitive, or similarly high risk. Assign each draft through the task tool to the discovered planner agent with context "fork" so it receives the conversation and gathered evidence. If the planner agent is unavailable, assign the same draft task through the task tool with a focused inlineAgent. All children receive read, Bash, grep, find, ls, and configured MCP tools with artifacts disabled. Bash and MCP tools are for read-only inspection and must not modify files, external systems, or repository state. Doom Team runs asynchronously, so do not poll. After launch, continue non-overlapping exploration or end your turn; completion notifications wake the parent session.\n\nAfter all planning drafts complete, compare the candidates, pick the strongest draft, cross-check it against gathered evidence and the other drafts, resolve conflicts and gaps, and ask the user only for product decisions. A child produces the draft, but the main agent owns and synthesizes the final plan. Do not modify files or repository state except through write_plan. Start the final plan with a meaningful Markdown H1 because write_plan derives the filename from it. Present the complete plan as visible Markdown, then call write_plan with no arguments. After write_plan succeeds, clear the completed durable task graph and call complete_plan so the user can review the plan and choose whether to begin implementation or continue planning. Do not exit plan mode without that approval.`}function r(e,n){return`[PLAN MODE ACTIVE: DEBUG]\nYou are in repository read-only adaptive debug planning. The dedicated write_plan tool may write one unique Markdown plan file under ${e}.\n\n${n?`A bounded debug evidence packet is recorded below. Cite its verified facts when making source findings. Keep verified facts and hypotheses distinct. Do not claim a verified root cause when reproduction or supporting evidence is unavailable.\n\n[DEBUG EVIDENCE]\n${t(n)}`:`No structured debug evidence packet is recorded yet. First understand the reported issue, then gather only the evidence relevant to it. Recording evidence is optional and must not block source exploration, delegation, writing a plan, or completing a plan.`}\n\nUse the exact read-only tools available for the issue. Bash is available for repository inspection, but commands must not modify files or repository state. Treat unavailable evidence as unavailable, never invent its contents, and keep verified facts separate from hypotheses. ${n?`The final plan must separate verified facts from hypotheses and must not present an unsupported root cause as verified.`:`You may call record_debug_evidence when structured notes would help, but continue investigating without it when it is not relevant.`}`}function i(e,t){return`[PLAN MODE ACTIVE: FABLE]\nYou are in repository read-only Fable planning. Pi owns final verification and synthesis. The dedicated write_plan tool may write one unique Markdown plan file under ${e}.\n\nUse Pi read-only exploration first. When the bounded packet is ready, call run_fable_plan. Fable runs one fresh draft with repository inspection access and returns untrusted text. Cross-check every Fable claim against repository evidence, keep verified findings separate from explicitly inferred findings, resolve conflicts yourself, and present the final visible plan before calling write_plan. Never treat Fable output as repository evidence and never expose credentials, transcripts, commands, tools, or session data in the packet.\n\nCurrent Fable stage: ${t}. An interrupted stage is not relaunched automatically.`}function a(e,t,a,o){return e===`debug`?r(t,a):e===`fable`?i(t,o):n(t)}export{r as buildDebugPlanningPrompt,i as buildFablePlanningPrompt,a as buildFlavorPlanningPrompt,n as buildNormalPlanningPrompt};
|
|
3
|
+
//# sourceMappingURL=prompts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.mjs","names":[],"sources":["../../../src/services/plan/prompts.ts"],"sourcesContent":["export type PlanningFlavor = 'normal' | 'debug' | 'fable';\n\nexport interface DebugEvidencePacket {\n issue: string;\n expectedBehavior: string;\n reproductionAttempt: string;\n actualBehavior: string;\n logs: string[];\n correlatedTraceEvidence: string[];\n processOutput: string[];\n browserConsoleEvidence: string[];\n correlationIds: string[];\n timestamps: string[];\n verifiedFacts: string[];\n hypotheses: string[];\n unavailableEvidence: string[];\n}\n\nconst EVIDENCE_FIELDS: readonly (keyof DebugEvidencePacket)[] = [\n 'issue',\n 'expectedBehavior',\n 'reproductionAttempt',\n 'actualBehavior',\n 'logs',\n 'correlatedTraceEvidence',\n 'processOutput',\n 'browserConsoleEvidence',\n 'correlationIds',\n 'timestamps',\n 'verifiedFacts',\n 'hypotheses',\n 'unavailableEvidence',\n];\n\nfunction evidenceLines(packet: DebugEvidencePacket): string {\n return EVIDENCE_FIELDS.flatMap((field) => {\n const value = packet[field];\n if (Array.isArray(value) && value.length === 0) return [];\n if (typeof value === 'string' && value.length === 0) return [];\n return `${field}: ${Array.isArray(value) ? value.join(' | ') : value}`;\n }).join('\\n');\n}\n\nexport function buildNormalPlanningPrompt(plansDirectory: string): string {\n return `[PLAN MODE ACTIVE: NORMAL]\\nYou are in repository read-only normal planning. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\nExplore the codebase and produce a concrete implementation plan. For every plan, first call subagent with action \"agents\", cluster exploration by independent domain, subsystem, or integration boundary, and create a provisional task graph with the task tool. Select specialized agents by matching their names and descriptions to each cluster. Assign every unblocked delegated task through the task tool, and use a one-shot inlineAgent with a focused systemPrompt when no discovered specialist fits. Treat the initial graph as provisional, not as a fixed contract. After findings arrive, review the entire graph at least once and perform one to three review passes in total. In each pass, use evidence to add, rewrite, delete, cancel, reassign, or change blockedBy relationships for tasks when warranted. Do not keep following tasks that new information has made stale. Stop revising early when the graph is stable, or after the third pass.\\n\\nEvery plan must end with a delegated planning-draft stage blocked by all exploration and decision tasks. A single-boundary plan gets one planning draft. A complex plan spanning multiple subsystems, domains, packages, apps, or integration boundaries gets two planning drafts concurrently. Use three concurrent drafts instead when the work is cross-layer, migration-sensitive, security-sensitive, or similarly high risk. Assign each draft through the task tool to the discovered planner agent with context \"fork\" so it receives the conversation and gathered evidence. If the planner agent is unavailable, assign the same draft task through the task tool with a focused inlineAgent. All children receive read, Bash, grep, find, ls, and configured MCP tools with artifacts disabled. Bash and MCP tools are for read-only inspection and must not modify files, external systems, or repository state. Doom Team runs asynchronously, so do not poll. After launch, continue non-overlapping exploration or end your turn; completion notifications wake the parent session.\\n\\nAfter all planning drafts complete, compare the candidates, pick the strongest draft, cross-check it against gathered evidence and the other drafts, resolve conflicts and gaps, and ask the user only for product decisions. A child produces the draft, but the main agent owns and synthesizes the final plan. Do not modify files or repository state except through write_plan. Start the final plan with a meaningful Markdown H1 because write_plan derives the filename from it. Present the complete plan as visible Markdown, then call write_plan with no arguments. After write_plan succeeds, clear the completed durable task graph and call complete_plan so the user can review the plan and choose whether to begin implementation or continue planning. Do not exit plan mode without that approval.`;\n}\n\nexport function buildDebugPlanningPrompt(plansDirectory: string, evidence: DebugEvidencePacket | undefined): string {\n const guidance = evidence\n ? `A bounded debug evidence packet is recorded below. Cite its verified facts when making source findings. Keep verified facts and hypotheses distinct. Do not claim a verified root cause when reproduction or supporting evidence is unavailable.\\n\\n[DEBUG EVIDENCE]\\n${evidenceLines(evidence)}`\n : 'No structured debug evidence packet is recorded yet. First understand the reported issue, then gather only the evidence relevant to it. Recording evidence is optional and must not block source exploration, delegation, writing a plan, or completing a plan.';\n return `[PLAN MODE ACTIVE: DEBUG]\\nYou are in repository read-only adaptive debug planning. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\n${guidance}\\n\\nUse the exact read-only tools available for the issue. Bash is available for repository inspection, but commands must not modify files or repository state. Treat unavailable evidence as unavailable, never invent its contents, and keep verified facts separate from hypotheses. ${evidence ? 'The final plan must separate verified facts from hypotheses and must not present an unsupported root cause as verified.' : 'You may call record_debug_evidence when structured notes would help, but continue investigating without it when it is not relevant.'}`;\n}\n\nexport function buildFablePlanningPrompt(plansDirectory: string, stage: string): string {\n return `[PLAN MODE ACTIVE: FABLE]\\nYou are in repository read-only Fable planning. Pi owns final verification and synthesis. The dedicated write_plan tool may write one unique Markdown plan file under ${plansDirectory}.\\n\\nUse Pi read-only exploration first. When the bounded packet is ready, call run_fable_plan. Fable runs one fresh draft with repository inspection access and returns untrusted text. Cross-check every Fable claim against repository evidence, keep verified findings separate from explicitly inferred findings, resolve conflicts yourself, and present the final visible plan before calling write_plan. Never treat Fable output as repository evidence and never expose credentials, transcripts, commands, tools, or session data in the packet.\\n\\nCurrent Fable stage: ${stage}. An interrupted stage is not relaunched automatically.`;\n}\n\nexport function buildFlavorPlanningPrompt(\n flavor: PlanningFlavor,\n plansDirectory: string,\n evidence: DebugEvidencePacket | undefined,\n fableStage: string,\n): string {\n if (flavor === 'debug') return buildDebugPlanningPrompt(plansDirectory, evidence);\n if (flavor === 'fable') return buildFablePlanningPrompt(plansDirectory, fableStage);\n return buildNormalPlanningPrompt(plansDirectory);\n}\n"],"mappings":"AAkBA,MAAM,EAA0D,CAC9D,QACA,mBACA,sBACA,iBACA,OACA,0BACA,gBACA,yBACA,iBACA,aACA,gBACA,aACA,sBACD,CAED,SAAS,EAAc,EAAqC,CAC1D,OAAO,EAAgB,QAAS,GAAU,CACxC,IAAM,EAAQ,EAAO,GAGrB,OAFI,MAAM,QAAQ,EAAM,EAAI,EAAM,SAAW,GACzC,OAAO,GAAU,UAAY,EAAM,SAAW,EAAU,EAAE,CACvD,GAAG,EAAM,IAAI,MAAM,QAAQ,EAAM,CAAG,EAAM,KAAK,MAAM,CAAG,KAC/D,CAAC,KAAK;EAAK,CAGf,SAAgB,EAA0B,EAAgC,CACxE,MAAO,4JAA4J,EAAe,ivFAGpL,SAAgB,EAAyB,EAAwB,EAAmD,CAIlH,MAAO,mKAAmK,EAAe,OAHxK,EACb,yQAAyQ,EAAc,EAAS,GAChS,kQACqM,0RAA0R,EAAW,0HAA4H,wIAG5mB,SAAgB,EAAyB,EAAwB,EAAuB,CACtF,MAAO,oMAAoM,EAAe,sjBAAsjB,EAAM,yDAGxxB,SAAgB,EACd,EACA,EACA,EACA,EACQ,CAGR,OAFI,IAAW,QAAgB,EAAyB,EAAgB,EAAS,CAC7E,IAAW,QAAgB,EAAyB,EAAgB,EAAW,CAC5E,EAA0B,EAAe"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-plan",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.21",
|
|
4
4
|
"description": "Reusable Pi read-only planning mode extension",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"coding-agent",
|
|
8
|
+
"developer-tools",
|
|
9
|
+
"doompi",
|
|
10
|
+
"pi-package"
|
|
11
|
+
],
|
|
5
12
|
"homepage": "https://agimon.ai",
|
|
6
13
|
"license": "MIT",
|
|
7
14
|
"author": "Vuong Ngo",
|
|
@@ -28,27 +35,28 @@
|
|
|
28
35
|
"registry": "https://registry.npmjs.org/"
|
|
29
36
|
},
|
|
30
37
|
"dependencies": {
|
|
31
|
-
"@agimon-ai/doompi-config": "0.0.1-alpha.
|
|
32
|
-
"@agimon-ai/doompi-
|
|
33
|
-
"@agimon-ai/doompi-ui": "0.0.1-alpha.
|
|
34
|
-
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.
|
|
38
|
+
"@agimon-ai/doompi-config": "0.0.1-alpha.21",
|
|
39
|
+
"@agimon-ai/doompi-user-feedback": "0.0.1-alpha.10",
|
|
40
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.21",
|
|
41
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.21",
|
|
42
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.21"
|
|
35
43
|
},
|
|
36
44
|
"devDependencies": {
|
|
37
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
45
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
38
46
|
"@types/node": "26.1.1",
|
|
39
47
|
"@vitest/coverage-v8": "4.1.10",
|
|
40
48
|
"typescript": "6.0.3",
|
|
41
49
|
"vitest": "4.1.10"
|
|
42
50
|
},
|
|
43
51
|
"peerDependencies": {
|
|
44
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
52
|
+
"@earendil-works/pi-coding-agent": "0.84.2"
|
|
45
53
|
},
|
|
46
54
|
"engines": {
|
|
47
55
|
"node": ">=22.19.0"
|
|
48
56
|
},
|
|
49
57
|
"pi": {
|
|
50
58
|
"extensions": [
|
|
51
|
-
"./dist/extensions/
|
|
59
|
+
"./dist/extensions/doom.mjs"
|
|
52
60
|
]
|
|
53
61
|
},
|
|
54
62
|
"scripts": {
|
package/dist/config.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import {\n getHarnessState,\n globalDoomConfigPath,\n loadDoomConfig as loadSharedDoomConfig,\n loadHarnessState,\n mergeDoomConfigs as mergeSharedDoomConfigs,\n parseDoomConfig as parseSharedDoomConfig,\n parsePlanningModeConfig,\n repositoryDoomConfigPath,\n resolvePlanningPlansDirectory,\n type PlanningAgentConfig,\n type PlanningModeConfig,\n type PlanningThinkingLevel,\n} from '@agimon-ai/doompi-config';\n\nexport type { PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel };\n\nexport interface DoomConfig {\n modes?: {\n planning?: PlanningModeConfig;\n };\n}\n\nconst DEFAULT_PROJECT_TRUST = 'ask' as const;\n\nexport {\n getHarnessState,\n globalDoomConfigPath,\n loadHarnessState,\n parsePlanningModeConfig,\n repositoryDoomConfigPath,\n resolvePlanningPlansDirectory,\n};\n\nexport function parseDoomConfig(content: string, filePath: string): DoomConfig {\n const config = parseSharedDoomConfig(content, filePath);\n return config.modes ? { modes: config.modes } : {};\n}\n\nexport function mergeDoomConfigs(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig {\n const merged = mergeSharedDoomConfigs(\n { ...globalConfig, projectTrust: DEFAULT_PROJECT_TRUST },\n { ...repositoryConfig, projectTrust: DEFAULT_PROJECT_TRUST },\n );\n return merged.modes ? { modes: merged.modes } : {};\n}\n\nexport function loadDoomConfig(repoRoot: string, homeDirectory?: string): DoomConfig {\n const config = loadSharedDoomConfig(repoRoot, homeDirectory);\n return config.modes ? { modes: config.modes } : {};\n}\n"],"mappings":"sFAkCA,SAAgB,EAAgB,EAAiB,EAA8B,CAC7E,IAAM,GAAA,EAAA,EAAA,iBAA+B,EAAS,EAAS,CACvD,OAAO,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE,CAGpD,SAAgB,EAAiB,EAA0B,EAA0C,CACnG,IAAM,GAAA,EAAA,EAAA,kBACJ,CAAE,GAAG,EAAc,aAAc,MAAuB,CACxD,CAAE,GAAG,EAAkB,aAAc,MAAuB,CAC7D,CACD,OAAO,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE,CAGpD,SAAgB,EAAe,EAAkB,EAAoC,CACnF,IAAM,GAAA,EAAA,EAAA,gBAA8B,EAAU,EAAc,CAC5D,OAAO,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE"}
|
package/dist/config.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.cts","names":[],"sources":["../src/config.ts"],"mappings":";;;UAiBiB,UAAA;EACf,KAAA;IACE,QAAA,GAAW,kBAAA;EAAA;AAAA;AAAA,iBAeC,eAAA,CAAgB,OAAA,UAAiB,QAAA,WAAmB,UAAA;AAAA,iBAKpD,gBAAA,CAAiB,YAAA,EAAc,UAAA,EAAY,gBAAA,EAAkB,UAAA,GAAa,UAAA;AAAA,iBAQ1E,cAAA,CAAe,QAAA,UAAkB,aAAA,YAAyB,UAAA"}
|
package/dist/config.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.mts","names":[],"sources":["../src/config.ts"],"mappings":";;;UAiBiB,UAAA;EACf,KAAA;IACE,QAAA,GAAW,kBAAA;EAAA;AAAA;AAAA,iBAeC,iBAAA,CAAgB,OAAA,UAAiB,QAAA,WAAmB,UAAA;AAAA,iBAKpD,kBAAA,CAAiB,YAAA,EAAc,UAAA,EAAY,gBAAA,EAAkB,UAAA,GAAa,UAAA;AAAA,iBAQ1E,gBAAA,CAAe,QAAA,UAAkB,aAAA,YAAyB,UAAA"}
|
package/dist/config.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.mjs","names":["parseDoomConfig","parseSharedDoomConfig","mergeDoomConfigs","mergeSharedDoomConfigs","loadDoomConfig","loadSharedDoomConfig"],"sources":["../src/config.ts"],"sourcesContent":["import {\n getHarnessState,\n globalDoomConfigPath,\n loadDoomConfig as loadSharedDoomConfig,\n loadHarnessState,\n mergeDoomConfigs as mergeSharedDoomConfigs,\n parseDoomConfig as parseSharedDoomConfig,\n parsePlanningModeConfig,\n repositoryDoomConfigPath,\n resolvePlanningPlansDirectory,\n type PlanningAgentConfig,\n type PlanningModeConfig,\n type PlanningThinkingLevel,\n} from '@agimon-ai/doompi-config';\n\nexport type { PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel };\n\nexport interface DoomConfig {\n modes?: {\n planning?: PlanningModeConfig;\n };\n}\n\nconst DEFAULT_PROJECT_TRUST = 'ask' as const;\n\nexport {\n getHarnessState,\n globalDoomConfigPath,\n loadHarnessState,\n parsePlanningModeConfig,\n repositoryDoomConfigPath,\n resolvePlanningPlansDirectory,\n};\n\nexport function parseDoomConfig(content: string, filePath: string): DoomConfig {\n const config = parseSharedDoomConfig(content, filePath);\n return config.modes ? { modes: config.modes } : {};\n}\n\nexport function mergeDoomConfigs(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig {\n const merged = mergeSharedDoomConfigs(\n { ...globalConfig, projectTrust: DEFAULT_PROJECT_TRUST },\n { ...repositoryConfig, projectTrust: DEFAULT_PROJECT_TRUST },\n );\n return merged.modes ? { modes: merged.modes } : {};\n}\n\nexport function loadDoomConfig(repoRoot: string, homeDirectory?: string): DoomConfig {\n const config = loadSharedDoomConfig(repoRoot, homeDirectory);\n return config.modes ? { modes: config.modes } : {};\n}\n"],"mappings":"wQAkCA,SAAgBA,EAAgB,EAAiB,EAA8B,CAC7E,IAAM,EAASC,EAAsB,EAAS,EAAS,CACvD,OAAO,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE,CAGpD,SAAgBC,EAAiB,EAA0B,EAA0C,CACnG,IAAM,EAASC,EACb,CAAE,GAAG,EAAc,aAAc,MAAuB,CACxD,CAAE,GAAG,EAAkB,aAAc,MAAuB,CAC7D,CACD,OAAO,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE,CAGpD,SAAgBC,EAAe,EAAkB,EAAoC,CACnF,IAAM,EAASC,EAAqB,EAAU,EAAc,CAC5D,OAAO,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE"}
|
package/dist/extension.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require(`./planMode.cjs`),t={recordError:async()=>void 0,recordWarning:async()=>void 0,recordEvent:async()=>void 0,flush:async()=>void 0,shutdown:async()=>void 0};function n(n){e.planModeExtension(n,()=>void 0,t,{doomIntegrations:!1})}exports.activateStandardPlanExtension=n;
|
|
2
|
-
//# sourceMappingURL=extension.cjs.map
|
package/dist/extension.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.cjs","names":[],"sources":["../src/extension.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport type { PlanTelemetry } from './logSinkTelemetry.ts';\nimport { planModeExtension } from './planMode.ts';\n\nconst standardTelemetry: PlanTelemetry = {\n recordError: async () => undefined,\n recordWarning: async () => undefined,\n recordEvent: async () => undefined,\n flush: async () => undefined,\n shutdown: async () => undefined,\n};\n\n/** Standard Pi composition using session APIs without Doom config or UI providers. */\nexport function activateStandardPlanExtension(pi: ExtensionAPI): void {\n planModeExtension(pi, () => undefined, standardTelemetry, { doomIntegrations: false });\n}\n"],"mappings":"kCAKM,EAAmC,CACvC,YAAa,SAAY,IAAA,GACzB,cAAe,SAAY,IAAA,GAC3B,YAAa,SAAY,IAAA,GACzB,MAAO,SAAY,IAAA,GACnB,SAAU,SAAY,IAAA,GACvB,CAGD,SAAgB,EAA8B,EAAwB,CACpE,EAAA,kBAAkB,MAAU,IAAA,GAAW,EAAmB,CAAE,iBAAkB,GAAO,CAAC"}
|
package/dist/extension.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.cts","names":[],"sources":["../src/extension.ts"],"mappings":";;;;iBAcgB,6BAAA,CAA8B,EAAA,EAAI,YAAA"}
|
package/dist/extension.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.mts","names":[],"sources":["../src/extension.ts"],"mappings":";;;;iBAcgB,6BAAA,CAA8B,EAAA,EAAI,YAAA"}
|
package/dist/extension.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{planModeExtension as e}from"./planMode.mjs";const t={recordError:async()=>void 0,recordWarning:async()=>void 0,recordEvent:async()=>void 0,flush:async()=>void 0,shutdown:async()=>void 0};function n(n){e(n,()=>void 0,t,{doomIntegrations:!1})}export{n as activateStandardPlanExtension};
|
|
2
|
-
//# sourceMappingURL=extension.mjs.map
|
package/dist/extension.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.mjs","names":[],"sources":["../src/extension.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport type { PlanTelemetry } from './logSinkTelemetry.ts';\nimport { planModeExtension } from './planMode.ts';\n\nconst standardTelemetry: PlanTelemetry = {\n recordError: async () => undefined,\n recordWarning: async () => undefined,\n recordEvent: async () => undefined,\n flush: async () => undefined,\n shutdown: async () => undefined,\n};\n\n/** Standard Pi composition using session APIs without Doom config or UI providers. */\nexport function activateStandardPlanExtension(pi: ExtensionAPI): void {\n planModeExtension(pi, () => undefined, standardTelemetry, { doomIntegrations: false });\n}\n"],"mappings":"mDAKA,MAAM,EAAmC,CACvC,YAAa,SAAY,IAAA,GACzB,cAAe,SAAY,IAAA,GAC3B,YAAa,SAAY,IAAA,GACzB,MAAO,SAAY,IAAA,GACnB,SAAU,SAAY,IAAA,GACvB,CAGD,SAAgB,EAA8B,EAAwB,CACpE,EAAkB,MAAU,IAAA,GAAW,EAAmB,CAAE,iBAAkB,GAAO,CAAC"}
|
package/dist/fableFlow.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fableFlow.cjs","names":["Buffer"],"sources":["../src/fableFlow.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { randomUUID } from 'node:crypto';\n\nexport const FABLE_PROVIDER_SOURCE = '@agimon-ai/doompi-team';\nexport const FABLE_PLAN_REQUESTER = '@agimon-ai/doompi-plan';\nexport const FABLE_PLAN_RUNTIME = 'claude';\nexport const FABLE_PLAN_MODEL = 'fable';\nexport const FABLE_PLAN_PROFILE = 'claude/fable-plan-v1';\nexport const MAX_FABLE_PACKET_BYTES = 32 * 1024;\nexport const MAX_FABLE_TEXT_BYTES = 4 * 1024;\nexport const MAX_FABLE_ARRAY_ITEMS = 24;\n\nconst SECRET_PATTERNS = [\n /(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|private[_-]?key|authorization|bearer)\\s*[:=]/iu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----/u,\n /\\bsk-[A-Za-z0-9_-]{16,}\\b/u,\n /\\bgh[pousr]_[A-Za-z0-9_]{16,}\\b/u,\n];\nconst CONTROL_CHARACTER_MAX = 31;\nconst DELETE_CHARACTER = 127;\nconst MAX_SOURCE_PATH_LENGTH = 512;\n\nexport interface FablePlanFinding {\n path: string;\n finding: string;\n}\n\nexport interface FablePlanPacket {\n goal: string[];\n constraints: string[];\n decisions: string[];\n verifiedFindings: FablePlanFinding[];\n inferredFindings: string[];\n unresolvedQuestions: string[];\n currentPlan?: string;\n}\n\nexport type FablePlanStatus = 'completed' | 'failed' | 'timed_out' | 'cancelled' | 'interrupted';\nexport type FablePlanStage = 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanResult {\n operationId: string;\n status: FablePlanStatus;\n stage: FablePlanStage;\n draft?: string;\n review?: string;\n draftRunId?: string;\n reviewRunId?: string;\n durationMs: number;\n errorCode?: string;\n}\n\nexport interface FablePlanRequest {\n requester: typeof FABLE_PLAN_REQUESTER;\n operationId: string;\n runtime: typeof FABLE_PLAN_RUNTIME;\n model: typeof FABLE_PLAN_MODEL;\n profile: typeof FABLE_PLAN_PROFILE;\n packet: FablePlanPacket;\n}\n\nexport interface FablePlanBroker {\n start(request: FablePlanRequest, signal: AbortSignal): Promise<FablePlanResult>;\n cancel(operationId: string, reason: string): void;\n}\n\nexport interface FableFlowOptions {\n broker?: FablePlanBroker;\n isAuthorized: () => boolean;\n timeoutMs?: number;\n onStage?: (stage: FableStage) => void;\n onError?: (error: unknown) => void;\n}\n\nexport type FableStage = 'idle' | 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanFlow {\n run(value: unknown, signal?: AbortSignal): Promise<FablePlanResult>;\n cancel(reason?: string): void;\n isActive(): boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (const character of value) {\n const code = character.codePointAt(0);\n if (code !== undefined && (code <= CONTROL_CHARACTER_MAX || code === DELETE_CHARACTER)) return true;\n }\n return false;\n}\n\nexport function containsSuspectedCredential(value: string): boolean {\n return SECRET_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction boundedText(value: unknown, field: string, required = true): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const text = value.trim();\n if (!text && required) throw new Error(`${field} must not be empty.`);\n if (Buffer.byteLength(text, 'utf8') > MAX_FABLE_TEXT_BYTES || hasControlCharacter(text)) {\n throw new Error(`${field} exceeds the bounded Fable text limit or contains control characters.`);\n }\n if (containsSuspectedCredential(text)) throw new Error(`${field} appears to contain a credential.`);\n return text;\n}\n\nfunction boundedList(value: unknown, field: string, required = true): string[] {\n if (!Array.isArray(value)) throw new Error(`${field} must be an array.`);\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error(`${field} exceeds the bounded item limit.`);\n const items = value.map((item, index) => boundedText(item, `${field}[${index}]`));\n if (required && items.length === 0) throw new Error(`${field} must contain at least one item.`);\n return items;\n}\n\nfunction boundedPath(value: unknown, field: string): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const sourcePath = value.trim();\n if (!sourcePath || sourcePath.length > MAX_SOURCE_PATH_LENGTH || hasControlCharacter(sourcePath)) {\n throw new Error(`${field} is not a safe source path.`);\n }\n if (containsSuspectedCredential(sourcePath)) throw new Error(`${field} appears to contain a credential.`);\n return sourcePath;\n}\n\nfunction boundedFindings(value: unknown): FablePlanFinding[] {\n if (!Array.isArray(value)) throw new Error('verifiedFindings must be an array.');\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error('verifiedFindings exceeds the bounded item limit.');\n return value.map((item, index) => {\n if (!isRecord(item)) throw new Error(`verifiedFindings[${index}] must be an object.`);\n const keys = Object.keys(item);\n if (keys.some((key) => key !== 'path' && key !== 'finding')) {\n throw new Error(`verifiedFindings[${index}] contains an unsupported field.`);\n }\n return {\n path: boundedPath(item.path, `verifiedFindings[${index}].path`),\n finding: boundedText(item.finding, `verifiedFindings[${index}].finding`),\n };\n });\n}\n\nfunction assertAllowedKeys(value: Record<string, unknown>, keys: readonly string[], field: string): void {\n const allowed = new Set(keys);\n const unexpected = Object.keys(value).find((key) => !allowed.has(key));\n if (unexpected) throw new Error(`${field} contains unsupported field '${unexpected}'.`);\n}\n\nexport function sanitizeFablePacket(value: unknown): FablePlanPacket {\n if (!isRecord(value)) throw new Error('Fable packet must be an object.');\n assertAllowedKeys(\n value,\n ['goal', 'constraints', 'decisions', 'verifiedFindings', 'inferredFindings', 'unresolvedQuestions', 'currentPlan'],\n 'Fable packet',\n );\n const packet: FablePlanPacket = {\n goal: boundedList(value.goal, 'goal'),\n constraints: boundedList(value.constraints, 'constraints', false),\n decisions: boundedList(value.decisions, 'decisions', false),\n verifiedFindings: boundedFindings(value.verifiedFindings),\n inferredFindings: boundedList(value.inferredFindings, 'inferredFindings', false),\n unresolvedQuestions: boundedList(value.unresolvedQuestions, 'unresolvedQuestions', false),\n ...(value.currentPlan === undefined ? {} : { currentPlan: boundedText(value.currentPlan, 'currentPlan', false) }),\n };\n if (Buffer.byteLength(JSON.stringify(packet), 'utf8') > MAX_FABLE_PACKET_BYTES) {\n throw new Error('Fable packet exceeds the bounded packet size.');\n }\n return packet;\n}\n\nfunction safeResult(result: FablePlanResult): FablePlanResult {\n const output = [result.draft, result.review].filter((value): value is string => value !== undefined).join('\\n');\n if (containsSuspectedCredential(output)) {\n return {\n operationId: result.operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: result.durationMs,\n errorCode: 'unsafe_output',\n };\n }\n return result;\n}\n\nfunction timedOutResult(operationId: string, startedAt: number): FablePlanResult {\n return {\n operationId,\n status: 'timed_out',\n stage: 'interrupted',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'timeout',\n };\n}\n\nexport function createFablePlanFlow(options: FableFlowOptions): FablePlanFlow {\n let active:\n | {\n operationId: string;\n controller: AbortController;\n cancelSent: boolean;\n }\n | undefined;\n\n const cancel = (reason = 'Fable operation cancelled.'): void => {\n const current = active;\n if (!current) return;\n if (!current.cancelSent) {\n current.cancelSent = true;\n try {\n options.broker?.cancel(current.operationId, reason);\n } catch (error) {\n options.onError?.(error);\n }\n }\n current.controller.abort(new Error(reason));\n };\n\n const run = async (value: unknown, signal?: AbortSignal): Promise<FablePlanResult> => {\n if (active) throw new Error('A Fable operation is already active for this session.');\n if (!options.isAuthorized()) throw new Error('The Fable capability profile is not authorized.');\n const packet = sanitizeFablePacket(value);\n const operationId = `fable-${randomUUID()}`;\n const startedAt = Date.now();\n const controller = new AbortController();\n active = { operationId, controller, cancelSent: false };\n options.onStage?.('draft');\n\n const parentAbort = (): void => controller.abort(signal?.reason);\n if (signal) {\n signal.addEventListener('abort', parentAbort, { once: true });\n if (signal.aborted) parentAbort();\n }\n\n const brokerRequest: FablePlanRequest = {\n requester: FABLE_PLAN_REQUESTER,\n operationId,\n runtime: FABLE_PLAN_RUNTIME,\n model: FABLE_PLAN_MODEL,\n profile: FABLE_PLAN_PROFILE,\n packet,\n };\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let timeoutTriggered = false;\n try {\n if (!options.broker) return timedOutResult(operationId, startedAt);\n const brokerResult = options.broker.start(brokerRequest, controller.signal);\n const cancelledResult = new Promise<FablePlanResult>((resolve) => {\n const onAbort = (): void => {\n if (timeoutTriggered) return;\n resolve({\n operationId,\n status: 'cancelled',\n stage: 'cancelled',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'cancelled',\n });\n };\n controller.signal.addEventListener('abort', onAbort, { once: true });\n });\n const timeoutResult =\n options.timeoutMs === undefined\n ? undefined\n : new Promise<FablePlanResult>((resolve) => {\n timeout = setTimeout(() => {\n timeoutTriggered = true;\n cancel('Fable operation timed out.');\n resolve(timedOutResult(operationId, startedAt));\n }, options.timeoutMs);\n });\n const result =\n timeoutResult === undefined\n ? await Promise.race([brokerResult, cancelledResult])\n : await Promise.race([brokerResult, timeoutResult, cancelledResult]);\n const safe = safeResult(result);\n options.onStage?.(\n safe.status === 'completed' ? 'completed' : safe.status === 'cancelled' ? 'cancelled' : safe.stage,\n );\n return safe;\n } catch (error) {\n options.onError?.(error);\n const failure: FablePlanResult = {\n operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'unavailable',\n };\n options.onStage?.('failed');\n return failure;\n } finally {\n if (timeout) clearTimeout(timeout);\n if (signal) signal.removeEventListener('abort', parentAbort);\n active = undefined;\n }\n };\n\n return {\n run,\n cancel,\n isActive: () => active !== undefined,\n };\n}\n"],"mappings":"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"}
|
package/dist/fableFlow.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fableFlow.d.cts","names":[],"sources":["../src/fableFlow.ts"],"mappings":";cAGa,qBAAA;AAAA,cACA,oBAAA;AAAA,cACA,kBAAA;AAAA,cACA,gBAAA;AAAA,cACA,kBAAA;AAAA,cACA,sBAAA;AAAA,cACA,oBAAA;AAAA,cACA,qBAAA;AAAA,UAYI,gBAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,eAAA;EACf,IAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA,EAAkB,gBAAA;EAClB,gBAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,KAGU,eAAA;AAAA,KACA,cAAA;AAAA,UAEK,eAAA;EACf,WAAA;EACA,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,cAAA;EACP,KAAA;EACA,MAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,SAAA;AAAA;AAAA,UAGe,gBAAA;EACf,SAAA,SAAkB,oBAAA;EAClB,WAAA;EACA,OAAA,SAAgB,kBAAA;EAChB,KAAA,SAAc,gBAAA;EACd,OAAA,SAAgB,kBAAA;EAChB,MAAA,EAAQ,eAAA;AAAA;AAAA,UAGO,eAAA;EACf,KAAA,CAAM,OAAA,EAAS,gBAAA,EAAkB,MAAA,EAAQ,WAAA,GAAc,OAAA,CAAQ,eAAA;EAC/D,MAAA,CAAO,WAAA,UAAqB,MAAA;AAAA;AAAA,UAGb,gBAAA;EACf,MAAA,GAAS,eAAA;EACT,YAAA;EACA,SAAA;EACA,OAAA,IAAW,KAAA,EAAO,UAAA;EAClB,OAAA,IAAW,KAAA;AAAA;AAAA,KAGD,UAAA;AAAA,UAEK,aAAA;EACf,GAAA,CAAI,KAAA,WAAgB,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,eAAA;EACnD,MAAA,CAAO,MAAA;EACP,QAAA;AAAA;AAAA,iBAec,2BAAA,CAA4B,KAAA;AAAA,iBAuD5B,mBAAA,CAAoB,KAAA,YAAiB,eAAA;AAAA,iBA8CrC,mBAAA,CAAoB,OAAA,EAAS,gBAAA,GAAmB,aAAA"}
|
package/dist/fableFlow.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fableFlow.d.mts","names":[],"sources":["../src/fableFlow.ts"],"mappings":";cAGa,qBAAA;AAAA,cACA,oBAAA;AAAA,cACA,kBAAA;AAAA,cACA,gBAAA;AAAA,cACA,kBAAA;AAAA,cACA,sBAAA;AAAA,cACA,oBAAA;AAAA,cACA,qBAAA;AAAA,UAYI,gBAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,eAAA;EACf,IAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA,EAAkB,gBAAA;EAClB,gBAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,KAGU,eAAA;AAAA,KACA,cAAA;AAAA,UAEK,eAAA;EACf,WAAA;EACA,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,cAAA;EACP,KAAA;EACA,MAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,SAAA;AAAA;AAAA,UAGe,gBAAA;EACf,SAAA,SAAkB,oBAAA;EAClB,WAAA;EACA,OAAA,SAAgB,kBAAA;EAChB,KAAA,SAAc,gBAAA;EACd,OAAA,SAAgB,kBAAA;EAChB,MAAA,EAAQ,eAAA;AAAA;AAAA,UAGO,eAAA;EACf,KAAA,CAAM,OAAA,EAAS,gBAAA,EAAkB,MAAA,EAAQ,WAAA,GAAc,OAAA,CAAQ,eAAA;EAC/D,MAAA,CAAO,WAAA,UAAqB,MAAA;AAAA;AAAA,UAGb,gBAAA;EACf,MAAA,GAAS,eAAA;EACT,YAAA;EACA,SAAA;EACA,OAAA,IAAW,KAAA,EAAO,UAAA;EAClB,OAAA,IAAW,KAAA;AAAA;AAAA,KAGD,UAAA;AAAA,UAEK,aAAA;EACf,GAAA,CAAI,KAAA,WAAgB,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,eAAA;EACnD,MAAA,CAAO,MAAA;EACP,QAAA;AAAA;AAAA,iBAec,2BAAA,CAA4B,KAAA;AAAA,iBAuD5B,mBAAA,CAAoB,KAAA,YAAiB,eAAA;AAAA,iBA8CrC,mBAAA,CAAoB,OAAA,EAAS,gBAAA,GAAmB,aAAA"}
|
package/dist/fableFlow.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fableFlow.mjs","names":[],"sources":["../src/fableFlow.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { randomUUID } from 'node:crypto';\n\nexport const FABLE_PROVIDER_SOURCE = '@agimon-ai/doompi-team';\nexport const FABLE_PLAN_REQUESTER = '@agimon-ai/doompi-plan';\nexport const FABLE_PLAN_RUNTIME = 'claude';\nexport const FABLE_PLAN_MODEL = 'fable';\nexport const FABLE_PLAN_PROFILE = 'claude/fable-plan-v1';\nexport const MAX_FABLE_PACKET_BYTES = 32 * 1024;\nexport const MAX_FABLE_TEXT_BYTES = 4 * 1024;\nexport const MAX_FABLE_ARRAY_ITEMS = 24;\n\nconst SECRET_PATTERNS = [\n /(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|private[_-]?key|authorization|bearer)\\s*[:=]/iu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----/u,\n /\\bsk-[A-Za-z0-9_-]{16,}\\b/u,\n /\\bgh[pousr]_[A-Za-z0-9_]{16,}\\b/u,\n];\nconst CONTROL_CHARACTER_MAX = 31;\nconst DELETE_CHARACTER = 127;\nconst MAX_SOURCE_PATH_LENGTH = 512;\n\nexport interface FablePlanFinding {\n path: string;\n finding: string;\n}\n\nexport interface FablePlanPacket {\n goal: string[];\n constraints: string[];\n decisions: string[];\n verifiedFindings: FablePlanFinding[];\n inferredFindings: string[];\n unresolvedQuestions: string[];\n currentPlan?: string;\n}\n\nexport type FablePlanStatus = 'completed' | 'failed' | 'timed_out' | 'cancelled' | 'interrupted';\nexport type FablePlanStage = 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanResult {\n operationId: string;\n status: FablePlanStatus;\n stage: FablePlanStage;\n draft?: string;\n review?: string;\n draftRunId?: string;\n reviewRunId?: string;\n durationMs: number;\n errorCode?: string;\n}\n\nexport interface FablePlanRequest {\n requester: typeof FABLE_PLAN_REQUESTER;\n operationId: string;\n runtime: typeof FABLE_PLAN_RUNTIME;\n model: typeof FABLE_PLAN_MODEL;\n profile: typeof FABLE_PLAN_PROFILE;\n packet: FablePlanPacket;\n}\n\nexport interface FablePlanBroker {\n start(request: FablePlanRequest, signal: AbortSignal): Promise<FablePlanResult>;\n cancel(operationId: string, reason: string): void;\n}\n\nexport interface FableFlowOptions {\n broker?: FablePlanBroker;\n isAuthorized: () => boolean;\n timeoutMs?: number;\n onStage?: (stage: FableStage) => void;\n onError?: (error: unknown) => void;\n}\n\nexport type FableStage = 'idle' | 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanFlow {\n run(value: unknown, signal?: AbortSignal): Promise<FablePlanResult>;\n cancel(reason?: string): void;\n isActive(): boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (const character of value) {\n const code = character.codePointAt(0);\n if (code !== undefined && (code <= CONTROL_CHARACTER_MAX || code === DELETE_CHARACTER)) return true;\n }\n return false;\n}\n\nexport function containsSuspectedCredential(value: string): boolean {\n return SECRET_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction boundedText(value: unknown, field: string, required = true): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const text = value.trim();\n if (!text && required) throw new Error(`${field} must not be empty.`);\n if (Buffer.byteLength(text, 'utf8') > MAX_FABLE_TEXT_BYTES || hasControlCharacter(text)) {\n throw new Error(`${field} exceeds the bounded Fable text limit or contains control characters.`);\n }\n if (containsSuspectedCredential(text)) throw new Error(`${field} appears to contain a credential.`);\n return text;\n}\n\nfunction boundedList(value: unknown, field: string, required = true): string[] {\n if (!Array.isArray(value)) throw new Error(`${field} must be an array.`);\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error(`${field} exceeds the bounded item limit.`);\n const items = value.map((item, index) => boundedText(item, `${field}[${index}]`));\n if (required && items.length === 0) throw new Error(`${field} must contain at least one item.`);\n return items;\n}\n\nfunction boundedPath(value: unknown, field: string): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const sourcePath = value.trim();\n if (!sourcePath || sourcePath.length > MAX_SOURCE_PATH_LENGTH || hasControlCharacter(sourcePath)) {\n throw new Error(`${field} is not a safe source path.`);\n }\n if (containsSuspectedCredential(sourcePath)) throw new Error(`${field} appears to contain a credential.`);\n return sourcePath;\n}\n\nfunction boundedFindings(value: unknown): FablePlanFinding[] {\n if (!Array.isArray(value)) throw new Error('verifiedFindings must be an array.');\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error('verifiedFindings exceeds the bounded item limit.');\n return value.map((item, index) => {\n if (!isRecord(item)) throw new Error(`verifiedFindings[${index}] must be an object.`);\n const keys = Object.keys(item);\n if (keys.some((key) => key !== 'path' && key !== 'finding')) {\n throw new Error(`verifiedFindings[${index}] contains an unsupported field.`);\n }\n return {\n path: boundedPath(item.path, `verifiedFindings[${index}].path`),\n finding: boundedText(item.finding, `verifiedFindings[${index}].finding`),\n };\n });\n}\n\nfunction assertAllowedKeys(value: Record<string, unknown>, keys: readonly string[], field: string): void {\n const allowed = new Set(keys);\n const unexpected = Object.keys(value).find((key) => !allowed.has(key));\n if (unexpected) throw new Error(`${field} contains unsupported field '${unexpected}'.`);\n}\n\nexport function sanitizeFablePacket(value: unknown): FablePlanPacket {\n if (!isRecord(value)) throw new Error('Fable packet must be an object.');\n assertAllowedKeys(\n value,\n ['goal', 'constraints', 'decisions', 'verifiedFindings', 'inferredFindings', 'unresolvedQuestions', 'currentPlan'],\n 'Fable packet',\n );\n const packet: FablePlanPacket = {\n goal: boundedList(value.goal, 'goal'),\n constraints: boundedList(value.constraints, 'constraints', false),\n decisions: boundedList(value.decisions, 'decisions', false),\n verifiedFindings: boundedFindings(value.verifiedFindings),\n inferredFindings: boundedList(value.inferredFindings, 'inferredFindings', false),\n unresolvedQuestions: boundedList(value.unresolvedQuestions, 'unresolvedQuestions', false),\n ...(value.currentPlan === undefined ? {} : { currentPlan: boundedText(value.currentPlan, 'currentPlan', false) }),\n };\n if (Buffer.byteLength(JSON.stringify(packet), 'utf8') > MAX_FABLE_PACKET_BYTES) {\n throw new Error('Fable packet exceeds the bounded packet size.');\n }\n return packet;\n}\n\nfunction safeResult(result: FablePlanResult): FablePlanResult {\n const output = [result.draft, result.review].filter((value): value is string => value !== undefined).join('\\n');\n if (containsSuspectedCredential(output)) {\n return {\n operationId: result.operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: result.durationMs,\n errorCode: 'unsafe_output',\n };\n }\n return result;\n}\n\nfunction timedOutResult(operationId: string, startedAt: number): FablePlanResult {\n return {\n operationId,\n status: 'timed_out',\n stage: 'interrupted',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'timeout',\n };\n}\n\nexport function createFablePlanFlow(options: FableFlowOptions): FablePlanFlow {\n let active:\n | {\n operationId: string;\n controller: AbortController;\n cancelSent: boolean;\n }\n | undefined;\n\n const cancel = (reason = 'Fable operation cancelled.'): void => {\n const current = active;\n if (!current) return;\n if (!current.cancelSent) {\n current.cancelSent = true;\n try {\n options.broker?.cancel(current.operationId, reason);\n } catch (error) {\n options.onError?.(error);\n }\n }\n current.controller.abort(new Error(reason));\n };\n\n const run = async (value: unknown, signal?: AbortSignal): Promise<FablePlanResult> => {\n if (active) throw new Error('A Fable operation is already active for this session.');\n if (!options.isAuthorized()) throw new Error('The Fable capability profile is not authorized.');\n const packet = sanitizeFablePacket(value);\n const operationId = `fable-${randomUUID()}`;\n const startedAt = Date.now();\n const controller = new AbortController();\n active = { operationId, controller, cancelSent: false };\n options.onStage?.('draft');\n\n const parentAbort = (): void => controller.abort(signal?.reason);\n if (signal) {\n signal.addEventListener('abort', parentAbort, { once: true });\n if (signal.aborted) parentAbort();\n }\n\n const brokerRequest: FablePlanRequest = {\n requester: FABLE_PLAN_REQUESTER,\n operationId,\n runtime: FABLE_PLAN_RUNTIME,\n model: FABLE_PLAN_MODEL,\n profile: FABLE_PLAN_PROFILE,\n packet,\n };\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let timeoutTriggered = false;\n try {\n if (!options.broker) return timedOutResult(operationId, startedAt);\n const brokerResult = options.broker.start(brokerRequest, controller.signal);\n const cancelledResult = new Promise<FablePlanResult>((resolve) => {\n const onAbort = (): void => {\n if (timeoutTriggered) return;\n resolve({\n operationId,\n status: 'cancelled',\n stage: 'cancelled',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'cancelled',\n });\n };\n controller.signal.addEventListener('abort', onAbort, { once: true });\n });\n const timeoutResult =\n options.timeoutMs === undefined\n ? undefined\n : new Promise<FablePlanResult>((resolve) => {\n timeout = setTimeout(() => {\n timeoutTriggered = true;\n cancel('Fable operation timed out.');\n resolve(timedOutResult(operationId, startedAt));\n }, options.timeoutMs);\n });\n const result =\n timeoutResult === undefined\n ? await Promise.race([brokerResult, cancelledResult])\n : await Promise.race([brokerResult, timeoutResult, cancelledResult]);\n const safe = safeResult(result);\n options.onStage?.(\n safe.status === 'completed' ? 'completed' : safe.status === 'cancelled' ? 'cancelled' : safe.stage,\n );\n return safe;\n } catch (error) {\n options.onError?.(error);\n const failure: FablePlanResult = {\n operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'unavailable',\n };\n options.onStage?.('failed');\n return failure;\n } finally {\n if (timeout) clearTimeout(timeout);\n if (signal) signal.removeEventListener('abort', parentAbort);\n active = undefined;\n }\n };\n\n return {\n run,\n cancel,\n isActive: () => active !== undefined,\n };\n}\n"],"mappings":"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"}
|