@agimon-ai/doompi-team 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 +33 -17
- package/dist/adapters/asyncJobTracker.cjs +2 -0
- package/dist/adapters/asyncJobTracker.cjs.map +1 -0
- package/dist/adapters/asyncJobTracker.mjs +2 -0
- package/dist/adapters/asyncJobTracker.mjs.map +1 -0
- package/dist/adapters/atomicJson.cjs +2 -0
- package/dist/adapters/atomicJson.cjs.map +1 -0
- package/dist/adapters/atomicJson.mjs +2 -0
- package/dist/adapters/atomicJson.mjs.map +1 -0
- package/dist/adapters/pi/extension.cjs +2 -0
- package/dist/adapters/pi/extension.cjs.map +1 -0
- package/dist/adapters/pi/extension.mjs +2 -0
- package/dist/adapters/pi/extension.mjs.map +1 -0
- package/dist/adapters/pollScheduler.cjs +2 -0
- package/dist/adapters/pollScheduler.cjs.map +1 -0
- package/dist/adapters/pollScheduler.mjs +2 -0
- package/dist/adapters/pollScheduler.mjs.map +1 -0
- package/dist/adapters/process/childTranscript.cjs +5 -0
- package/dist/adapters/process/childTranscript.cjs.map +1 -0
- package/dist/adapters/process/childTranscript.mjs +5 -0
- package/dist/adapters/process/childTranscript.mjs.map +1 -0
- package/dist/adapters/process/env.cjs +2 -0
- package/dist/adapters/process/env.cjs.map +1 -0
- package/dist/adapters/process/env.d.cts +69 -0
- package/dist/adapters/process/env.d.cts.map +1 -0
- package/dist/adapters/process/env.d.mts +69 -0
- package/dist/adapters/process/env.d.mts.map +1 -0
- package/dist/adapters/process/env.mjs +2 -0
- package/dist/adapters/process/env.mjs.map +1 -0
- package/dist/adapters/process/sdkRunnerEntry.cjs +2 -0
- package/dist/adapters/process/sdkRunnerEntry.cjs.map +1 -0
- package/dist/adapters/process/sdkRunnerEntry.d.cts +5 -0
- package/dist/adapters/process/sdkRunnerEntry.d.cts.map +1 -0
- package/dist/adapters/process/sdkRunnerEntry.d.mts +5 -0
- package/dist/adapters/process/sdkRunnerEntry.d.mts.map +1 -0
- package/dist/adapters/process/sdkRunnerEntry.mjs +2 -0
- package/dist/adapters/process/sdkRunnerEntry.mjs.map +1 -0
- package/dist/adapters/processTerminal.cjs +2 -0
- package/dist/adapters/processTerminal.cjs.map +1 -0
- package/dist/adapters/processTerminal.mjs +2 -0
- package/dist/adapters/processTerminal.mjs.map +1 -0
- package/dist/adapters/resultWatcher.cjs +2 -0
- package/dist/adapters/resultWatcher.cjs.map +1 -0
- package/dist/adapters/resultWatcher.mjs +2 -0
- package/dist/adapters/resultWatcher.mjs.map +1 -0
- package/dist/adapters/runIdResolver.cjs +2 -0
- package/dist/adapters/runIdResolver.cjs.map +1 -0
- package/dist/adapters/runIdResolver.mjs +2 -0
- package/dist/adapters/runIdResolver.mjs.map +1 -0
- package/dist/adapters/runRegistry.cjs +2 -0
- package/dist/adapters/runRegistry.cjs.map +1 -0
- package/dist/adapters/runRegistry.mjs +2 -0
- package/dist/adapters/runRegistry.mjs.map +1 -0
- package/dist/adapters/scopeOwner.cjs +2 -0
- package/dist/adapters/scopeOwner.cjs.map +1 -0
- package/dist/adapters/scopeOwner.mjs +2 -0
- package/dist/adapters/scopeOwner.mjs.map +1 -0
- package/dist/adapters/staleRunReconciler.cjs +2 -0
- package/dist/adapters/staleRunReconciler.cjs.map +1 -0
- package/dist/adapters/staleRunReconciler.mjs +2 -0
- package/dist/adapters/staleRunReconciler.mjs.map +1 -0
- package/dist/adapters/statusReader.cjs +2 -0
- package/dist/adapters/statusReader.cjs.map +1 -0
- package/dist/adapters/statusReader.mjs +2 -0
- package/dist/adapters/statusReader.mjs.map +1 -0
- package/dist/adapters/suspendedRuns.cjs +6 -0
- package/dist/adapters/suspendedRuns.cjs.map +1 -0
- package/dist/adapters/suspendedRuns.mjs +6 -0
- package/dist/adapters/suspendedRuns.mjs.map +1 -0
- package/dist/api/backgroundWork.cjs +1 -1
- package/dist/api/backgroundWork.d.cts +2 -2
- package/dist/api/backgroundWork.d.mts +2 -2
- package/dist/api/backgroundWork.mjs +1 -1
- package/dist/api/capabilityCeiling.cjs +1 -1
- package/dist/api/capabilityCeiling.d.cts +3 -3
- package/dist/api/capabilityCeiling.d.mts +3 -3
- package/dist/api/capabilityCeiling.mjs +1 -2
- package/dist/api/delegation.cjs +1 -1
- package/dist/api/delegation.d.cts +1 -1
- package/dist/api/delegation.d.mts +1 -1
- package/dist/api/delegation.mjs +1 -1
- package/dist/api/teamSnapshot.cjs +1 -1
- package/dist/api/teamSnapshot.d.cts +2 -2
- package/dist/api/teamSnapshot.d.mts +2 -2
- package/dist/api/teamSnapshot.mjs +1 -2
- package/dist/commands/slash/chainExpression.cjs.map +1 -0
- package/dist/commands/slash/chainExpression.mjs.map +1 -0
- package/dist/commands/slash/doctor.cjs +5 -0
- package/dist/commands/slash/doctor.cjs.map +1 -0
- package/dist/commands/slash/doctor.mjs +5 -0
- package/dist/{slash/doctor.cjs.map → commands/slash/doctor.mjs.map} +1 -1
- package/dist/{slash → commands/slash}/slashCommands.cjs +1 -1
- package/dist/commands/slash/slashCommands.cjs.map +1 -0
- package/dist/{slash → commands/slash}/slashCommands.mjs +2 -2
- package/dist/commands/slash/slashCommands.mjs.map +1 -0
- package/dist/commands/slash/spawnRequestMapping.cjs.map +1 -0
- package/dist/commands/slash/spawnRequestMapping.mjs.map +1 -0
- package/dist/commands/slash/subagentLaunch.cjs +2 -0
- package/dist/commands/slash/subagentLaunch.cjs.map +1 -0
- package/dist/commands/slash/subagentLaunch.mjs +2 -0
- package/dist/commands/slash/subagentLaunch.mjs.map +1 -0
- package/dist/container/globalBridge.cjs.map +1 -1
- package/dist/container/globalBridge.d.cts +1 -1
- package/dist/container/globalBridge.d.mts +1 -1
- package/dist/container/globalBridge.mjs.map +1 -1
- package/dist/container/index.cjs +1 -1
- package/dist/container/index.cjs.map +1 -1
- package/dist/container/index.d.cts +2 -1
- package/dist/container/index.d.cts.map +1 -1
- package/dist/container/index.d.mts +2 -1
- package/dist/container/index.d.mts.map +1 -1
- package/dist/container/index.mjs +1 -1
- package/dist/container/index.mjs.map +1 -1
- package/dist/container/modules/agents.cjs +1 -1
- package/dist/container/modules/agents.cjs.map +1 -1
- package/dist/container/modules/agents.mjs +1 -1
- package/dist/container/modules/agents.mjs.map +1 -1
- package/dist/container/modules/core.cjs +1 -1
- package/dist/container/modules/core.cjs.map +1 -1
- package/dist/container/modules/core.mjs +1 -1
- package/dist/container/modules/core.mjs.map +1 -1
- package/dist/container/modules/extensions.cjs +1 -1
- package/dist/container/modules/extensions.cjs.map +1 -1
- package/dist/container/modules/extensions.mjs +1 -1
- package/dist/container/modules/extensions.mjs.map +1 -1
- package/dist/container/modules/intercom.cjs +1 -1
- package/dist/container/modules/intercom.cjs.map +1 -1
- package/dist/container/modules/intercom.mjs +1 -1
- package/dist/container/modules/intercom.mjs.map +1 -1
- package/dist/container/modules/runs.cjs +1 -1
- package/dist/container/modules/runs.cjs.map +1 -1
- package/dist/container/modules/runs.mjs +1 -1
- package/dist/container/modules/runs.mjs.map +1 -1
- package/dist/container/types.cjs +1 -1
- package/dist/container/types.cjs.map +1 -1
- package/dist/container/types.d.cts +1 -0
- package/dist/container/types.d.cts.map +1 -1
- package/dist/container/types.d.mts +1 -0
- package/dist/container/types.d.mts.map +1 -1
- package/dist/container/types.mjs +1 -1
- package/dist/container/types.mjs.map +1 -1
- package/dist/env.cjs +1 -2
- package/dist/env.d.cts +2 -65
- package/dist/env.d.mts +2 -65
- package/dist/env.mjs +1 -1
- package/dist/env.mjs.map +1 -1
- package/dist/extensions/config.cjs.map +1 -1
- package/dist/extensions/config.mjs.map +1 -1
- package/dist/extensions/delegationBridge.cjs.map +1 -1
- package/dist/extensions/delegationBridge.mjs.map +1 -1
- 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/fablePlanBridge.cjs +1 -1
- package/dist/extensions/fablePlanBridge.cjs.map +1 -1
- package/dist/extensions/fablePlanBridge.mjs +1 -1
- package/dist/extensions/fablePlanBridge.mjs.map +1 -1
- package/dist/extensions/managementActions.cjs +1 -1
- package/dist/extensions/managementActions.cjs.map +1 -1
- package/dist/extensions/managementActions.mjs +1 -1
- package/dist/extensions/managementActions.mjs.map +1 -1
- package/dist/extensions/operationJournal.cjs +1 -1
- package/dist/extensions/operationJournal.cjs.map +1 -1
- package/dist/extensions/operationJournal.mjs +1 -1
- package/dist/extensions/operationJournal.mjs.map +1 -1
- package/dist/extensions/orchestratorPrompt.cjs +5 -6
- package/dist/extensions/orchestratorPrompt.cjs.map +1 -1
- package/dist/extensions/orchestratorPrompt.mjs +5 -6
- package/dist/extensions/orchestratorPrompt.mjs.map +1 -1
- package/dist/extensions/schemas.mjs.map +1 -1
- package/dist/extensions/spawnPlan.cjs +3 -2
- package/dist/extensions/spawnPlan.cjs.map +1 -1
- package/dist/extensions/spawnPlan.mjs +3 -2
- package/dist/extensions/spawnPlan.mjs.map +1 -1
- package/dist/extensions/standard.cjs +1 -1
- package/dist/extensions/standard.cjs.map +1 -1
- package/dist/extensions/standard.mjs +1 -1
- package/dist/extensions/standard.mjs.map +1 -1
- package/dist/extensions/statusViews.cjs +1 -1
- package/dist/extensions/statusViews.cjs.map +1 -1
- package/dist/extensions/statusViews.mjs +2 -2
- package/dist/extensions/statusViews.mjs.map +1 -1
- package/dist/extensions/subagentPromptRuntime.cjs +11 -11
- package/dist/extensions/subagentPromptRuntime.cjs.map +1 -1
- package/dist/extensions/subagentPromptRuntime.d.cts.map +1 -1
- package/dist/extensions/subagentPromptRuntime.d.mts.map +1 -1
- package/dist/extensions/subagentPromptRuntime.mjs +5 -5
- package/dist/extensions/subagentPromptRuntime.mjs.map +1 -1
- package/dist/extensions/subagentTool.cjs +5 -6
- package/dist/extensions/subagentTool.cjs.map +1 -1
- package/dist/extensions/subagentTool.mjs +5 -6
- package/dist/extensions/subagentTool.mjs.map +1 -1
- package/dist/extensions/toolDescription.cjs +1 -1
- package/dist/extensions/toolDescription.cjs.map +1 -1
- package/dist/extensions/toolDescription.mjs +1 -1
- package/dist/extensions/toolDescription.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/runs/background/cliRunnerEntry.cjs +1 -2
- package/dist/runs/background/cliRunnerEntry.mjs +1 -2
- package/dist/runs/sdkRunnerEntry.cjs +1 -2
- package/dist/runs/sdkRunnerEntry.d.cts +2 -1
- package/dist/runs/sdkRunnerEntry.d.mts +2 -1
- package/dist/runs/sdkRunnerEntry.mjs +1 -2
- package/dist/schemas/team/backgroundWork.cjs +2 -0
- package/dist/schemas/team/backgroundWork.cjs.map +1 -0
- package/dist/{protocol → schemas/team}/backgroundWork.d.cts +2 -2
- package/dist/schemas/team/backgroundWork.d.cts.map +1 -0
- package/dist/{protocol → schemas/team}/backgroundWork.d.mts +2 -2
- package/dist/schemas/team/backgroundWork.d.mts.map +1 -0
- package/dist/schemas/team/backgroundWork.mjs +2 -0
- package/dist/{protocol/backgroundWork.cjs.map → schemas/team/backgroundWork.mjs.map} +1 -1
- package/dist/schemas/team/capabilityCeiling.cjs +2 -0
- package/dist/schemas/team/capabilityCeiling.cjs.map +1 -0
- package/dist/{protocol → schemas/team}/capabilityCeiling.d.cts +3 -3
- package/dist/schemas/team/capabilityCeiling.d.cts.map +1 -0
- package/dist/{protocol → schemas/team}/capabilityCeiling.d.mts +3 -3
- package/dist/schemas/team/capabilityCeiling.d.mts.map +1 -0
- package/dist/schemas/team/capabilityCeiling.mjs +2 -0
- package/dist/schemas/team/capabilityCeiling.mjs.map +1 -0
- package/dist/schemas/team/delegation.cjs.map +1 -0
- package/dist/{protocol → schemas/team}/delegation.d.cts +1 -1
- package/dist/schemas/team/delegation.d.cts.map +1 -0
- package/dist/{protocol → schemas/team}/delegation.d.mts +1 -1
- package/dist/schemas/team/delegation.d.mts.map +1 -0
- package/dist/schemas/team/delegation.mjs.map +1 -0
- package/dist/schemas/team/packageConfig.cjs +2 -0
- package/dist/schemas/team/packageConfig.cjs.map +1 -0
- package/dist/schemas/team/packageConfig.mjs +2 -0
- package/dist/schemas/team/packageConfig.mjs.map +1 -0
- package/dist/services/agents/discovery.cjs +2 -0
- package/dist/services/agents/discovery.cjs.map +1 -0
- package/dist/services/agents/discovery.mjs +2 -0
- package/dist/services/agents/discovery.mjs.map +1 -0
- package/dist/services/agents/frontmatter.cjs.map +1 -0
- package/dist/{agents → services/agents}/frontmatter.mjs +1 -1
- package/dist/services/agents/frontmatter.mjs.map +1 -0
- package/dist/services/agents/loader.cjs +2 -0
- package/dist/services/agents/loader.cjs.map +1 -0
- package/dist/services/agents/loader.mjs +2 -0
- package/dist/services/agents/loader.mjs.map +1 -0
- package/dist/services/agents/memory.cjs +3 -0
- package/dist/services/agents/memory.cjs.map +1 -0
- package/dist/{agents → services/agents}/memory.mjs +1 -1
- package/dist/services/agents/memory.mjs.map +1 -0
- package/dist/services/agents/projectRoot.cjs +2 -0
- package/dist/services/agents/projectRoot.cjs.map +1 -0
- package/dist/services/agents/projectRoot.mjs +2 -0
- package/dist/services/agents/projectRoot.mjs.map +1 -0
- package/dist/services/agents/settings.cjs +2 -0
- package/dist/services/agents/settings.cjs.map +1 -0
- package/dist/services/agents/settings.mjs +2 -0
- package/dist/services/agents/settings.mjs.map +1 -0
- package/dist/services/agents/skills.cjs +0 -0
- package/dist/services/agents/skills.cjs.map +1 -0
- package/dist/services/agents/skills.mjs +5 -0
- package/dist/services/agents/skills.mjs.map +1 -0
- package/dist/{agents → services/agents}/types.d.cts +4 -4
- package/dist/services/agents/types.d.cts.map +1 -0
- package/dist/{agents → services/agents}/types.d.mts +4 -4
- package/dist/services/agents/types.d.mts.map +1 -0
- package/dist/services/api/backgroundWork.cjs +1 -0
- package/dist/services/api/backgroundWork.d.cts +1 -0
- package/dist/services/api/backgroundWork.d.mts +1 -0
- package/dist/services/api/backgroundWork.mjs +1 -0
- package/dist/services/api/capabilityCeiling.cjs +1 -0
- package/dist/services/api/capabilityCeiling.d.cts +2 -0
- package/dist/services/api/capabilityCeiling.d.mts +2 -0
- package/dist/services/api/capabilityCeiling.mjs +2 -0
- package/dist/services/api/capabilityCeiling.mjs.map +1 -0
- package/dist/services/api/teamSnapshot.cjs +1 -0
- package/dist/services/api/teamSnapshot.d.cts +1 -0
- package/dist/services/api/teamSnapshot.d.mts +1 -0
- package/dist/services/api/teamSnapshot.mjs +2 -0
- package/dist/services/api/teamSnapshot.mjs.map +1 -0
- package/dist/services/intercom/intercomBridge.cjs.map +1 -0
- package/dist/services/intercom/intercomBridge.mjs.map +1 -0
- package/dist/services/intercom/nativeTeamChannel.cjs +5 -0
- package/dist/services/intercom/nativeTeamChannel.cjs.map +1 -0
- package/dist/{intercom → services/intercom}/nativeTeamChannel.d.cts +1 -1
- package/dist/services/intercom/nativeTeamChannel.d.cts.map +1 -0
- package/dist/{intercom → services/intercom}/nativeTeamChannel.d.mts +1 -1
- package/dist/services/intercom/nativeTeamChannel.d.mts.map +1 -0
- package/dist/services/intercom/nativeTeamChannel.mjs +5 -0
- package/dist/services/intercom/nativeTeamChannel.mjs.map +1 -0
- package/dist/services/intercom/supervisorControlChannel.cjs +2 -0
- package/dist/services/intercom/supervisorControlChannel.cjs.map +1 -0
- package/dist/{intercom → services/intercom}/supervisorControlChannel.mjs +1 -1
- package/dist/services/intercom/supervisorControlChannel.mjs.map +1 -0
- package/dist/services/runs/background/asyncExecution.cjs +2 -0
- package/dist/services/runs/background/asyncExecution.cjs.map +1 -0
- package/dist/services/runs/background/asyncExecution.mjs +2 -0
- package/dist/services/runs/background/asyncExecution.mjs.map +1 -0
- package/dist/services/runs/background/asyncJobTracker.cjs +1 -0
- package/dist/services/runs/background/asyncJobTracker.mjs +2 -0
- package/dist/services/runs/background/asyncJobTracker.mjs.map +1 -0
- package/dist/services/runs/background/cliRunnerEntry.cjs +2 -0
- package/dist/services/runs/background/cliRunnerEntry.cjs.map +1 -0
- package/dist/services/runs/background/cliRunnerEntry.mjs +2 -0
- package/dist/services/runs/background/cliRunnerEntry.mjs.map +1 -0
- package/dist/services/runs/background/completionBatcher.cjs.map +1 -0
- package/dist/services/runs/background/completionBatcher.mjs +2 -0
- package/dist/services/runs/background/completionBatcher.mjs.map +1 -0
- package/dist/{runs → services/runs}/background/notify.cjs +1 -1
- package/dist/services/runs/background/notify.cjs.map +1 -0
- package/dist/{runs → services/runs}/background/notify.mjs +1 -1
- package/dist/services/runs/background/notify.mjs.map +1 -0
- package/dist/services/runs/background/parentWatchdog.cjs.map +1 -0
- package/dist/services/runs/background/parentWatchdog.mjs.map +1 -0
- package/dist/services/runs/background/processTerminal.cjs +1 -0
- package/dist/services/runs/background/processTerminal.mjs +2 -0
- package/dist/services/runs/background/processTerminal.mjs.map +1 -0
- package/dist/services/runs/background/resultWatcher.cjs +1 -0
- package/dist/services/runs/background/resultWatcher.mjs +2 -0
- package/dist/services/runs/background/resultWatcher.mjs.map +1 -0
- package/dist/services/runs/background/runIdResolver.cjs +1 -0
- package/dist/services/runs/background/runIdResolver.mjs +2 -0
- package/dist/services/runs/background/runIdResolver.mjs.map +1 -0
- package/dist/services/runs/background/runnerBootstrap.cjs +2 -0
- package/dist/services/runs/background/runnerBootstrap.cjs.map +1 -0
- package/dist/services/runs/background/runnerBootstrap.mjs +2 -0
- package/dist/services/runs/background/runnerBootstrap.mjs.map +1 -0
- package/dist/services/runs/background/runnerExecution.cjs +2 -0
- package/dist/services/runs/background/runnerExecution.cjs.map +1 -0
- package/dist/services/runs/background/runnerExecution.mjs +2 -0
- package/dist/services/runs/background/runnerExecution.mjs.map +1 -0
- package/dist/{runs → services/runs}/background/runnerReporting.cjs +2 -2
- package/dist/services/runs/background/runnerReporting.cjs.map +1 -0
- package/dist/{runs → services/runs}/background/runnerReporting.mjs +2 -2
- package/dist/services/runs/background/runnerReporting.mjs.map +1 -0
- package/dist/services/runs/background/runnerTeamMembership.cjs +2 -0
- package/dist/services/runs/background/runnerTeamMembership.cjs.map +1 -0
- package/dist/services/runs/background/runnerTeamMembership.mjs +2 -0
- package/dist/services/runs/background/runnerTeamMembership.mjs.map +1 -0
- package/dist/services/runs/background/spawnHandshake.cjs +2 -0
- package/dist/services/runs/background/spawnHandshake.cjs.map +1 -0
- package/dist/services/runs/background/spawnHandshake.mjs +2 -0
- package/dist/services/runs/background/spawnHandshake.mjs.map +1 -0
- package/dist/services/runs/background/staleRunReconciler.cjs +1 -0
- package/dist/services/runs/background/staleRunReconciler.mjs +2 -0
- package/dist/services/runs/background/staleRunReconciler.mjs.map +1 -0
- package/dist/services/runs/background/statusReader.cjs +1 -0
- package/dist/services/runs/background/statusReader.mjs +2 -0
- package/dist/services/runs/background/statusReader.mjs.map +1 -0
- package/dist/services/runs/background/statusWriter.cjs +2 -0
- package/dist/services/runs/background/statusWriter.cjs.map +1 -0
- package/dist/services/runs/background/statusWriter.mjs +2 -0
- package/dist/services/runs/background/statusWriter.mjs.map +1 -0
- package/dist/services/runs/background/subagentWait.cjs +2 -0
- package/dist/services/runs/background/subagentWait.cjs.map +1 -0
- package/dist/services/runs/background/subagentWait.mjs +2 -0
- package/dist/services/runs/background/subagentWait.mjs.map +1 -0
- package/dist/{runs/background/terminalPersistence.mjs → services/runs/background/terminalPersistence.cjs} +2 -2
- package/dist/services/runs/background/terminalPersistence.cjs.map +1 -0
- package/dist/services/runs/background/terminalPersistence.mjs +2 -0
- package/dist/services/runs/background/terminalPersistence.mjs.map +1 -0
- package/dist/services/runs/extensionErrorTelemetry.cjs +2 -0
- package/dist/services/runs/extensionErrorTelemetry.cjs.map +1 -0
- package/dist/services/runs/extensionErrorTelemetry.mjs +2 -0
- package/dist/services/runs/extensionErrorTelemetry.mjs.map +1 -0
- package/dist/services/runs/registry/processGroup.cjs.map +1 -0
- package/dist/services/runs/registry/processGroup.mjs.map +1 -0
- package/dist/services/runs/registry/runRegistry.cjs +1 -0
- package/dist/services/runs/registry/runRegistry.mjs +2 -0
- package/dist/services/runs/registry/runRegistry.mjs.map +1 -0
- package/dist/services/runs/registry/sessionLifecycle.cjs +2 -0
- package/dist/services/runs/registry/sessionLifecycle.cjs.map +1 -0
- package/dist/services/runs/registry/sessionLifecycle.mjs +2 -0
- package/dist/services/runs/registry/sessionLifecycle.mjs.map +1 -0
- package/dist/services/runs/registry/suspendedRuns.cjs +1 -0
- package/dist/services/runs/registry/suspendedRuns.mjs +2 -0
- package/dist/services/runs/registry/suspendedRuns.mjs.map +1 -0
- package/dist/services/runs/sdkRunnerEntry.cjs +1 -0
- package/dist/services/runs/sdkRunnerEntry.mjs +1 -0
- package/dist/services/runs/shared/claudeFableProfile.cjs +4 -0
- package/dist/services/runs/shared/claudeFableProfile.cjs.map +1 -0
- package/dist/services/runs/shared/claudeFableProfile.mjs +4 -0
- package/dist/services/runs/shared/claudeFableProfile.mjs.map +1 -0
- package/dist/services/runs/shared/depthGuard.cjs +2 -0
- package/dist/services/runs/shared/depthGuard.cjs.map +1 -0
- package/dist/services/runs/shared/depthGuard.mjs +2 -0
- package/dist/services/runs/shared/depthGuard.mjs.map +1 -0
- package/dist/services/runs/shared/mcpDirectToolAllowlist.cjs +2 -0
- package/dist/services/runs/shared/mcpDirectToolAllowlist.cjs.map +1 -0
- package/dist/services/runs/shared/mcpDirectToolAllowlist.mjs +2 -0
- package/dist/services/runs/shared/mcpDirectToolAllowlist.mjs.map +1 -0
- package/dist/services/runs/shared/modelFallback.cjs +2 -0
- package/dist/services/runs/shared/modelFallback.cjs.map +1 -0
- package/dist/services/runs/shared/modelFallback.mjs +2 -0
- package/dist/services/runs/shared/modelFallback.mjs.map +1 -0
- package/dist/services/runs/shared/modelScope.cjs +2 -0
- package/dist/services/runs/shared/modelScope.cjs.map +1 -0
- package/dist/services/runs/shared/modelScope.mjs +2 -0
- package/dist/services/runs/shared/modelScope.mjs.map +1 -0
- package/dist/services/runs/shared/nestedPath.cjs +2 -0
- package/dist/services/runs/shared/nestedPath.cjs.map +1 -0
- package/dist/services/runs/shared/nestedPath.mjs +2 -0
- package/dist/services/runs/shared/nestedPath.mjs.map +1 -0
- package/dist/services/runs/shared/piArgs.cjs +2 -0
- package/dist/services/runs/shared/piArgs.cjs.map +1 -0
- package/dist/services/runs/shared/piArgs.mjs +2 -0
- package/dist/services/runs/shared/piArgs.mjs.map +1 -0
- package/dist/services/runs/shared/piSpawn.cjs +2 -0
- package/dist/services/runs/shared/piSpawn.cjs.map +1 -0
- package/dist/services/runs/shared/piSpawn.mjs +2 -0
- package/dist/services/runs/shared/piSpawn.mjs.map +1 -0
- package/dist/services/runs/shared/runWithConcurrency.cjs +2 -0
- package/dist/services/runs/shared/runWithConcurrency.cjs.map +1 -0
- package/dist/services/runs/shared/runWithConcurrency.d.cts +25 -0
- package/dist/services/runs/shared/runWithConcurrency.d.cts.map +1 -0
- package/dist/services/runs/shared/runWithConcurrency.d.mts +25 -0
- package/dist/services/runs/shared/runWithConcurrency.d.mts.map +1 -0
- package/dist/services/runs/shared/runWithConcurrency.mjs +2 -0
- package/dist/services/runs/shared/runWithConcurrency.mjs.map +1 -0
- package/dist/services/runs/shared/runtimeRegistry.cjs +2 -0
- package/dist/services/runs/shared/runtimeRegistry.cjs.map +1 -0
- package/dist/services/runs/shared/runtimeRegistry.mjs +2 -0
- package/dist/services/runs/shared/runtimeRegistry.mjs.map +1 -0
- package/dist/services/runs/shared/structuredOutput.cjs +2 -0
- package/dist/{runs → services/runs}/shared/structuredOutput.cjs.map +1 -1
- package/dist/services/runs/shared/structuredOutput.mjs +2 -0
- package/dist/{runs → services/runs}/shared/structuredOutput.mjs.map +1 -1
- package/dist/services/runs/shared/toolAvailability.cjs +2 -0
- package/dist/services/runs/shared/toolAvailability.cjs.map +1 -0
- package/dist/services/runs/shared/toolAvailability.mjs +2 -0
- package/dist/services/runs/shared/toolAvailability.mjs.map +1 -0
- package/dist/services/runs/shared/toolBudget.cjs +2 -0
- package/dist/services/runs/shared/toolBudget.cjs.map +1 -0
- package/dist/services/runs/shared/toolBudget.mjs +2 -0
- package/dist/services/runs/shared/toolBudget.mjs.map +1 -0
- package/dist/shared/artifacts.cjs.map +1 -1
- package/dist/shared/artifacts.mjs.map +1 -1
- package/dist/shared/atomicJson.cjs +1 -2
- package/dist/shared/atomicJson.mjs +1 -1
- package/dist/shared/atomicJson.mjs.map +1 -1
- package/dist/shared/childTranscript.cjs +1 -5
- package/dist/shared/childTranscript.mjs +1 -4
- package/dist/shared/childTranscript.mjs.map +1 -1
- package/dist/shared/fileSystemRetry.cjs +1 -1
- package/dist/shared/fileSystemRetry.cjs.map +1 -1
- package/dist/shared/fileSystemRetry.mjs +1 -1
- package/dist/shared/fileSystemRetry.mjs.map +1 -1
- package/dist/shared/formatters.cjs.map +1 -1
- package/dist/shared/formatters.mjs.map +1 -1
- package/dist/shared/paths.cjs +1 -1
- package/dist/shared/paths.cjs.map +1 -1
- package/dist/shared/paths.mjs +1 -1
- package/dist/shared/paths.mjs.map +1 -1
- package/dist/shared/pollScheduler.cjs +1 -2
- package/dist/shared/pollScheduler.mjs +1 -1
- package/dist/shared/pollScheduler.mjs.map +1 -1
- package/dist/shared/scopeOwner.cjs +1 -2
- package/dist/shared/scopeOwner.mjs +1 -1
- package/dist/shared/scopeOwner.mjs.map +1 -1
- package/dist/tui/agentCatalog.cjs +1 -1
- package/dist/tui/agentCatalog.cjs.map +1 -1
- package/dist/tui/agentCatalog.mjs +1 -1
- package/dist/tui/agentCatalog.mjs.map +1 -1
- package/dist/tui/agentResourceProjection.cjs +1 -1
- package/dist/tui/agentResourceProjection.cjs.map +1 -1
- package/dist/tui/agentResourceProjection.mjs +1 -1
- package/dist/tui/agentResourceProjection.mjs.map +1 -1
- package/dist/tui/completionNotice.cjs +1 -1
- package/dist/tui/completionNotice.cjs.map +1 -1
- package/dist/tui/completionNotice.mjs +1 -1
- package/dist/tui/completionNotice.mjs.map +1 -1
- package/dist/tui/fleet.cjs +2 -2
- package/dist/tui/fleet.cjs.map +1 -1
- package/dist/tui/fleet.mjs +2 -2
- package/dist/tui/fleet.mjs.map +1 -1
- package/dist/tui/fleetAgentView.cjs.map +1 -1
- package/dist/tui/fleetAgentView.mjs.map +1 -1
- package/dist/tui/fleetStatus.cjs +1 -1
- package/dist/tui/fleetStatus.cjs.map +1 -1
- package/dist/tui/fleetStatus.mjs +1 -1
- package/dist/tui/fleetStatus.mjs.map +1 -1
- package/dist/tui/fleetTranscript.cjs +1 -1
- package/dist/tui/fleetTranscript.cjs.map +1 -1
- package/dist/tui/fleetTranscript.mjs +1 -1
- package/dist/tui/fleetTranscript.mjs.map +1 -1
- package/dist/tui/register.cjs +1 -1
- package/dist/tui/register.cjs.map +1 -1
- package/dist/tui/register.mjs +1 -1
- package/dist/tui/register.mjs.map +1 -1
- package/dist/tui/subagentToolRender.cjs +3 -0
- package/dist/tui/subagentToolRender.cjs.map +1 -0
- package/dist/tui/subagentToolRender.mjs +3 -0
- package/dist/tui/subagentToolRender.mjs.map +1 -0
- package/dist/{types.d.cts → types/index.d.cts} +2 -2
- package/dist/types/index.d.cts.map +1 -0
- package/dist/{types.d.mts → types/index.d.mts} +2 -2
- package/dist/types/index.d.mts.map +1 -0
- package/package.json +23 -16
- package/dist/agents/discovery.cjs +0 -2
- package/dist/agents/discovery.cjs.map +0 -1
- package/dist/agents/discovery.mjs +0 -2
- package/dist/agents/discovery.mjs.map +0 -1
- package/dist/agents/frontmatter.cjs.map +0 -1
- package/dist/agents/frontmatter.mjs.map +0 -1
- package/dist/agents/loader.cjs +0 -2
- package/dist/agents/loader.cjs.map +0 -1
- package/dist/agents/loader.mjs +0 -2
- package/dist/agents/loader.mjs.map +0 -1
- package/dist/agents/memory.cjs +0 -3
- package/dist/agents/memory.cjs.map +0 -1
- package/dist/agents/memory.mjs.map +0 -1
- package/dist/agents/projectRoot.cjs +0 -2
- package/dist/agents/projectRoot.cjs.map +0 -1
- package/dist/agents/projectRoot.mjs +0 -2
- package/dist/agents/projectRoot.mjs.map +0 -1
- package/dist/agents/settings.cjs +0 -2
- package/dist/agents/settings.cjs.map +0 -1
- package/dist/agents/settings.mjs +0 -2
- package/dist/agents/settings.mjs.map +0 -1
- package/dist/agents/skills.cjs +0 -0
- package/dist/agents/skills.cjs.map +0 -1
- package/dist/agents/skills.mjs +0 -5
- package/dist/agents/skills.mjs.map +0 -1
- package/dist/agents/types.d.cts.map +0 -1
- package/dist/agents/types.d.mts.map +0 -1
- package/dist/api/capabilityCeiling.mjs.map +0 -1
- package/dist/api/teamSnapshot.mjs.map +0 -1
- package/dist/env.cjs.map +0 -1
- package/dist/env.d.cts.map +0 -1
- package/dist/env.d.mts.map +0 -1
- package/dist/extension.cjs +0 -2
- package/dist/extension.cjs.map +0 -1
- package/dist/extension.mjs +0 -2
- package/dist/extension.mjs.map +0 -1
- package/dist/intercom/intercomBridge.cjs.map +0 -1
- package/dist/intercom/intercomBridge.mjs.map +0 -1
- package/dist/intercom/nativeTeamChannel.cjs +0 -5
- package/dist/intercom/nativeTeamChannel.cjs.map +0 -1
- package/dist/intercom/nativeTeamChannel.d.cts.map +0 -1
- package/dist/intercom/nativeTeamChannel.d.mts.map +0 -1
- package/dist/intercom/nativeTeamChannel.mjs +0 -5
- package/dist/intercom/nativeTeamChannel.mjs.map +0 -1
- package/dist/intercom/supervisorControlChannel.cjs +0 -2
- package/dist/intercom/supervisorControlChannel.cjs.map +0 -1
- package/dist/intercom/supervisorControlChannel.mjs.map +0 -1
- package/dist/protocol/backgroundWork.cjs +0 -2
- package/dist/protocol/backgroundWork.d.cts.map +0 -1
- package/dist/protocol/backgroundWork.d.mts.map +0 -1
- package/dist/protocol/backgroundWork.mjs +0 -2
- package/dist/protocol/backgroundWork.mjs.map +0 -1
- package/dist/protocol/capabilityCeiling.cjs +0 -2
- package/dist/protocol/capabilityCeiling.cjs.map +0 -1
- package/dist/protocol/capabilityCeiling.d.cts.map +0 -1
- package/dist/protocol/capabilityCeiling.d.mts.map +0 -1
- package/dist/protocol/capabilityCeiling.mjs +0 -2
- package/dist/protocol/capabilityCeiling.mjs.map +0 -1
- package/dist/protocol/delegation.cjs.map +0 -1
- package/dist/protocol/delegation.d.cts.map +0 -1
- package/dist/protocol/delegation.d.mts.map +0 -1
- package/dist/protocol/delegation.mjs.map +0 -1
- package/dist/runs/background/asyncExecution.cjs +0 -2
- package/dist/runs/background/asyncExecution.cjs.map +0 -1
- package/dist/runs/background/asyncExecution.mjs +0 -2
- package/dist/runs/background/asyncExecution.mjs.map +0 -1
- package/dist/runs/background/asyncJobTracker.cjs +0 -2
- package/dist/runs/background/asyncJobTracker.cjs.map +0 -1
- package/dist/runs/background/asyncJobTracker.mjs +0 -2
- package/dist/runs/background/asyncJobTracker.mjs.map +0 -1
- package/dist/runs/background/cliRunnerEntry.cjs.map +0 -1
- package/dist/runs/background/cliRunnerEntry.mjs.map +0 -1
- package/dist/runs/background/completionBatcher.cjs.map +0 -1
- package/dist/runs/background/completionBatcher.mjs +0 -2
- package/dist/runs/background/completionBatcher.mjs.map +0 -1
- package/dist/runs/background/notify.cjs.map +0 -1
- package/dist/runs/background/notify.mjs.map +0 -1
- package/dist/runs/background/parentWatchdog.cjs.map +0 -1
- package/dist/runs/background/parentWatchdog.mjs.map +0 -1
- package/dist/runs/background/processTerminal.cjs +0 -2
- package/dist/runs/background/processTerminal.cjs.map +0 -1
- package/dist/runs/background/processTerminal.mjs +0 -2
- package/dist/runs/background/processTerminal.mjs.map +0 -1
- package/dist/runs/background/resultWatcher.cjs +0 -2
- package/dist/runs/background/resultWatcher.cjs.map +0 -1
- package/dist/runs/background/resultWatcher.mjs +0 -2
- package/dist/runs/background/resultWatcher.mjs.map +0 -1
- package/dist/runs/background/runIdResolver.cjs +0 -2
- package/dist/runs/background/runIdResolver.cjs.map +0 -1
- package/dist/runs/background/runIdResolver.mjs +0 -2
- package/dist/runs/background/runIdResolver.mjs.map +0 -1
- package/dist/runs/background/runnerBootstrap.cjs +0 -2
- package/dist/runs/background/runnerBootstrap.cjs.map +0 -1
- package/dist/runs/background/runnerBootstrap.mjs +0 -2
- package/dist/runs/background/runnerBootstrap.mjs.map +0 -1
- package/dist/runs/background/runnerExecution.cjs +0 -2
- package/dist/runs/background/runnerExecution.cjs.map +0 -1
- package/dist/runs/background/runnerExecution.mjs +0 -2
- package/dist/runs/background/runnerExecution.mjs.map +0 -1
- package/dist/runs/background/runnerReporting.cjs.map +0 -1
- package/dist/runs/background/runnerReporting.mjs.map +0 -1
- package/dist/runs/background/runnerTeamMembership.cjs +0 -2
- package/dist/runs/background/runnerTeamMembership.cjs.map +0 -1
- package/dist/runs/background/runnerTeamMembership.mjs +0 -2
- package/dist/runs/background/runnerTeamMembership.mjs.map +0 -1
- package/dist/runs/background/spawnHandshake.cjs +0 -2
- package/dist/runs/background/spawnHandshake.cjs.map +0 -1
- package/dist/runs/background/spawnHandshake.mjs +0 -2
- package/dist/runs/background/spawnHandshake.mjs.map +0 -1
- package/dist/runs/background/staleRunReconciler.cjs +0 -2
- package/dist/runs/background/staleRunReconciler.cjs.map +0 -1
- package/dist/runs/background/staleRunReconciler.mjs +0 -2
- package/dist/runs/background/staleRunReconciler.mjs.map +0 -1
- package/dist/runs/background/statusReader.cjs +0 -2
- package/dist/runs/background/statusReader.cjs.map +0 -1
- package/dist/runs/background/statusReader.mjs +0 -2
- package/dist/runs/background/statusReader.mjs.map +0 -1
- package/dist/runs/background/statusWriter.cjs +0 -2
- package/dist/runs/background/statusWriter.cjs.map +0 -1
- package/dist/runs/background/statusWriter.mjs +0 -2
- package/dist/runs/background/statusWriter.mjs.map +0 -1
- package/dist/runs/background/subagentWait.cjs +0 -2
- package/dist/runs/background/subagentWait.cjs.map +0 -1
- package/dist/runs/background/subagentWait.mjs +0 -2
- package/dist/runs/background/subagentWait.mjs.map +0 -1
- package/dist/runs/background/terminalPersistence.cjs +0 -2
- package/dist/runs/background/terminalPersistence.cjs.map +0 -1
- package/dist/runs/background/terminalPersistence.mjs.map +0 -1
- package/dist/runs/registry/processGroup.cjs.map +0 -1
- package/dist/runs/registry/processGroup.mjs.map +0 -1
- package/dist/runs/registry/runRegistry.cjs +0 -2
- package/dist/runs/registry/runRegistry.cjs.map +0 -1
- package/dist/runs/registry/runRegistry.mjs +0 -2
- package/dist/runs/registry/runRegistry.mjs.map +0 -1
- package/dist/runs/registry/sessionLifecycle.cjs +0 -2
- package/dist/runs/registry/sessionLifecycle.cjs.map +0 -1
- package/dist/runs/registry/sessionLifecycle.mjs +0 -2
- package/dist/runs/registry/sessionLifecycle.mjs.map +0 -1
- package/dist/runs/registry/suspendedRuns.cjs +0 -4
- package/dist/runs/registry/suspendedRuns.cjs.map +0 -1
- package/dist/runs/registry/suspendedRuns.mjs +0 -4
- package/dist/runs/registry/suspendedRuns.mjs.map +0 -1
- package/dist/runs/sdkRunnerEntry.cjs.map +0 -1
- package/dist/runs/sdkRunnerEntry.mjs.map +0 -1
- package/dist/runs/shared/claudeFableProfile.cjs +0 -4
- package/dist/runs/shared/claudeFableProfile.cjs.map +0 -1
- package/dist/runs/shared/claudeFableProfile.mjs +0 -4
- package/dist/runs/shared/claudeFableProfile.mjs.map +0 -1
- package/dist/runs/shared/depthGuard.cjs +0 -2
- package/dist/runs/shared/depthGuard.cjs.map +0 -1
- package/dist/runs/shared/depthGuard.mjs +0 -2
- package/dist/runs/shared/depthGuard.mjs.map +0 -1
- package/dist/runs/shared/mcpDirectToolAllowlist.cjs +0 -2
- package/dist/runs/shared/mcpDirectToolAllowlist.cjs.map +0 -1
- package/dist/runs/shared/mcpDirectToolAllowlist.mjs +0 -2
- package/dist/runs/shared/mcpDirectToolAllowlist.mjs.map +0 -1
- package/dist/runs/shared/modelFallback.cjs +0 -2
- package/dist/runs/shared/modelFallback.cjs.map +0 -1
- package/dist/runs/shared/modelFallback.mjs +0 -2
- package/dist/runs/shared/modelFallback.mjs.map +0 -1
- package/dist/runs/shared/modelScope.cjs +0 -2
- package/dist/runs/shared/modelScope.cjs.map +0 -1
- package/dist/runs/shared/modelScope.mjs +0 -2
- package/dist/runs/shared/modelScope.mjs.map +0 -1
- package/dist/runs/shared/nestedPath.cjs +0 -2
- package/dist/runs/shared/nestedPath.cjs.map +0 -1
- package/dist/runs/shared/nestedPath.mjs +0 -2
- package/dist/runs/shared/nestedPath.mjs.map +0 -1
- package/dist/runs/shared/piArgs.cjs +0 -2
- package/dist/runs/shared/piArgs.cjs.map +0 -1
- package/dist/runs/shared/piArgs.mjs +0 -2
- package/dist/runs/shared/piArgs.mjs.map +0 -1
- package/dist/runs/shared/piSpawn.cjs +0 -2
- package/dist/runs/shared/piSpawn.cjs.map +0 -1
- package/dist/runs/shared/piSpawn.mjs +0 -2
- package/dist/runs/shared/piSpawn.mjs.map +0 -1
- package/dist/runs/shared/runWithConcurrency.cjs +0 -2
- package/dist/runs/shared/runWithConcurrency.cjs.map +0 -1
- package/dist/runs/shared/runWithConcurrency.mjs +0 -2
- package/dist/runs/shared/runWithConcurrency.mjs.map +0 -1
- package/dist/runs/shared/runtimeRegistry.cjs +0 -2
- package/dist/runs/shared/runtimeRegistry.cjs.map +0 -1
- package/dist/runs/shared/runtimeRegistry.mjs +0 -2
- package/dist/runs/shared/runtimeRegistry.mjs.map +0 -1
- package/dist/runs/shared/structuredOutput.cjs +0 -2
- package/dist/runs/shared/structuredOutput.mjs +0 -2
- package/dist/runs/shared/toolAvailability.cjs +0 -2
- package/dist/runs/shared/toolAvailability.cjs.map +0 -1
- package/dist/runs/shared/toolAvailability.mjs +0 -2
- package/dist/runs/shared/toolAvailability.mjs.map +0 -1
- package/dist/runs/shared/toolBudget.cjs +0 -2
- package/dist/runs/shared/toolBudget.cjs.map +0 -1
- package/dist/runs/shared/toolBudget.mjs +0 -2
- package/dist/runs/shared/toolBudget.mjs.map +0 -1
- package/dist/shared/atomicJson.cjs.map +0 -1
- package/dist/shared/childTranscript.cjs.map +0 -1
- package/dist/shared/pollScheduler.cjs.map +0 -1
- package/dist/shared/scopeOwner.cjs.map +0 -1
- package/dist/slash/chainExpression.cjs.map +0 -1
- package/dist/slash/chainExpression.mjs.map +0 -1
- package/dist/slash/doctor.cjs +0 -5
- package/dist/slash/doctor.mjs +0 -5
- package/dist/slash/doctor.mjs.map +0 -1
- package/dist/slash/slashCommands.cjs.map +0 -1
- package/dist/slash/slashCommands.mjs.map +0 -1
- package/dist/slash/spawnRequestMapping.cjs.map +0 -1
- package/dist/slash/spawnRequestMapping.mjs.map +0 -1
- package/dist/slash/subagentLaunch.cjs +0 -2
- package/dist/slash/subagentLaunch.cjs.map +0 -1
- package/dist/slash/subagentLaunch.mjs +0 -2
- package/dist/slash/subagentLaunch.mjs.map +0 -1
- package/dist/types.d.cts.map +0 -1
- package/dist/types.d.mts.map +0 -1
- /package/dist/{slash → commands/slash}/chainExpression.cjs +0 -0
- /package/dist/{slash → commands/slash}/chainExpression.mjs +0 -0
- /package/dist/{slash → commands/slash}/spawnRequestMapping.cjs +0 -0
- /package/dist/{slash → commands/slash}/spawnRequestMapping.mjs +0 -0
- /package/dist/{protocol → schemas/team}/delegation.cjs +0 -0
- /package/dist/{protocol → schemas/team}/delegation.mjs +0 -0
- /package/dist/{agents → services/agents}/frontmatter.cjs +0 -0
- /package/dist/{intercom → services/intercom}/intercomBridge.cjs +0 -0
- /package/dist/{intercom → services/intercom}/intercomBridge.mjs +0 -0
- /package/dist/{runs → services/runs}/background/completionBatcher.cjs +0 -0
- /package/dist/{runs → services/runs}/background/parentWatchdog.cjs +0 -0
- /package/dist/{runs → services/runs}/background/parentWatchdog.mjs +0 -0
- /package/dist/{runs → services/runs}/registry/processGroup.cjs +0 -0
- /package/dist/{runs → services/runs}/registry/processGroup.mjs +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.mjs","names":[],"sources":["../../../src/services/agents/settings.ts"],"sourcesContent":["/**\n * Agent settings: reading them, and applying what they say to discovered agents.\n *\n * Two things live here because they are the same contract seen from both ends.\n * Reading turns untyped JSON on disk into settings; applying folds those\n * settings over the agents discovery found. The precedence is fixed: project\n * settings beat user settings, an explicit per-agent override beats a bulk\n * switch, and for a custom agent the agent's own frontmatter beats both.\n *\n * That last rule is why builtins and custom agents take different paths.\n * Overriding a builtin replaces values outright, because a builtin has no file\n * the user could have edited instead. Overriding a custom agent only fills\n * fields its frontmatter left unset, so a settings default never silently\n * contradicts what the author wrote in the file.\n *\n * DESIGN PATTERNS:\n * - Reading is strict and throws with the offending path and field. A settings\n * file that is quietly half-ignored is worse than one that refuses to load,\n * because the user sees agents behaving in ways their config does not explain\n * - Applying is pure and copy-on-write. Every `apply*` returns new configs and\n * never mutates its input, so a cached discovery result cannot be corrupted\n * by a later pass over it\n * - Overriding a builtin snapshots the values it replaced into `override.base`,\n * which is what makes removing the override restore the builtin exactly\n *\n * AVOID:\n * - Trusting any shape read off disk without a real guard\n * - Mutating an `AgentConfig` in place\n * - Writing a settings file non-atomically; it holds the user's overrides\n */\n\nimport * as fs from 'node:fs';\nimport { writeAtomicJson } from '../../shared/atomicJson.ts';\nimport { readSettingsFileStrict } from '../../shared/configDir.ts';\nimport type { ModelScopeConfig, ToolBudgetConfig } from '../../types/index.ts';\nimport { getProjectAgentSettingsPath, getUserAgentSettingsPath } from './projectRoot.ts';\n\nexport { readSettingsFileStrict } from '../../shared/configDir.ts';\n\nimport type {\n AgentConfig,\n AgentModelSourceInfo,\n BuiltinAgentOverrideBase,\n BuiltinAgentOverrideConfig,\n SubagentSettings,\n} from './types.ts';\n\nconst SUBAGENTS_SETTINGS_KEY = 'subagents';\nconst AGENT_OVERRIDES_KEY = 'agentOverrides';\n/** Prefix marking a tool the child calls on an MCP server directly. */\nconst MCP_DIRECT_TOOL_PREFIX = 'mcp:';\n\n/** Which settings file an override came from, without the value snapshot. */\ntype OverrideScopeMeta = { scope: 'user' | 'project'; path: string };\n\n/**\n * The snapshot of a builtin's pre-override values.\n *\n * Widens the contract with `mcpDirectTools` because a builtin's tool list is\n * stored split in `AgentConfig` and must round-trip through the snapshot to be\n * restorable. See the report note on `BuiltinAgentOverrideBase`.\n */\nexport interface BuiltinOverrideSnapshot extends BuiltinAgentOverrideBase {\n mcpDirectTools?: string[];\n}\n\n/**\n * Returned whenever there is nothing to read.\n *\n * Shared rather than freshly built per call because it is returned on the hot\n * discovery path for every session with no project settings file.\n */\nexport const EMPTY_SUBAGENT_SETTINGS: SubagentSettings = { overrides: {} };\n\n/**\n * Which fields of a config came from its file's frontmatter.\n *\n * Keyed by the config object rather than by agent name because configs are\n * copied on write: each `apply*` pass produces new objects, and the new one\n * inherits the entry so later passes still know what the author declared.\n * A WeakMap means a discarded config's entry is collectable with it.\n */\nconst agentFrontmatterFields = new WeakMap<AgentConfig, Set<string>>();\n\n/** Record which fields a freshly parsed config took from frontmatter. */\nexport function setAgentFrontmatterFields(agent: AgentConfig, fields: Set<string>): void {\n agentFrontmatterFields.set(agent, fields);\n}\n\n/** True when the agent's file declared any of `fields` in its frontmatter. */\nexport function agentHasFrontmatterField(agent: AgentConfig, ...fields: string[]): boolean {\n const frontmatterFields = agentFrontmatterFields.get(agent);\n return frontmatterFields ? fields.some((field) => frontmatterFields.has(field)) : false;\n}\n\n/** Carry the frontmatter record onto a copy produced by an `apply*` pass. */\nfunction inheritFrontmatterFields(source: AgentConfig, next: AgentConfig): AgentConfig {\n const frontmatterFields = agentFrontmatterFields.get(source);\n if (frontmatterFields) agentFrontmatterFields.set(next, frontmatterFields);\n return next;\n}\n\n/** Split a flat tool list into host tools and direct MCP tools. */\nfunction splitToolList(rawTools: string[] | undefined): { tools?: string[]; mcpDirectTools?: string[] } {\n const mcpDirectTools: string[] = [];\n const tools: string[] = [];\n for (const tool of rawTools ?? []) {\n if (tool.startsWith(MCP_DIRECT_TOOL_PREFIX)) mcpDirectTools.push(tool.slice(MCP_DIRECT_TOOL_PREFIX.length));\n else tools.push(tool);\n }\n return {\n ...(rawTools !== undefined ? { tools } : {}),\n ...(mcpDirectTools.length > 0 ? { mcpDirectTools } : {}),\n };\n}\n\n/** Inverse of `splitToolList`, for writing a tool list back to settings. */\nfunction joinToolList(config: { tools?: string[]; mcpDirectTools?: string[] }): string[] | undefined {\n const joined = [\n ...(config.tools ?? []),\n ...(config.mcpDirectTools ?? []).map((tool) => `${MCP_DIRECT_TOOL_PREFIX}${tool}`),\n ];\n return joined.length > 0 ? joined : undefined;\n}\n\n/** Order-sensitive equality; a reordered tool list is a real change. */\nfunction arraysEqual(a: string[] | undefined, b: string[] | undefined): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n// ============================================================================\n// Reading\n// ============================================================================\n\n/**\n * Write a settings file atomically.\n *\n * This file holds every override the user configured. A partial write from a\n * crash mid-save would be read back as malformed on the next start and, because\n * reading is strict, would refuse to load at all.\n */\nexport function writeSettingsFile(filePath: string, settings: Record<string, unknown>): void {\n writeAtomicJson(filePath, settings);\n}\n\n/** Read a settings object at `key`, or undefined when it is absent or not an object. */\nfunction readObjectField(source: Record<string, unknown>, key: string): Record<string, unknown> | undefined {\n const value = source[key];\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;\n return value as Record<string, unknown>;\n}\n\n/** Copy a settings object at `key`, or start a fresh one when it is absent. */\nfunction cloneObjectField(source: Record<string, unknown>, key: string): Record<string, unknown> {\n // Spreading undefined is already a no-op, so no empty-object fallback is needed.\n return { ...readObjectField(source, key) };\n}\n\n/**\n * Parse the model-scope block.\n *\n * Lives here rather than beside the scope enforcement logic because parsing is\n * a settings concern and the agents domain may not reach into the runs domain.\n */\nfunction parseModelScopeConfig(value: unknown, filePath: string): ModelScopeConfig | undefined {\n if (value === undefined) return undefined;\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`Subagent settings in '${filePath}' have invalid 'modelScope'; expected an object.`);\n }\n\n const input = value as Record<string, unknown>;\n const config: ModelScopeConfig = {};\n\n if ('enforce' in input) {\n if (typeof input.enforce !== 'boolean') {\n throw new Error(`Subagent settings in '${filePath}' have invalid 'modelScope.enforce'; expected a boolean.`);\n }\n config.enforce = input.enforce;\n }\n\n if ('allow' in input) {\n if (!Array.isArray(input.allow)) {\n throw new Error(\n `Subagent settings in '${filePath}' have invalid 'modelScope.allow'; expected an array of strings.`,\n );\n }\n const allow: string[] = [];\n for (const entry of input.allow) {\n if (typeof entry !== 'string') {\n throw new Error(\n `Subagent settings in '${filePath}' have invalid 'modelScope.allow'; expected an array of strings.`,\n );\n }\n const trimmed = entry.trim();\n if (trimmed) allow.push(trimmed);\n }\n if (allow.length === 0) {\n throw new Error(\n `Subagent settings in '${filePath}' have invalid 'modelScope.allow'; expected a non-empty array of patterns.`,\n );\n }\n config.allow = allow;\n }\n\n // Enforcing against an empty allow list would reject every model, so it is\n // rejected here rather than at the point it would start failing runs.\n if (config.enforce === true && (!config.allow || config.allow.length === 0)) {\n throw new Error(\n `Subagent settings in '${filePath}' set modelScope.enforce without a non-empty 'allow' list; supply allowed model patterns or disable enforcement.`,\n );\n }\n\n return Object.keys(config).length > 0 ? config : undefined;\n}\n\n/**\n * Parse a string-array override field, which may also be `false` to clear it.\n *\n * Empty entries are dropped rather than rejected: trailing commas in a hand\n * edited list are common and unambiguous.\n */\nexport function parseOverrideStringArrayOrFalse(\n value: unknown,\n meta: { filePath: string; name: string; field: string },\n): string[] | false | undefined {\n if (value === undefined) return undefined;\n if (value === false) return false;\n if (!Array.isArray(value)) {\n throw new Error(\n `Builtin override '${meta.name}' in '${meta.filePath}' has invalid '${meta.field}'; expected an array of strings or false.`,\n );\n }\n\n const items: string[] = [];\n for (const item of value) {\n if (typeof item !== 'string') {\n throw new Error(\n `Builtin override '${meta.name}' in '${meta.filePath}' has invalid '${meta.field}'; expected an array of strings or false.`,\n );\n }\n const trimmed = item.trim();\n if (trimmed) items.push(trimmed);\n }\n return items;\n}\n\n/**\n * Parse one entry of `subagents.agentOverrides`.\n *\n * Returns undefined for an entry that declared nothing, so an empty object in\n * the file does not register as an override and mark the agent as overridden.\n */\nexport function parseBuiltinOverrideEntry(\n name: string,\n value: unknown,\n filePath: string,\n): BuiltinAgentOverrideConfig | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`Builtin override '${name}' in '${filePath}' must be an object.`);\n }\n\n const input = value as Record<string, unknown>;\n const override: BuiltinAgentOverrideConfig = {};\n\n if ('model' in input) {\n if (typeof input.model === 'string' || input.model === false) override.model = input.model;\n else\n throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'model'; expected a string or false.`);\n }\n\n if ('thinking' in input) {\n if (typeof input.thinking === 'string' || input.thinking === false) override.thinking = input.thinking;\n else\n throw new Error(\n `Builtin override '${name}' in '${filePath}' has invalid 'thinking'; expected a string or false.`,\n );\n }\n\n if ('systemPromptMode' in input) {\n if (input.systemPromptMode === 'append' || input.systemPromptMode === 'replace') {\n override.systemPromptMode = input.systemPromptMode;\n } else {\n throw new Error(\n `Builtin override '${name}' in '${filePath}' has invalid 'systemPromptMode'; expected 'append' or 'replace'.`,\n );\n }\n }\n\n if ('inheritProjectContext' in input) {\n if (typeof input.inheritProjectContext === 'boolean') {\n override.inheritProjectContext = input.inheritProjectContext;\n } else {\n throw new Error(\n `Builtin override '${name}' in '${filePath}' has invalid 'inheritProjectContext'; expected a boolean.`,\n );\n }\n }\n\n if ('inheritSkills' in input) {\n if (typeof input.inheritSkills === 'boolean') {\n override.inheritSkills = input.inheritSkills;\n } else {\n throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'inheritSkills'; expected a boolean.`);\n }\n }\n\n if ('defaultContext' in input) {\n if (input.defaultContext === 'fresh' || input.defaultContext === 'fork' || input.defaultContext === false) {\n override.defaultContext = input.defaultContext;\n } else {\n throw new Error(\n `Builtin override '${name}' in '${filePath}' has invalid 'defaultContext'; expected 'fresh', 'fork', or false.`,\n );\n }\n }\n\n if ('disabled' in input) {\n if (typeof input.disabled === 'boolean') {\n override.disabled = input.disabled;\n } else {\n throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'disabled'; expected a boolean.`);\n }\n }\n\n if ('completionGuard' in input) {\n if (typeof input.completionGuard === 'boolean') {\n override.completionGuard = input.completionGuard;\n } else {\n throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'completionGuard'; expected a boolean.`);\n }\n }\n\n if ('toolBudget' in input) {\n const toolBudget = parseToolBudgetOverride(input.toolBudget, name, filePath);\n if (toolBudget !== undefined) override.toolBudget = toolBudget;\n }\n\n if ('systemPrompt' in input) {\n if (typeof input.systemPrompt === 'string') override.systemPrompt = input.systemPrompt;\n else throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'systemPrompt'; expected a string.`);\n }\n\n const parseArrayField = (field: string): string[] | false | undefined =>\n parseOverrideStringArrayOrFalse(input[field], { filePath, name, field });\n\n const fallbackModels = parseArrayField('fallbackModels');\n if (fallbackModels !== undefined) override.fallbackModels = fallbackModels;\n const skills = parseArrayField('skills');\n if (skills !== undefined) override.skills = skills;\n const tools = parseArrayField('tools');\n if (tools !== undefined) override.tools = tools;\n const extensions = parseArrayField('extensions');\n if (extensions !== undefined) override.extensions = extensions;\n const subagentOnlyExtensions = parseArrayField('subagentOnlyExtensions');\n if (subagentOnlyExtensions !== undefined) override.subagentOnlyExtensions = subagentOnlyExtensions;\n\n return Object.keys(override).length > 0 ? override : undefined;\n}\n\n/**\n * Parse a `toolBudget` override.\n *\n * `hard` is required by the contract, so an object without a usable one is\n * rejected here instead of producing a budget that never blocks.\n */\nfunction parseToolBudgetOverride(value: unknown, name: string, filePath: string): ToolBudgetConfig | false | undefined {\n if (value === false) return false;\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(\n `Builtin override '${name}' in '${filePath}' has invalid 'toolBudget'; expected an object or false.`,\n );\n }\n\n const input = value as Record<string, unknown>;\n if (typeof input.hard !== 'number') {\n throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'toolBudget.hard'; expected a number.`);\n }\n\n const budget: ToolBudgetConfig = { hard: input.hard };\n if ('soft' in input) {\n if (typeof input.soft !== 'number') {\n throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'toolBudget.soft'; expected a number.`);\n }\n budget.soft = input.soft;\n }\n if ('block' in input) {\n if (input.block === '*') {\n budget.block = '*';\n } else if (Array.isArray(input.block) && input.block.every((entry) => typeof entry === 'string')) {\n budget.block = [...input.block];\n } else {\n throw new Error(\n `Builtin override '${name}' in '${filePath}' has invalid 'toolBudget.block'; expected an array of strings or '*'.`,\n );\n }\n }\n return budget;\n}\n\n/** Read and validate one settings file's `subagents` block. */\nexport function readSubagentSettings(filePath: string | null): SubagentSettings {\n if (!filePath) return EMPTY_SUBAGENT_SETTINGS;\n const settings = readSettingsFileStrict(filePath);\n const subagentsObject = readObjectField(settings, SUBAGENTS_SETTINGS_KEY);\n if (!subagentsObject) return EMPTY_SUBAGENT_SETTINGS;\n\n let disableBuiltins: boolean | undefined;\n if ('disableBuiltins' in subagentsObject) {\n if (typeof subagentsObject.disableBuiltins === 'boolean') {\n disableBuiltins = subagentsObject.disableBuiltins;\n } else {\n throw new Error(`Subagent settings in '${filePath}' have invalid 'disableBuiltins'; expected a boolean.`);\n }\n }\n\n let disableThinking: boolean | undefined;\n if ('disableThinking' in subagentsObject) {\n if (typeof subagentsObject.disableThinking === 'boolean') {\n disableThinking = subagentsObject.disableThinking;\n } else {\n throw new Error(`Subagent settings in '${filePath}' have invalid 'disableThinking'; expected a boolean.`);\n }\n }\n\n let defaultModel: string | undefined;\n if ('defaultModel' in subagentsObject) {\n if (typeof subagentsObject.defaultModel === 'string' && subagentsObject.defaultModel.trim()) {\n defaultModel = subagentsObject.defaultModel.trim();\n } else {\n throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultModel'; expected a non-empty string.`);\n }\n }\n\n let defaultThinking: string | undefined;\n if ('defaultThinking' in subagentsObject) {\n if (typeof subagentsObject.defaultThinking === 'string' && subagentsObject.defaultThinking.trim()) {\n defaultThinking = subagentsObject.defaultThinking.trim();\n } else {\n throw new Error(\n `Subagent settings in '${filePath}' have invalid 'defaultThinking'; expected a non-empty string.`,\n );\n }\n }\n\n let defaultExtensions: string[] | undefined;\n if ('defaultExtensions' in subagentsObject) {\n const raw = subagentsObject.defaultExtensions;\n if (!Array.isArray(raw) || raw.some((item) => typeof item !== 'string' || !item.trim())) {\n throw new Error(\n `Subagent settings in '${filePath}' have invalid 'defaultExtensions'; expected an array of non-empty strings.`,\n );\n }\n defaultExtensions = raw.map((item) => String(item).trim());\n }\n\n const modelScope = parseModelScopeConfig(subagentsObject.modelScope, filePath);\n\n const overrides: Record<string, BuiltinAgentOverrideConfig> = {};\n const agentOverrides = readObjectField(subagentsObject, AGENT_OVERRIDES_KEY);\n if (agentOverrides) {\n for (const [name, value] of Object.entries(agentOverrides)) {\n const override = parseBuiltinOverrideEntry(name, value, filePath);\n if (override) overrides[name] = override;\n }\n }\n\n return { overrides, defaultModel, defaultThinking, defaultExtensions, disableBuiltins, disableThinking, modelScope };\n}\n\n// ============================================================================\n// Settings-level defaults\n// ============================================================================\n\n/** Which settings file supplies `defaultModel`, project winning over user. */\nexport function resolveSubagentDefaultModel(\n userSettings: SubagentSettings,\n projectSettings: SubagentSettings,\n userSettingsPath: string,\n projectSettingsPath: string | null,\n): AgentModelSourceInfo | undefined {\n if (projectSettingsPath && projectSettings.defaultModel !== undefined) {\n return {\n type: 'subagents.defaultModel',\n scope: 'project',\n path: projectSettingsPath,\n model: projectSettings.defaultModel,\n };\n }\n return userSettings.defaultModel !== undefined\n ? { type: 'subagents.defaultModel', scope: 'user', path: userSettingsPath, model: userSettings.defaultModel }\n : undefined;\n}\n\n/**\n * Fill in the default model for agents that declared none.\n *\n * `modelSource` is recorded alongside so callers can tell an inherited model\n * from a requested one, which decides how hard model-scope enforcement bites.\n */\nexport function applySubagentDefaultModel(\n agents: AgentConfig[],\n defaultModel: AgentModelSourceInfo | undefined,\n): AgentConfig[] {\n if (!defaultModel) return agents;\n return agents.map((agent) => {\n if (agent.model !== undefined) return agent;\n return inheritFrontmatterFields(agent, { ...agent, model: defaultModel.model, modelSource: defaultModel });\n });\n}\n\n/** Fill in fallback models only when the agent declared no fallback policy. */\nexport function applySubagentDefaultFallbackModels(\n agents: AgentConfig[],\n fallbackModels: string[] | undefined,\n): AgentConfig[] {\n if (fallbackModels === undefined) return agents;\n return agents.map((agent) => {\n if (agent.fallbackModels !== undefined) return agent;\n return inheritFrontmatterFields(agent, { ...agent, fallbackModels: [...fallbackModels] });\n });\n}\n\nexport function resolveSubagentDefaultThinking(\n userSettings: SubagentSettings,\n projectSettings: SubagentSettings,\n projectSettingsPath: string | null,\n): string | undefined {\n if (projectSettingsPath && projectSettings.defaultThinking !== undefined) return projectSettings.defaultThinking;\n return userSettings.defaultThinking;\n}\n\nexport function applySubagentDefaultThinking(\n agents: AgentConfig[],\n defaultThinking: string | undefined,\n): AgentConfig[] {\n if (defaultThinking === undefined) return agents;\n return agents.map((agent) => {\n if (agent.thinking !== undefined) return agent;\n return inheritFrontmatterFields(agent, { ...agent, thinking: defaultThinking });\n });\n}\n\nexport function resolveSubagentDefaultExtensions(\n userSettings: SubagentSettings,\n projectSettings: SubagentSettings,\n projectSettingsPath: string | null,\n): string[] | undefined {\n if (projectSettingsPath && projectSettings.defaultExtensions !== undefined) return projectSettings.defaultExtensions;\n return userSettings.defaultExtensions;\n}\n\n/**\n * Fill in default extensions for agents that declared none.\n *\n * The `extensionsFromDefault` flag matters when the agent is later overridden:\n * a snapshot must not record a settings default as if the builtin had declared\n * it, or removing the override would bake the default in permanently.\n */\nexport function applySubagentDefaultExtensions(\n agents: AgentConfig[],\n defaultExtensions: string[] | undefined,\n): AgentConfig[] {\n if (defaultExtensions === undefined) return agents;\n return agents.map((agent) => {\n if (agent.extensions !== undefined) return agent;\n return inheritFrontmatterFields(agent, {\n ...agent,\n extensions: [...defaultExtensions],\n extensionsFromDefault: true,\n });\n });\n}\n\nexport function applySubagentDefaults(\n agents: AgentConfig[],\n defaultModel: AgentModelSourceInfo | undefined,\n defaultThinking: string | undefined,\n defaultExtensions: string[] | undefined,\n defaultFallbackModels?: string[],\n): AgentConfig[] {\n return applySubagentDefaultExtensions(\n applySubagentDefaultThinking(\n applySubagentDefaultFallbackModels(applySubagentDefaultModel(agents, defaultModel), defaultFallbackModels),\n defaultThinking,\n ),\n defaultExtensions,\n );\n}\n\n// ============================================================================\n// Override snapshots\n// ============================================================================\n\n/**\n * Snapshot the fields an override may replace, so it can be undone.\n *\n * `extensions` is omitted when it came from a settings default rather than the\n * agent itself; restoring it would turn a default into a permanent value.\n */\nexport function cloneOverrideBase(agent: AgentConfig): BuiltinOverrideSnapshot {\n return {\n model: agent.model,\n fallbackModels: agent.fallbackModels ? [...agent.fallbackModels] : undefined,\n thinking: agent.thinking,\n systemPromptMode: agent.systemPromptMode,\n inheritProjectContext: agent.inheritProjectContext,\n inheritSkills: agent.inheritSkills,\n defaultContext: agent.defaultContext,\n disabled: agent.disabled,\n systemPrompt: agent.systemPrompt,\n skills: agent.skills ? [...agent.skills] : undefined,\n skillPath: agent.skillPath ? [...agent.skillPath] : undefined,\n tools: agent.tools ? [...agent.tools] : undefined,\n mcpDirectTools: agent.mcpDirectTools ? [...agent.mcpDirectTools] : undefined,\n extensions: agent.extensionsFromDefault ? undefined : agent.extensions ? [...agent.extensions] : undefined,\n subagentOnlyExtensions: agent.subagentOnlyExtensions ? [...agent.subagentOnlyExtensions] : undefined,\n completionGuard: agent.completionGuard,\n toolBudget: agent.toolBudget,\n };\n}\n\n/**\n * Deep-copy an override before it is written to a settings file.\n *\n * Only keys the caller actually set are copied, because an explicit `undefined`\n * would serialise the key away and read back as \"not overridden\".\n */\nexport function cloneOverrideValue(override: BuiltinAgentOverrideConfig): BuiltinAgentOverrideConfig {\n return {\n ...(override.model !== undefined ? { model: override.model } : {}),\n ...(override.fallbackModels !== undefined\n ? { fallbackModels: override.fallbackModels === false ? false : [...override.fallbackModels] }\n : {}),\n ...(override.thinking !== undefined ? { thinking: override.thinking } : {}),\n ...(override.systemPromptMode !== undefined ? { systemPromptMode: override.systemPromptMode } : {}),\n ...(override.inheritProjectContext !== undefined ? { inheritProjectContext: override.inheritProjectContext } : {}),\n ...(override.inheritSkills !== undefined ? { inheritSkills: override.inheritSkills } : {}),\n ...(override.defaultContext !== undefined ? { defaultContext: override.defaultContext } : {}),\n ...(override.disabled !== undefined ? { disabled: override.disabled } : {}),\n ...(override.systemPrompt !== undefined ? { systemPrompt: override.systemPrompt } : {}),\n ...(override.skills !== undefined ? { skills: override.skills === false ? false : [...override.skills] } : {}),\n ...(override.tools !== undefined ? { tools: override.tools === false ? false : [...override.tools] } : {}),\n ...(override.extensions !== undefined\n ? { extensions: override.extensions === false ? false : [...override.extensions] }\n : {}),\n ...(override.subagentOnlyExtensions !== undefined\n ? {\n subagentOnlyExtensions:\n override.subagentOnlyExtensions === false ? false : [...override.subagentOnlyExtensions],\n }\n : {}),\n ...(override.completionGuard !== undefined ? { completionGuard: override.completionGuard } : {}),\n ...(override.toolBudget !== undefined\n ? {\n toolBudget:\n override.toolBudget === false\n ? false\n : {\n ...override.toolBudget,\n ...(Array.isArray(override.toolBudget.block) ? { block: [...override.toolBudget.block] } : {}),\n },\n }\n : {}),\n };\n}\n\n// ============================================================================\n// Applying overrides\n// ============================================================================\n\n/**\n * Replace a builtin's values with an override's.\n *\n * `false` clears a field rather than setting it to false; that distinction is\n * the whole reason the stored shape differs from the snapshot shape.\n */\nexport function applyBuiltinOverride(\n agent: AgentConfig,\n override: BuiltinAgentOverrideConfig,\n meta: OverrideScopeMeta,\n): AgentConfig {\n const next: AgentConfig = { ...agent, override: { ...meta, base: cloneOverrideBase(agent) } };\n\n if (override.model !== undefined) {\n next.model = override.model === false ? undefined : override.model;\n next.modelSource = undefined;\n }\n if (override.fallbackModels !== undefined) {\n next.fallbackModels = override.fallbackModels === false ? undefined : [...override.fallbackModels];\n }\n if (override.thinking !== undefined) next.thinking = override.thinking === false ? undefined : override.thinking;\n if (override.systemPromptMode !== undefined) next.systemPromptMode = override.systemPromptMode;\n if (override.inheritProjectContext !== undefined) next.inheritProjectContext = override.inheritProjectContext;\n if (override.inheritSkills !== undefined) next.inheritSkills = override.inheritSkills;\n if (override.defaultContext !== undefined) {\n next.defaultContext = override.defaultContext === false ? undefined : override.defaultContext;\n }\n if (override.disabled !== undefined) next.disabled = override.disabled;\n if (override.systemPrompt !== undefined) next.systemPrompt = override.systemPrompt;\n if (override.skills !== undefined) next.skills = override.skills === false ? undefined : [...override.skills];\n if (override.tools !== undefined) {\n const { tools, mcpDirectTools } = splitToolList(override.tools === false ? [] : override.tools);\n next.tools = tools;\n next.mcpDirectTools = mcpDirectTools;\n }\n if (override.extensions !== undefined) {\n next.extensions = override.extensions === false ? undefined : [...override.extensions];\n }\n if (override.subagentOnlyExtensions !== undefined) {\n next.subagentOnlyExtensions =\n override.subagentOnlyExtensions === false ? undefined : [...override.subagentOnlyExtensions];\n }\n if (override.completionGuard !== undefined) next.completionGuard = override.completionGuard;\n if (override.toolBudget !== undefined) {\n next.toolBudget = override.toolBudget === false ? undefined : override.toolBudget;\n }\n\n return next;\n}\n\n/**\n * Strip an agent's thinking level for the bulk `disableThinking` switch.\n *\n * An existing `override` is kept rather than replaced, so a per-agent override\n * remains the recorded reason the agent differs from its builtin definition.\n */\nexport function clearBuiltinThinking(agent: AgentConfig, meta: OverrideScopeMeta): AgentConfig {\n if (agent.thinking === undefined) return agent;\n return { ...agent, thinking: undefined, override: agent.override ?? { ...meta, base: cloneOverrideBase(agent) } };\n}\n\n/**\n * Apply user and project settings to the builtin agents.\n *\n * Precedence per agent: a project override, then the project bulk disable, then\n * a user override, then the user bulk disable. A project file that sets\n * `disableBuiltins` at all (including to false) shadows the user's switch, so a\n * project can re-enable builtins its user settings turned off.\n */\nexport function applyBuiltinOverrides(\n builtinAgents: AgentConfig[],\n userSettings: SubagentSettings,\n projectSettings: SubagentSettings,\n userSettingsPath: string,\n projectSettingsPath: string | null,\n): AgentConfig[] {\n const projectBulkDisabled = projectSettings.disableBuiltins === true && projectSettingsPath !== null;\n const userBulkDisabled = projectSettings.disableBuiltins === undefined && userSettings.disableBuiltins === true;\n const projectThinkingConfigured = projectSettings.disableThinking !== undefined && projectSettingsPath !== null;\n const disableThinking = projectThinkingConfigured\n ? projectSettings.disableThinking === true\n : userSettings.disableThinking === true;\n const disableThinkingMeta: OverrideScopeMeta =\n projectThinkingConfigured && projectSettingsPath\n ? { scope: 'project', path: projectSettingsPath }\n : { scope: 'user', path: userSettingsPath };\n\n // A per-agent thinking override is more specific than the bulk switch, so it\n // survives it; everything else is cleared.\n const applyGlobalThinking = (agent: AgentConfig, hasExplicitThinkingOverride: boolean): AgentConfig => {\n if (!disableThinking || hasExplicitThinkingOverride) return agent;\n return clearBuiltinThinking(agent, disableThinkingMeta);\n };\n\n return builtinAgents.map((agent) => {\n const projectOverride = projectSettings.overrides[agent.name];\n if (projectOverride && projectSettingsPath) {\n return applyGlobalThinking(\n applyBuiltinOverride(agent, projectOverride, { scope: 'project', path: projectSettingsPath }),\n projectOverride.thinking !== undefined,\n );\n }\n\n if (projectBulkDisabled && projectSettingsPath) {\n return applyGlobalThinking(\n applyBuiltinOverride(agent, { disabled: true }, { scope: 'project', path: projectSettingsPath }),\n false,\n );\n }\n\n const userOverride = userSettings.overrides[agent.name];\n if (userOverride) {\n return applyGlobalThinking(\n applyBuiltinOverride(agent, userOverride, { scope: 'user', path: userSettingsPath }),\n !projectThinkingConfigured && userOverride.thinking !== undefined,\n );\n }\n\n if (userBulkDisabled) {\n return applyGlobalThinking(\n applyBuiltinOverride(agent, { disabled: true }, { scope: 'user', path: userSettingsPath }),\n false,\n );\n }\n\n return applyGlobalThinking(agent, false);\n });\n}\n\n/**\n * Apply an override to a custom agent, filling only unset fields.\n *\n * A custom agent has a file the user could have edited, so a settings value\n * must never contradict its frontmatter. Nothing is copied and no `override`\n * is recorded unless at least one field was actually filled, which keeps agents\n * that declared everything from being reported as overridden.\n */\nexport function applyCustomAgentOverride(\n agent: AgentConfig,\n override: BuiltinAgentOverrideConfig,\n meta: OverrideScopeMeta,\n): AgentConfig {\n let next: AgentConfig | undefined;\n let anyFilled = false;\n\n const mutable = (): AgentConfig => {\n next ??= { ...agent };\n return next;\n };\n\n const fill = <K extends keyof AgentConfig>(field: K, frontmatterFields: string[], value: AgentConfig[K]): void => {\n if (agentHasFrontmatterField(agent, ...frontmatterFields)) return;\n mutable()[field] = value;\n anyFilled = true;\n };\n\n if (override.model !== undefined && !agentHasFrontmatterField(agent, 'model')) {\n const target = mutable();\n target.model = override.model === false ? undefined : override.model;\n target.modelSource = undefined;\n anyFilled = true;\n }\n if (override.fallbackModels !== undefined) {\n fill(\n 'fallbackModels',\n ['fallbackModels'],\n override.fallbackModels === false ? undefined : [...override.fallbackModels],\n );\n }\n if (override.thinking !== undefined) {\n fill('thinking', ['thinking'], override.thinking === false ? undefined : override.thinking);\n }\n if (override.systemPromptMode !== undefined) {\n fill('systemPromptMode', ['systemPromptMode'], override.systemPromptMode);\n }\n if (override.inheritProjectContext !== undefined) {\n fill('inheritProjectContext', ['inheritProjectContext'], override.inheritProjectContext);\n }\n if (override.inheritSkills !== undefined) {\n fill('inheritSkills', ['inheritSkills'], override.inheritSkills);\n }\n if (override.defaultContext !== undefined) {\n fill('defaultContext', ['defaultContext'], override.defaultContext === false ? undefined : override.defaultContext);\n }\n if (override.disabled !== undefined && agent.disabled === undefined) {\n mutable().disabled = override.disabled;\n anyFilled = true;\n }\n if (override.skills !== undefined) {\n fill('skills', ['skill', 'skills'], override.skills === false ? undefined : [...override.skills]);\n }\n if (override.tools !== undefined && !agentHasFrontmatterField(agent, 'tools')) {\n const { tools, mcpDirectTools } = splitToolList(override.tools === false ? [] : override.tools);\n const target = mutable();\n target.tools = tools;\n target.mcpDirectTools = mcpDirectTools;\n anyFilled = true;\n }\n if (override.extensions !== undefined) {\n fill('extensions', ['extensions'], override.extensions === false ? undefined : [...override.extensions]);\n }\n if (override.subagentOnlyExtensions !== undefined) {\n fill(\n 'subagentOnlyExtensions',\n ['subagentOnlyExtensions'],\n override.subagentOnlyExtensions === false ? undefined : [...override.subagentOnlyExtensions],\n );\n }\n if (override.completionGuard !== undefined) {\n fill('completionGuard', ['completionGuard'], override.completionGuard);\n }\n if (override.toolBudget !== undefined) {\n fill('toolBudget', ['toolBudget'], override.toolBudget === false ? undefined : override.toolBudget);\n }\n\n if (!anyFilled || !next) return agent;\n next.override = { ...meta, base: cloneOverrideBase(agent) };\n return inheritFrontmatterFields(agent, next);\n}\n\nexport function applyCustomAgentOverrides(\n agents: AgentConfig[],\n userSettings: SubagentSettings,\n projectSettings: SubagentSettings,\n userSettingsPath: string,\n projectSettingsPath: string | null,\n): AgentConfig[] {\n return agents.map((agent) => {\n const projectOverride = projectSettings.overrides[agent.name];\n if (projectOverride && projectSettingsPath) {\n return applyCustomAgentOverride(agent, projectOverride, { scope: 'project', path: projectSettingsPath });\n }\n\n const userOverride = userSettings.overrides[agent.name];\n if (userOverride) {\n return applyCustomAgentOverride(agent, userOverride, { scope: 'user', path: userSettingsPath });\n }\n\n return agent;\n });\n}\n\n/**\n * Diff an edited agent against its pre-override snapshot.\n *\n * Only changed fields are written, so a settings file records the user's edits\n * rather than a full copy of the builtin that would drift as the builtin does.\n * Returns undefined when nothing changed, which callers treat as \"remove the\n * override\" rather than \"write an empty one\".\n */\nexport function buildBuiltinOverrideConfig(\n base: BuiltinOverrideSnapshot,\n draft: Pick<\n AgentConfig,\n | 'model'\n | 'fallbackModels'\n | 'thinking'\n | 'systemPromptMode'\n | 'inheritProjectContext'\n | 'inheritSkills'\n | 'defaultContext'\n | 'disabled'\n | 'systemPrompt'\n | 'skills'\n | 'tools'\n | 'mcpDirectTools'\n | 'extensions'\n | 'subagentOnlyExtensions'\n | 'completionGuard'\n | 'toolBudget'\n >,\n): BuiltinAgentOverrideConfig | undefined {\n const override: BuiltinAgentOverrideConfig = {};\n\n if (draft.model !== base.model) override.model = draft.model ?? false;\n if (!arraysEqual(draft.fallbackModels, base.fallbackModels)) {\n override.fallbackModels = draft.fallbackModels ? [...draft.fallbackModels] : false;\n }\n if (draft.thinking !== base.thinking) override.thinking = draft.thinking ?? false;\n if (draft.systemPromptMode !== base.systemPromptMode) override.systemPromptMode = draft.systemPromptMode;\n if (draft.inheritProjectContext !== base.inheritProjectContext) {\n override.inheritProjectContext = draft.inheritProjectContext;\n }\n if (draft.inheritSkills !== base.inheritSkills) override.inheritSkills = draft.inheritSkills;\n if (draft.defaultContext !== base.defaultContext) override.defaultContext = draft.defaultContext ?? false;\n if (draft.disabled !== base.disabled) override.disabled = draft.disabled ?? false;\n if (draft.systemPrompt !== base.systemPrompt) override.systemPrompt = draft.systemPrompt;\n if (!arraysEqual(draft.skills, base.skills)) override.skills = draft.skills ? [...draft.skills] : false;\n\n const baseTools = joinToolList(base);\n const draftTools = joinToolList(draft);\n if (!arraysEqual(draftTools, baseTools)) override.tools = draftTools ? [...draftTools] : false;\n if (!arraysEqual(draft.extensions, base.extensions)) {\n override.extensions = draft.extensions ? [...draft.extensions] : false;\n }\n if (!arraysEqual(draft.subagentOnlyExtensions, base.subagentOnlyExtensions)) {\n override.subagentOnlyExtensions = draft.subagentOnlyExtensions ? [...draft.subagentOnlyExtensions] : false;\n }\n // Compared as booleans because an unset guard and an enabled one behave the\n // same, so only a switch to or from explicitly disabled is a real change.\n if ((draft.completionGuard !== false) !== (base.completionGuard !== false)) {\n override.completionGuard = draft.completionGuard !== false;\n }\n if (JSON.stringify(draft.toolBudget) !== JSON.stringify(base.toolBudget)) {\n override.toolBudget = draft.toolBudget ?? false;\n }\n\n return Object.keys(override).length > 0 ? override : undefined;\n}\n\n// ============================================================================\n// Persisting overrides\n// ============================================================================\n\nconst NO_PROJECT_ROOT_MESSAGE = 'Project override is not available here. No project config root was found.';\n\n/** Resolve the settings file for a scope, or throw when there is no project. */\nfunction requireSettingsPath(cwd: string, scope: 'user' | 'project'): string {\n const filePath = scope === 'project' ? getProjectAgentSettingsPath(cwd) : getUserAgentSettingsPath();\n if (!filePath) throw new Error(NO_PROJECT_ROOT_MESSAGE);\n return filePath;\n}\n\n/** Write an override, replacing any existing entry for the agent wholesale. */\nexport function saveBuiltinAgentOverride(\n cwd: string,\n name: string,\n scope: 'user' | 'project',\n override: BuiltinAgentOverrideConfig,\n): string {\n const filePath = requireSettingsPath(cwd, scope);\n\n const settings = readSettingsFileStrict(filePath);\n const subagents = cloneObjectField(settings, SUBAGENTS_SETTINGS_KEY);\n const agentOverrides = cloneObjectField(subagents, AGENT_OVERRIDES_KEY);\n\n agentOverrides[name] = cloneOverrideValue(override);\n subagents[AGENT_OVERRIDES_KEY] = agentOverrides;\n settings[SUBAGENTS_SETTINGS_KEY] = subagents;\n writeSettingsFile(filePath, settings);\n return filePath;\n}\n\n/**\n * Drop an agent's whole override entry.\n *\n * Emptied containers are deleted rather than left behind, so removing the last\n * override leaves the settings file as it was before any were added.\n */\nexport function removeBuiltinAgentOverride(\n cwd: string,\n name: string,\n scope: 'user' | 'project',\n): { path: string; removed: boolean } {\n const filePath = requireSettingsPath(cwd, scope);\n if (!fs.existsSync(filePath)) return { path: filePath, removed: false };\n\n const settings = readSettingsFileStrict(filePath);\n const subagents = readObjectField(settings, SUBAGENTS_SETTINGS_KEY);\n if (!subagents) return { path: filePath, removed: false };\n const agentOverrides = readObjectField(subagents, AGENT_OVERRIDES_KEY);\n if (!agentOverrides) return { path: filePath, removed: false };\n if (!Object.hasOwn(agentOverrides, name)) return { path: filePath, removed: false };\n\n const nextSubagents = { ...subagents };\n const nextOverrides = { ...agentOverrides };\n delete nextOverrides[name];\n if (Object.keys(nextOverrides).length > 0) nextSubagents[AGENT_OVERRIDES_KEY] = nextOverrides;\n else delete nextSubagents[AGENT_OVERRIDES_KEY];\n\n if (Object.keys(nextSubagents).length > 0) settings[SUBAGENTS_SETTINGS_KEY] = nextSubagents;\n else delete settings[SUBAGENTS_SETTINGS_KEY];\n\n writeSettingsFile(filePath, settings);\n return { path: filePath, removed: true };\n}\n\n/** Merge fields into an agent's existing override, leaving the rest in place. */\nexport function mergeBuiltinAgentOverride(\n cwd: string,\n name: string,\n scope: 'user' | 'project',\n fields: BuiltinAgentOverrideConfig,\n): string {\n const filePath = requireSettingsPath(cwd, scope);\n\n const settings = readSettingsFileStrict(filePath);\n const subagents = cloneObjectField(settings, SUBAGENTS_SETTINGS_KEY);\n const agentOverrides = cloneObjectField(subagents, AGENT_OVERRIDES_KEY);\n\n const existing = readObjectField(agentOverrides, name) ?? {};\n agentOverrides[name] = { ...existing, ...cloneOverrideValue(fields) };\n subagents[AGENT_OVERRIDES_KEY] = agentOverrides;\n settings[SUBAGENTS_SETTINGS_KEY] = subagents;\n writeSettingsFile(filePath, settings);\n return filePath;\n}\n\n/** Remove named fields from an agent's override, dropping it once empty. */\nexport function removeBuiltinAgentOverrideFields(\n cwd: string,\n name: string,\n scope: 'user' | 'project',\n fields: string[],\n): { path: string; removed: boolean } {\n const filePath = requireSettingsPath(cwd, scope);\n if (!fs.existsSync(filePath)) return { path: filePath, removed: false };\n\n const settings = readSettingsFileStrict(filePath);\n const subagents = readObjectField(settings, SUBAGENTS_SETTINGS_KEY);\n if (!subagents) return { path: filePath, removed: false };\n const agentOverrides = readObjectField(subagents, AGENT_OVERRIDES_KEY);\n if (!agentOverrides) return { path: filePath, removed: false };\n const entry = readObjectField(agentOverrides, name);\n if (!entry) return { path: filePath, removed: false };\n\n const nextEntry: Record<string, unknown> = { ...entry };\n let removed = false;\n for (const field of fields) {\n if (Object.hasOwn(nextEntry, field)) {\n delete nextEntry[field];\n removed = true;\n }\n }\n if (!removed) return { path: filePath, removed: false };\n\n const nextSubagents = { ...subagents };\n const nextOverrides = { ...agentOverrides };\n if (Object.keys(nextEntry).length > 0) {\n nextOverrides[name] = nextEntry;\n nextSubagents[AGENT_OVERRIDES_KEY] = nextOverrides;\n } else {\n delete nextOverrides[name];\n if (Object.keys(nextOverrides).length > 0) nextSubagents[AGENT_OVERRIDES_KEY] = nextOverrides;\n else delete nextSubagents[AGENT_OVERRIDES_KEY];\n }\n if (Object.keys(nextSubagents).length > 0) settings[SUBAGENTS_SETTINGS_KEY] = nextSubagents;\n else delete settings[SUBAGENTS_SETTINGS_KEY];\n\n writeSettingsFile(filePath, settings);\n return { path: filePath, removed: true };\n}\n"],"mappings":"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"}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.cjs","names":["fs","path","getProjectConfigDir","os","LruCache","canonicalizeDiscoveryCwd","getAgentDir"],"sources":["../../../src/services/agents/skills.ts"],"sourcesContent":["/**\n * Resolving skill files by name and rendering them into a child system prompt.\n *\n * A skill is a markdown file, either `<dir>/SKILL.md` or a bare `<name>.md`,\n * found by sweeping a fixed list of search roots. The same name can appear in\n * several roots, so the sweep records where each hit came from and the highest\n * priority source wins.\n *\n * WHY THIS IS A SERVICE AND NOT A MODULE OF FUNCTIONS:\n * Resolution walks every skill root and reads the frontmatter of every markdown\n * file it finds. Prompt assembly asks for the catalogue on each launch and\n * completion asks on each keystroke, so the answers have to be cached, and a\n * cache needs an owner that can be invalidated and swapped in a test.\n *\n * DESIGN PATTERNS:\n * - Two caches with different lifetimes. Listing answers \"does this name exist\n * and where\", reading answers \"what does it say\"; the first goes stale on any\n * directory change, the second only when one file's mtime moves\n * - Both are bounded LRUs. The predecessor held the listing in a single mutable\n * slot keyed by cwd, which thrashed the moment two working directories were in\n * play, and evicted parsed files in insertion order regardless of use\n * - Every filesystem call is best-effort. A skill root that cannot be read is\n * skipped, never fatal: a missing skill surfaces to the caller as `missing`\n * - Symlinked and repeated directories are visited at most once per priority, so\n * a cycle in the skill tree terminates\n *\n * AVOID:\n * - Walking the skill roots on a completion path without going through the cache\n * - Deriving a config directory here instead of asking `configDir.ts`\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { injectable } from 'inversify';\n\nimport { EXTRA_SKILL_DIRS_ENV } from '../../adapters/process/env.ts';\nimport { getAgentDir, getProjectConfigDir } from '../../shared/configDir.ts';\nimport { LruCache } from '../../shared/lruCache.ts';\nimport { canonicalizeDiscoveryCwd } from './projectRoot.ts';\n\n/**\n * Where a skill file was found.\n *\n * Deliberately not `AgentSource`: a skill can also come from a settings list or\n * from an extension directory, neither of which can hold an agent definition.\n */\nexport type SkillSource =\n | 'project'\n | 'user'\n | 'project-settings'\n | 'user-settings'\n | 'extension'\n | 'builtin'\n | 'unknown';\n\nexport interface ResolvedSkill {\n name: string;\n path: string;\n content: string;\n description?: string;\n source: SkillSource;\n}\n\nexport interface SkillLocation {\n path: string;\n source: SkillSource;\n}\n\nexport interface SkillResolution {\n resolved: ResolvedSkill[];\n missing: string[];\n}\n\nexport interface DiscoveredSkill {\n name: string;\n source: SkillSource;\n description?: string;\n}\n\n/**\n * Discovery and reading of skill files.\n *\n * Behind an interface for the same reason agent discovery is: the results are\n * cached and invalidated, and callers on the completion path must be able to ask\n * repeatedly without paying for a directory walk each time.\n */\nexport interface ISkillDiscoveryService {\n /** Locate one skill by name, or undefined when no root holds it. */\n resolveSkillPath(skillName: string, cwd: string): SkillLocation | undefined;\n /** Read the named skills, reporting any that could not be resolved. */\n resolveSkills(skillNames: string[], cwd: string, localSkillPaths?: string[], localBaseDir?: string): SkillResolution;\n /** Resolve against `primaryCwd`, retrying whatever is missing in `fallbackCwd`. */\n resolveSkillsWithFallback(\n skillNames: string[],\n primaryCwd: string,\n fallbackCwd?: string,\n localSkillPaths?: string[],\n localBaseDir?: string,\n ): SkillResolution;\n /** Every skill visible from `cwd`, sorted by name. */\n discoverAvailableSkills(cwd: string): DiscoveredSkill[];\n /** Drop cached results. Call after writing or removing a skill file. */\n invalidate(): void;\n}\n\n/** One entry in a listing sweep: located, but not yet read. */\ninterface CachedSkillEntry {\n name: string;\n filePath: string;\n source: SkillSource;\n description?: string;\n /** Discovery order, used to break ties between equal-priority sources. */\n order: number;\n}\n\ninterface SkillFileCacheEntry {\n mtimeMs: number;\n skill: ResolvedSkill;\n}\n\ninterface SkillListingCacheEntry {\n skills: CachedSkillEntry[];\n expiresAt: number;\n}\n\ninterface SkillSearchPath {\n path: string;\n source: SkillSource;\n}\n\n/** Roughly the number of distinct skills one session touches. */\nconst SKILL_FILE_CACHE_CAPACITY = 50;\n/** One entry per (cwd, agentDir) pair; a session rarely spans more than a few. */\nconst SKILL_LISTING_CACHE_CAPACITY = 8;\n/**\n * How long a listing stays valid.\n *\n * Short enough that a skill added mid-session appears without a restart, long\n * enough that a burst of completions does not re-walk the roots per keystroke.\n */\nconst SKILL_LISTING_TTL_MS = 5_000;\n\n/** Cache keys join two paths, so use a separator that cannot occur in either. */\nconst CACHE_KEY_SEPARATOR = '\\0';\n\n/**\n * The orchestration skill, excluded from every listing and injection.\n *\n * A subagent already has the orchestration tools wired in, so handing it the\n * skill that explains how to reach for them wastes context and invites a child\n * to fan out again. The name is the published skill's, not this package's.\n */\nconst SUBAGENT_ORCHESTRATION_SKILL = 'pi-subagents';\n\nconst SKILL_FILE_NAME = 'SKILL.md';\nconst MARKDOWN_EXTENSION = '.md';\nconst FRONTMATTER_FENCE = '---';\nconst NODE_MODULES_DIR = 'node_modules';\nconst HOME_ALIAS_PREFIX = '~/';\n\n/** Sources a listing can report, most authoritative first. */\nconst SOURCE_PRIORITY: Record<SkillSource, number> = {\n project: 700,\n 'project-settings': 650,\n user: 300,\n 'user-settings': 250,\n extension: 150,\n builtin: 100,\n unknown: 0,\n};\n\nfunction priorityOf(source: SkillSource): number {\n return SOURCE_PRIORITY[source] ?? SOURCE_PRIORITY.unknown;\n}\n\n/** Index of the first character after a closing frontmatter fence, or -1. */\nfunction findFrontmatterEnd(normalized: string): number {\n if (!normalized.startsWith(FRONTMATTER_FENCE)) return -1;\n return normalized.indexOf(`\\n${FRONTMATTER_FENCE}`, FRONTMATTER_FENCE.length);\n}\n\nexport function stripSkillFrontmatter(content: string): string {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n const endIndex = findFrontmatterEnd(normalized);\n if (endIndex === -1) return normalized;\n return normalized.slice(endIndex + 1 + FRONTMATTER_FENCE.length).trim();\n}\n\nexport function parseSkillDescription(content: string): string | undefined {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n const endIndex = findFrontmatterEnd(normalized);\n if (endIndex === -1) return undefined;\n\n const frontmatter = normalized.slice(FRONTMATTER_FENCE.length, endIndex).trim();\n const match = frontmatter.match(/^description:\\s*(.+)$/m);\n return match?.[1]?.trim().replace(/^['\"]|['\"]$/g, '');\n}\n\nfunction maybeReadSkillDescription(filePath: string): string | undefined {\n try {\n return parseSkillDescription(fs.readFileSync(filePath, 'utf-8'));\n } catch {\n // The description is optional metadata; an unreadable file still lists by name.\n return undefined;\n }\n}\n\nfunction isWithinPath(filePath: string, dir: string): boolean {\n const relative = path.relative(dir, filePath);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\n/** Read a JSON file that is allowed to be absent, but not allowed to be corrupt. */\nfunction readOptionalJsonFile(filePath: string, label: string): unknown {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n return parsed;\n } catch (error) {\n const code =\n typeof error === 'object' && error !== null && 'code' in error ? (error as { code?: unknown }).code : undefined;\n if (code === 'ENOENT') return null;\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read ${label} '${filePath}': ${message}`, {\n cause: error instanceof Error ? error : undefined,\n });\n }\n}\n\n/** Extract the string entries of a settings file's `skills` array. */\nfunction readSettingsSkillList(settings: unknown): string[] {\n if (typeof settings !== 'object' || settings === null || Array.isArray(settings)) return [];\n const skills = (settings as { skills?: unknown }).skills;\n if (!Array.isArray(skills)) return [];\n return skills.filter((entry): entry is string => typeof entry === 'string');\n}\n\nfunction collectSettingsSkillPaths(cwd: string, agentDir: string): SkillSearchPath[] {\n const results: SkillSearchPath[] = [];\n const projectConfigDir = getProjectConfigDir(cwd);\n const settingsFiles = [\n { file: path.join(projectConfigDir, 'settings.json'), base: projectConfigDir, source: 'project-settings' as const },\n { file: path.join(agentDir, 'settings.json'), base: agentDir, source: 'user-settings' as const },\n ];\n\n for (const { file, base, source } of settingsFiles) {\n for (const entry of readSettingsSkillList(readOptionalJsonFile(file, 'skills settings file'))) {\n let resolved = entry;\n if (resolved.startsWith(HOME_ALIAS_PREFIX)) {\n resolved = path.join(os.homedir(), resolved.slice(HOME_ALIAS_PREFIX.length));\n } else if (!path.isAbsolute(resolved)) {\n resolved = path.resolve(base, resolved);\n }\n results.push({ path: resolved, source });\n }\n }\n\n return results;\n}\n\nfunction extraSkillPaths(): SkillSearchPath[] {\n return (process.env[EXTRA_SKILL_DIRS_ENV] ?? '')\n .split(path.delimiter)\n .map((directory) => directory.trim())\n .filter(Boolean)\n .map((directory) => ({ path: directory, source: 'extension' as const }));\n}\n\nfunction buildSkillPaths(cwd: string, agentDir: string): SkillSearchPath[] {\n const projectConfigDir = getProjectConfigDir(cwd);\n return [\n ...extraSkillPaths(),\n { path: path.join(projectConfigDir, 'skills'), source: 'project' },\n { path: path.join(cwd, '.agents', 'skills'), source: 'project' },\n { path: path.join(agentDir, 'skills'), source: 'user' },\n { path: path.join(os.homedir(), '.agents', 'skills'), source: 'user' },\n ...collectSettingsSkillPaths(cwd, agentDir),\n ];\n}\n\n/** Classify a hit that arrived without a source hint, by which root contains it. */\nfunction inferSkillSource(filePath: string, cwd: string, agentDir: string, sourceHint?: SkillSource): SkillSource {\n if (sourceHint) return sourceHint;\n\n const projectConfigRoot = path.resolve(getProjectConfigDir(cwd));\n const projectSkillsRoot = path.resolve(projectConfigRoot, 'skills');\n const projectAgentsRoot = path.resolve(cwd, '.agents');\n const userSkillsRoot = path.resolve(agentDir, 'skills');\n const userAgentRoot = path.resolve(agentDir);\n const userAgentsRoot = path.resolve(os.homedir(), '.agents');\n\n if (isWithinPath(filePath, projectSkillsRoot) || isWithinPath(filePath, projectAgentsRoot)) return 'project';\n if (isWithinPath(filePath, projectConfigRoot)) return 'project-settings';\n\n if (isWithinPath(filePath, userSkillsRoot) || isWithinPath(filePath, userAgentsRoot)) return 'user';\n if (isWithinPath(filePath, userAgentRoot)) return 'user-settings';\n\n return 'unknown';\n}\n\nfunction chooseHigherPrioritySkill(\n existing: CachedSkillEntry | undefined,\n candidate: CachedSkillEntry,\n): CachedSkillEntry {\n if (!existing) return candidate;\n const existingPriority = priorityOf(existing.source);\n const candidatePriority = priorityOf(candidate.source);\n if (candidatePriority > existingPriority) return candidate;\n if (candidatePriority < existingPriority) return existing;\n return candidate.order < existing.order ? candidate : existing;\n}\n\nfunction isMarkdownFile(fileName: string): boolean {\n return fileName.toLowerCase().endsWith(MARKDOWN_EXTENSION);\n}\n\n/** Directory names never worth descending into while hunting for skills. */\nfunction shouldSkipDirectory(name: string): boolean {\n return name.startsWith('.') || name === NODE_MODULES_DIR;\n}\n\nfunction statOrUndefined(target: string): fs.Stats | undefined {\n try {\n return fs.statSync(target);\n } catch {\n // A dangling symlink or a path removed mid-sweep is simply not a skill.\n return undefined;\n }\n}\n\nfunction readDirOrEmpty(dirPath: string): fs.Dirent[] {\n try {\n return fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n // An unreadable root must not abort the sweep over the remaining roots.\n return [];\n }\n}\n\n/**\n * Sweep the given roots for skill files.\n *\n * Pure with respect to the caches, which is what lets it serve both the cached\n * catalogue and an agent's own uncached `skillPath` list.\n */\nfunction collectFilesystemSkills(cwd: string, agentDir: string, skillPaths: SkillSearchPath[]): CachedSkillEntry[] {\n const entries: CachedSkillEntry[] = [];\n const seen = new Map<string, number>();\n const visitedDirectories = new Map<string, number>();\n let order = 0;\n\n const pushEntry = (name: string, filePath: string, sourceHint?: SkillSource) => {\n const resolvedFile = path.resolve(filePath);\n if (!fs.existsSync(resolvedFile)) return;\n const source = inferSkillSource(resolvedFile, cwd, agentDir, sourceHint);\n const existingIndex = seen.get(resolvedFile);\n if (existingIndex !== undefined) {\n const existing = entries[existingIndex];\n if (existing && priorityOf(source) > priorityOf(existing.source)) {\n entries[existingIndex] = {\n ...existing,\n name,\n source,\n description: maybeReadSkillDescription(resolvedFile),\n };\n }\n return;\n }\n seen.set(resolvedFile, entries.length);\n entries.push({\n name,\n filePath: resolvedFile,\n source,\n description: maybeReadSkillDescription(resolvedFile),\n order: order++,\n });\n };\n\n /** False when this directory was already walked at an equal or better priority. */\n const markDirectoryVisited = (dirPath: string, sourceHint?: SkillSource): boolean => {\n let resolvedDir: string;\n try {\n resolvedDir = fs.realpathSync(dirPath);\n } catch {\n // Symlink resolution is only needed to detect cycles; the lexical path is\n // a sound fallback that at worst walks one directory twice.\n resolvedDir = path.resolve(dirPath);\n }\n const priority = sourceHint ? priorityOf(sourceHint) : SOURCE_PRIORITY.unknown;\n const previousPriority = visitedDirectories.get(resolvedDir);\n if (previousPriority !== undefined && previousPriority >= priority) return false;\n visitedDirectories.set(resolvedDir, priority);\n return true;\n };\n\n const walkSkillDirectories = (dirPath: string, sourceHint?: SkillSource) => {\n if (!markDirectoryVisited(dirPath, sourceHint)) return;\n\n // A directory holding SKILL.md is itself the skill; do not descend further.\n const skillFile = path.join(dirPath, SKILL_FILE_NAME);\n if (fs.existsSync(skillFile)) {\n pushEntry(path.basename(dirPath), skillFile, sourceHint);\n return;\n }\n\n for (const entry of readDirOrEmpty(dirPath)) {\n if (shouldSkipDirectory(entry.name)) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n const entryPath = path.join(dirPath, entry.name);\n if (statOrUndefined(entryPath)?.isDirectory()) walkSkillDirectories(entryPath, sourceHint);\n }\n };\n\n for (const skillPath of skillPaths) {\n if (!fs.existsSync(skillPath.path)) continue;\n\n const stat = statOrUndefined(skillPath.path);\n if (!stat) continue;\n\n // A root may point straight at a markdown file rather than a directory.\n if (stat.isFile()) {\n const fileName = path.basename(skillPath.path);\n if (!isMarkdownFile(fileName)) continue;\n const skillName =\n fileName.toLowerCase() === SKILL_FILE_NAME.toLowerCase()\n ? path.basename(path.dirname(skillPath.path))\n : path.basename(fileName, path.extname(fileName));\n pushEntry(skillName, skillPath.path, skillPath.source);\n continue;\n }\n\n if (!stat.isDirectory()) continue;\n\n const rootSkillFile = path.join(skillPath.path, SKILL_FILE_NAME);\n if (fs.existsSync(rootSkillFile)) {\n pushEntry(path.basename(skillPath.path), rootSkillFile, skillPath.source);\n continue;\n }\n\n markDirectoryVisited(skillPath.path, skillPath.source);\n\n for (const child of readDirOrEmpty(skillPath.path)) {\n if (child.name.startsWith('.')) continue;\n const childPath = path.join(skillPath.path, child.name);\n if (child.isDirectory() || child.isSymbolicLink()) {\n if (shouldSkipDirectory(child.name)) continue;\n if (statOrUndefined(childPath)?.isDirectory()) walkSkillDirectories(childPath, skillPath.source);\n continue;\n }\n if (child.isFile() && isMarkdownFile(child.name)) {\n pushEntry(path.basename(child.name, path.extname(child.name)), childPath, skillPath.source);\n }\n }\n }\n\n return entries;\n}\n\n@injectable()\nexport class SkillDiscoveryService implements ISkillDiscoveryService {\n /** Parsed skill bodies, keyed by resolved file path and validated by mtime. */\n private readonly fileCache = new LruCache<string, SkillFileCacheEntry>(SKILL_FILE_CACHE_CAPACITY);\n /** Located-but-unread catalogues, keyed by the (cwd, agentDir) pair. */\n private readonly listingCache = new LruCache<string, SkillListingCacheEntry>(SKILL_LISTING_CACHE_CAPACITY);\n\n /**\n * Seams for tests, as protected members rather than constructor arguments.\n *\n * The container resolves this service by type, and inversify cannot supply a\n * primitive like a TTL, so configuration cannot arrive through the\n * constructor. The repo convention is also not to abstract the clock, so a\n * test subclass overrides these instead.\n */\n protected readonly listingTtlMs: number = SKILL_LISTING_TTL_MS;\n\n protected now(): number {\n return Date.now();\n }\n\n resolveSkillPath(skillName: string, cwd: string): SkillLocation | undefined {\n const skill = this.listSkills(cwd).find((candidate) => candidate.name === skillName);\n if (!skill) return undefined;\n return { path: skill.filePath, source: skill.source };\n }\n\n resolveSkills(skillNames: string[], cwd: string, localSkillPaths?: string[], localBaseDir?: string): SkillResolution {\n const resolved: ResolvedSkill[] = [];\n const missing: string[] = [];\n const localByName = localSkillPaths?.length\n ? collectLocalSkills(cwd, localSkillPaths, localBaseDir)\n : new Map<string, CachedSkillEntry>();\n\n for (const name of skillNames) {\n const trimmed = name.trim();\n if (!trimmed) continue;\n if (trimmed === SUBAGENT_ORCHESTRATION_SKILL) {\n missing.push(trimmed);\n continue;\n }\n\n // An agent's own skillPath outranks anything found in the shared roots.\n const local = localByName.get(trimmed);\n let skill = local ? this.readSkill(trimmed, local.filePath, local.source) : undefined;\n if (!skill) {\n const location = this.resolveSkillPath(trimmed, cwd);\n if (location) skill = this.readSkill(trimmed, location.path, location.source);\n }\n if (skill) resolved.push(skill);\n else missing.push(trimmed);\n }\n\n return { resolved, missing };\n }\n\n /**\n * Resolve against `primaryCwd`, then retry whatever is still missing elsewhere.\n *\n * A child launched into a worktree still needs the skills configured in the\n * repository it was launched from.\n */\n resolveSkillsWithFallback(\n skillNames: string[],\n primaryCwd: string,\n fallbackCwd?: string,\n localSkillPaths?: string[],\n localBaseDir?: string,\n ): SkillResolution {\n const resolvedPrimaryCwd = path.resolve(primaryCwd);\n const primary = this.resolveSkills(skillNames, resolvedPrimaryCwd, localSkillPaths, localBaseDir);\n if (!fallbackCwd || primary.missing.length === 0) return primary;\n const resolvedFallbackCwd = path.resolve(fallbackCwd);\n if (canonicalizeDiscoveryCwd(resolvedPrimaryCwd) === canonicalizeDiscoveryCwd(resolvedFallbackCwd)) return primary;\n\n const fallback = this.resolveSkills(primary.missing, resolvedFallbackCwd);\n return {\n resolved: [...primary.resolved, ...fallback.resolved],\n missing: fallback.missing,\n };\n }\n\n discoverAvailableSkills(cwd: string): DiscoveredSkill[] {\n return this.listSkills(cwd)\n .filter((skill) => skill.name !== SUBAGENT_ORCHESTRATION_SKILL)\n .map((skill) => ({\n name: skill.name,\n source: skill.source,\n description: skill.description,\n }))\n .sort((a, b) => a.name.localeCompare(b.name));\n }\n\n invalidate(): void {\n this.fileCache.clear();\n this.listingCache.clear();\n }\n\n /** The catalogue visible from `cwd`, sweeping the roots only when stale. */\n private listSkills(cwd: string): CachedSkillEntry[] {\n const timestamp = this.now();\n const resolvedCwd = path.resolve(cwd);\n const resolvedAgentDir = path.resolve(getAgentDir());\n const key = `${canonicalizeDiscoveryCwd(resolvedCwd)}${CACHE_KEY_SEPARATOR}${canonicalizeDiscoveryCwd(resolvedAgentDir)}`;\n\n const cached = this.listingCache.get(key);\n if (cached && cached.expiresAt > timestamp) return cached.skills;\n\n const loaded = collectFilesystemSkills(\n resolvedCwd,\n resolvedAgentDir,\n buildSkillPaths(resolvedCwd, resolvedAgentDir),\n );\n const dedupedByName = new Map<string, CachedSkillEntry>();\n for (const entry of loaded) {\n dedupedByName.set(entry.name, chooseHigherPrioritySkill(dedupedByName.get(entry.name), entry));\n }\n\n const skills = [...dedupedByName.values()].sort((a, b) => a.order - b.order);\n this.listingCache.set(key, { skills, expiresAt: timestamp + this.listingTtlMs });\n return skills;\n }\n\n /** Read one skill file, reusing the cached parse while its mtime holds. */\n private readSkill(skillName: string, skillPath: string, source: SkillSource): ResolvedSkill | undefined {\n try {\n const stat = fs.statSync(skillPath);\n const cached = this.fileCache.get(skillPath);\n if (cached && cached.mtimeMs === stat.mtimeMs) return cached.skill;\n\n const raw = fs.readFileSync(skillPath, 'utf-8');\n const skill: ResolvedSkill = {\n name: skillName,\n path: skillPath,\n content: stripSkillFrontmatter(raw),\n description: parseSkillDescription(raw),\n source,\n };\n\n this.fileCache.set(skillPath, { mtimeMs: stat.mtimeMs, skill });\n return skill;\n } catch {\n // Treat an unreadable skill file as unresolved so the caller reports it\n // missing rather than injecting a half-formed block into a child prompt.\n return undefined;\n }\n }\n}\n\n/**\n * Index skill files supplied by an agent's own `skillPath`, keyed by name.\n *\n * Deliberately uncached: these paths are per-agent rather than per-directory, so\n * they would pollute a catalogue cache keyed on cwd.\n */\nfunction collectLocalSkills(\n cwd: string,\n localSkillPaths: string[],\n localBaseDir?: string,\n): Map<string, CachedSkillEntry> {\n const localByName = new Map<string, CachedSkillEntry>();\n const localEntries = collectFilesystemSkills(\n cwd,\n getAgentDir(),\n localSkillPaths.map((entry) => ({\n path: path.resolve(localBaseDir ?? cwd, entry),\n source: 'unknown' as const,\n })),\n );\n for (const entry of localEntries) {\n if (!localByName.has(entry.name)) localByName.set(entry.name, entry);\n }\n return localByName;\n}\n\nfunction escapeXmlText(value: string): string {\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\n/**\n * Render the skill catalogue for a child system prompt.\n *\n * Only names, descriptions and locations are injected. The child reads a skill\n * when its description matches the task, which keeps the prompt small no matter\n * how large the configured skill bodies are.\n */\nexport function buildSkillInjection(skills: ResolvedSkill[]): string {\n if (skills.length === 0) return '';\n\n const lines = [\n 'The following configured skills are available to this subagent.',\n \"Use the read tool to load a skill's file when the task matches its description.\",\n 'When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.',\n '',\n '<available_skills>',\n ];\n const stableSkills = [...skills].sort(\n (left, right) => left.name.localeCompare(right.name) || left.path.localeCompare(right.path),\n );\n for (const skill of stableSkills) {\n lines.push(' <skill>');\n lines.push(` <name>${escapeXmlText(skill.name)}</name>`);\n lines.push(` <description>${escapeXmlText(skill.description ?? '')}</description>`);\n lines.push(` <location>${escapeXmlText(skill.path)}</location>`);\n lines.push(' </skill>');\n }\n lines.push('</available_skills>');\n return lines.join('\\n');\n}\n\nfunction dedupeSkillNames(names: string[]): string[] {\n return [...new Set(names.map((entry) => entry.trim()).filter((entry) => entry.length > 0))];\n}\n\n/**\n * Normalise the `skills` tool parameter into a name list.\n *\n * `false` means \"no skills at all\" and `undefined` means \"use the agent's own\n * configuration\", which is why they are distinct return values rather than both\n * collapsing to an empty array.\n */\nexport function normalizeSkillInput(input: string | string[] | boolean | undefined): string[] | false | undefined {\n if (input === false) return false;\n if (input === true || input === undefined) return undefined;\n if (Array.isArray(input)) return dedupeSkillNames(input);\n\n // Models sometimes serialise the parameter as a JSON string instead of a native\n // array. Splitting '[\"a\",\"b\"]' on commas would embed brackets and quotes into\n // the names, and resolution would then fail with no obvious cause.\n const trimmed = input.trim();\n if (trimmed.startsWith('[')) {\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (Array.isArray(parsed)) {\n return dedupeSkillNames(parsed.filter((entry): entry is string => typeof entry === 'string'));\n }\n } catch {\n // Not valid JSON after all; fall through to the comma-separated reading.\n }\n }\n return dedupeSkillNames(input.split(','));\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{__esmMin as e}from"../../_virtual/_rolldown/runtime.mjs";import{__decorate as t,init_decorate as n}from"../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.mjs";import{LruCache as r,init_lruCache as i}from"../../shared/lruCache.mjs";import{getAgentDir as a,getProjectConfigDir as o,init_configDir as s}from"../../shared/configDir.mjs";import{canonicalizeDiscoveryCwd as c,init_projectRoot as l}from"./projectRoot.mjs";import{init_env as u}from"../../adapters/process/env.mjs";import*as d from"node:fs";import*as f from"node:path";import{injectable as p}from"inversify";import*as m from"node:os";function h(e){return K[e]??K.unknown}function g(e){return e.startsWith(U)?e.indexOf(`\n${U}`,3):-1}function _(e){let t=e.replace(/\r\n/g,`
|
|
2
|
+
`),n=g(t);return n===-1?t:t.slice(n+1+3).trim()}function v(e){let t=e.replace(/\r\n/g,`
|
|
3
|
+
`),n=g(t);if(n!==-1)return t.slice(3,n).trim().match(/^description:\s*(.+)$/m)?.[1]?.trim().replace(/^['"]|['"]$/g,``)}function y(e){try{return v(d.readFileSync(e,`utf-8`))}catch{return}}function b(e,t){let n=f.relative(t,e);return n===``||!n.startsWith(`..`)&&!f.isAbsolute(n)}function x(e,t){try{return JSON.parse(d.readFileSync(e,`utf-8`))}catch(n){if((typeof n==`object`&&n&&`code`in n?n.code:void 0)===`ENOENT`)return null;let r=n instanceof Error?n.message:String(n);throw Error(`Failed to read ${t} '${e}': ${r}`,{cause:n instanceof Error?n:void 0})}}function S(e){if(typeof e!=`object`||!e||Array.isArray(e))return[];let t=e.skills;return Array.isArray(t)?t.filter(e=>typeof e==`string`):[]}function C(e,t){let n=[],r=o(e),i=[{file:f.join(r,`settings.json`),base:r,source:`project-settings`},{file:f.join(t,`settings.json`),base:t,source:`user-settings`}];for(let{file:e,base:t,source:r}of i)for(let i of S(x(e,`skills settings file`))){let e=i;e.startsWith(G)?e=f.join(m.homedir(),e.slice(2)):f.isAbsolute(e)||(e=f.resolve(t,e)),n.push({path:e,source:r})}return n}function w(){return(process.env.PI_SUBAGENT_EXTRA_SKILL_DIRS??``).split(f.delimiter).map(e=>e.trim()).filter(Boolean).map(e=>({path:e,source:`extension`}))}function T(e,t){let n=o(e);return[...w(),{path:f.join(n,`skills`),source:`project`},{path:f.join(e,`.agents`,`skills`),source:`project`},{path:f.join(t,`skills`),source:`user`},{path:f.join(m.homedir(),`.agents`,`skills`),source:`user`},...C(e,t)]}function E(e,t,n,r){if(r)return r;let i=f.resolve(o(t)),a=f.resolve(i,`skills`),s=f.resolve(t,`.agents`),c=f.resolve(n,`skills`),l=f.resolve(n),u=f.resolve(m.homedir(),`.agents`);return b(e,a)||b(e,s)?`project`:b(e,i)?`project-settings`:b(e,c)||b(e,u)?`user`:b(e,l)?`user-settings`:`unknown`}function D(e,t){if(!e)return t;let n=h(e.source),r=h(t.source);return r>n?t:r<n?e:t.order<e.order?t:e}function O(e){return e.toLowerCase().endsWith(H)}function k(e){return e.startsWith(`.`)||e===W}function A(e){try{return d.statSync(e)}catch{return}}function j(e){try{return d.readdirSync(e,{withFileTypes:!0})}catch{return[]}}function M(e,t,n){let r=[],i=new Map,a=new Map,o=0,s=(n,a,s)=>{let c=f.resolve(a);if(!d.existsSync(c))return;let l=E(c,e,t,s),u=i.get(c);if(u!==void 0){let e=r[u];e&&h(l)>h(e.source)&&(r[u]={...e,name:n,source:l,description:y(c)});return}i.set(c,r.length),r.push({name:n,filePath:c,source:l,description:y(c),order:o++})},c=(e,t)=>{let n;try{n=d.realpathSync(e)}catch{n=f.resolve(e)}let r=t?h(t):K.unknown,i=a.get(n);return i!==void 0&&i>=r?!1:(a.set(n,r),!0)},l=(e,t)=>{if(!c(e,t))return;let n=f.join(e,V);if(d.existsSync(n)){s(f.basename(e),n,t);return}for(let n of j(e)){if(k(n.name)||!n.isDirectory()&&!n.isSymbolicLink())continue;let r=f.join(e,n.name);A(r)?.isDirectory()&&l(r,t)}};for(let e of n){if(!d.existsSync(e.path))continue;let t=A(e.path);if(!t)continue;if(t.isFile()){let t=f.basename(e.path);if(!O(t))continue;s(t.toLowerCase()===V.toLowerCase()?f.basename(f.dirname(e.path)):f.basename(t,f.extname(t)),e.path,e.source);continue}if(!t.isDirectory())continue;let n=f.join(e.path,V);if(d.existsSync(n)){s(f.basename(e.path),n,e.source);continue}c(e.path,e.source);for(let t of j(e.path)){if(t.name.startsWith(`.`))continue;let n=f.join(e.path,t.name);if(t.isDirectory()||t.isSymbolicLink()){if(k(t.name))continue;A(n)?.isDirectory()&&l(n,e.source);continue}t.isFile()&&O(t.name)&&s(f.basename(t.name,f.extname(t.name)),n,e.source)}}return r}function N(e,t,n){let r=new Map,i=M(e,a(),t.map(t=>({path:f.resolve(n??e,t),source:`unknown`})));for(let e of i)r.has(e.name)||r.set(e.name,e);return r}function P(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function F(e){if(e.length===0)return``;let t=[`The following configured skills are available to this subagent.`,`Use the read tool to load a skill's file when the task matches its description.`,`When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.`,``,`<available_skills>`],n=[...e].sort((e,t)=>e.name.localeCompare(t.name)||e.path.localeCompare(t.path));for(let e of n)t.push(` <skill>`),t.push(` <name>${P(e.name)}</name>`),t.push(` <description>${P(e.description??``)}</description>`),t.push(` <location>${P(e.path)}</location>`),t.push(` </skill>`);return t.push(`</available_skills>`),t.join(`
|
|
4
|
+
`)}var I,L,R,z,B,V,H,U,W,G,K,q,J=e((()=>{u(),s(),i(),l(),n(),I=50,L=8,R=5e3,z=`\0`,B=`pi-subagents`,V=`SKILL.md`,H=`.md`,U=`---`,W=`node_modules`,G=`~/`,K={project:700,"project-settings":650,user:300,"user-settings":250,extension:150,builtin:100,unknown:0},q=class{fileCache=new r(I);listingCache=new r(L);listingTtlMs=R;now(){return Date.now()}resolveSkillPath(e,t){let n=this.listSkills(t).find(t=>t.name===e);if(n)return{path:n.filePath,source:n.source}}resolveSkills(e,t,n,r){let i=[],a=[],o=n?.length?N(t,n,r):new Map;for(let n of e){let e=n.trim();if(!e)continue;if(e===B){a.push(e);continue}let r=o.get(e),s=r?this.readSkill(e,r.filePath,r.source):void 0;if(!s){let n=this.resolveSkillPath(e,t);n&&(s=this.readSkill(e,n.path,n.source))}s?i.push(s):a.push(e)}return{resolved:i,missing:a}}resolveSkillsWithFallback(e,t,n,r,i){let a=f.resolve(t),o=this.resolveSkills(e,a,r,i);if(!n||o.missing.length===0)return o;let s=f.resolve(n);if(c(a)===c(s))return o;let l=this.resolveSkills(o.missing,s);return{resolved:[...o.resolved,...l.resolved],missing:l.missing}}discoverAvailableSkills(e){return this.listSkills(e).filter(e=>e.name!==B).map(e=>({name:e.name,source:e.source,description:e.description})).sort((e,t)=>e.name.localeCompare(t.name))}invalidate(){this.fileCache.clear(),this.listingCache.clear()}listSkills(e){let t=this.now(),n=f.resolve(e),r=f.resolve(a()),i=`${c(n)}${z}${c(r)}`,o=this.listingCache.get(i);if(o&&o.expiresAt>t)return o.skills;let s=M(n,r,T(n,r)),l=new Map;for(let e of s)l.set(e.name,D(l.get(e.name),e));let u=[...l.values()].sort((e,t)=>e.order-t.order);return this.listingCache.set(i,{skills:u,expiresAt:t+this.listingTtlMs}),u}readSkill(e,t,n){try{let r=d.statSync(t),i=this.fileCache.get(t);if(i&&i.mtimeMs===r.mtimeMs)return i.skill;let a=d.readFileSync(t,`utf-8`),o={name:e,path:t,content:_(a),description:v(a),source:n};return this.fileCache.set(t,{mtimeMs:r.mtimeMs,skill:o}),o}catch{return}}},q=t([p()],q)}));J();export{q as SkillDiscoveryService,F as buildSkillInjection,J as init_skills};
|
|
5
|
+
//# sourceMappingURL=skills.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.mjs","names":[],"sources":["../../../src/services/agents/skills.ts"],"sourcesContent":["/**\n * Resolving skill files by name and rendering them into a child system prompt.\n *\n * A skill is a markdown file, either `<dir>/SKILL.md` or a bare `<name>.md`,\n * found by sweeping a fixed list of search roots. The same name can appear in\n * several roots, so the sweep records where each hit came from and the highest\n * priority source wins.\n *\n * WHY THIS IS A SERVICE AND NOT A MODULE OF FUNCTIONS:\n * Resolution walks every skill root and reads the frontmatter of every markdown\n * file it finds. Prompt assembly asks for the catalogue on each launch and\n * completion asks on each keystroke, so the answers have to be cached, and a\n * cache needs an owner that can be invalidated and swapped in a test.\n *\n * DESIGN PATTERNS:\n * - Two caches with different lifetimes. Listing answers \"does this name exist\n * and where\", reading answers \"what does it say\"; the first goes stale on any\n * directory change, the second only when one file's mtime moves\n * - Both are bounded LRUs. The predecessor held the listing in a single mutable\n * slot keyed by cwd, which thrashed the moment two working directories were in\n * play, and evicted parsed files in insertion order regardless of use\n * - Every filesystem call is best-effort. A skill root that cannot be read is\n * skipped, never fatal: a missing skill surfaces to the caller as `missing`\n * - Symlinked and repeated directories are visited at most once per priority, so\n * a cycle in the skill tree terminates\n *\n * AVOID:\n * - Walking the skill roots on a completion path without going through the cache\n * - Deriving a config directory here instead of asking `configDir.ts`\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { injectable } from 'inversify';\n\nimport { EXTRA_SKILL_DIRS_ENV } from '../../adapters/process/env.ts';\nimport { getAgentDir, getProjectConfigDir } from '../../shared/configDir.ts';\nimport { LruCache } from '../../shared/lruCache.ts';\nimport { canonicalizeDiscoveryCwd } from './projectRoot.ts';\n\n/**\n * Where a skill file was found.\n *\n * Deliberately not `AgentSource`: a skill can also come from a settings list or\n * from an extension directory, neither of which can hold an agent definition.\n */\nexport type SkillSource =\n | 'project'\n | 'user'\n | 'project-settings'\n | 'user-settings'\n | 'extension'\n | 'builtin'\n | 'unknown';\n\nexport interface ResolvedSkill {\n name: string;\n path: string;\n content: string;\n description?: string;\n source: SkillSource;\n}\n\nexport interface SkillLocation {\n path: string;\n source: SkillSource;\n}\n\nexport interface SkillResolution {\n resolved: ResolvedSkill[];\n missing: string[];\n}\n\nexport interface DiscoveredSkill {\n name: string;\n source: SkillSource;\n description?: string;\n}\n\n/**\n * Discovery and reading of skill files.\n *\n * Behind an interface for the same reason agent discovery is: the results are\n * cached and invalidated, and callers on the completion path must be able to ask\n * repeatedly without paying for a directory walk each time.\n */\nexport interface ISkillDiscoveryService {\n /** Locate one skill by name, or undefined when no root holds it. */\n resolveSkillPath(skillName: string, cwd: string): SkillLocation | undefined;\n /** Read the named skills, reporting any that could not be resolved. */\n resolveSkills(skillNames: string[], cwd: string, localSkillPaths?: string[], localBaseDir?: string): SkillResolution;\n /** Resolve against `primaryCwd`, retrying whatever is missing in `fallbackCwd`. */\n resolveSkillsWithFallback(\n skillNames: string[],\n primaryCwd: string,\n fallbackCwd?: string,\n localSkillPaths?: string[],\n localBaseDir?: string,\n ): SkillResolution;\n /** Every skill visible from `cwd`, sorted by name. */\n discoverAvailableSkills(cwd: string): DiscoveredSkill[];\n /** Drop cached results. Call after writing or removing a skill file. */\n invalidate(): void;\n}\n\n/** One entry in a listing sweep: located, but not yet read. */\ninterface CachedSkillEntry {\n name: string;\n filePath: string;\n source: SkillSource;\n description?: string;\n /** Discovery order, used to break ties between equal-priority sources. */\n order: number;\n}\n\ninterface SkillFileCacheEntry {\n mtimeMs: number;\n skill: ResolvedSkill;\n}\n\ninterface SkillListingCacheEntry {\n skills: CachedSkillEntry[];\n expiresAt: number;\n}\n\ninterface SkillSearchPath {\n path: string;\n source: SkillSource;\n}\n\n/** Roughly the number of distinct skills one session touches. */\nconst SKILL_FILE_CACHE_CAPACITY = 50;\n/** One entry per (cwd, agentDir) pair; a session rarely spans more than a few. */\nconst SKILL_LISTING_CACHE_CAPACITY = 8;\n/**\n * How long a listing stays valid.\n *\n * Short enough that a skill added mid-session appears without a restart, long\n * enough that a burst of completions does not re-walk the roots per keystroke.\n */\nconst SKILL_LISTING_TTL_MS = 5_000;\n\n/** Cache keys join two paths, so use a separator that cannot occur in either. */\nconst CACHE_KEY_SEPARATOR = '\\0';\n\n/**\n * The orchestration skill, excluded from every listing and injection.\n *\n * A subagent already has the orchestration tools wired in, so handing it the\n * skill that explains how to reach for them wastes context and invites a child\n * to fan out again. The name is the published skill's, not this package's.\n */\nconst SUBAGENT_ORCHESTRATION_SKILL = 'pi-subagents';\n\nconst SKILL_FILE_NAME = 'SKILL.md';\nconst MARKDOWN_EXTENSION = '.md';\nconst FRONTMATTER_FENCE = '---';\nconst NODE_MODULES_DIR = 'node_modules';\nconst HOME_ALIAS_PREFIX = '~/';\n\n/** Sources a listing can report, most authoritative first. */\nconst SOURCE_PRIORITY: Record<SkillSource, number> = {\n project: 700,\n 'project-settings': 650,\n user: 300,\n 'user-settings': 250,\n extension: 150,\n builtin: 100,\n unknown: 0,\n};\n\nfunction priorityOf(source: SkillSource): number {\n return SOURCE_PRIORITY[source] ?? SOURCE_PRIORITY.unknown;\n}\n\n/** Index of the first character after a closing frontmatter fence, or -1. */\nfunction findFrontmatterEnd(normalized: string): number {\n if (!normalized.startsWith(FRONTMATTER_FENCE)) return -1;\n return normalized.indexOf(`\\n${FRONTMATTER_FENCE}`, FRONTMATTER_FENCE.length);\n}\n\nexport function stripSkillFrontmatter(content: string): string {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n const endIndex = findFrontmatterEnd(normalized);\n if (endIndex === -1) return normalized;\n return normalized.slice(endIndex + 1 + FRONTMATTER_FENCE.length).trim();\n}\n\nexport function parseSkillDescription(content: string): string | undefined {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n const endIndex = findFrontmatterEnd(normalized);\n if (endIndex === -1) return undefined;\n\n const frontmatter = normalized.slice(FRONTMATTER_FENCE.length, endIndex).trim();\n const match = frontmatter.match(/^description:\\s*(.+)$/m);\n return match?.[1]?.trim().replace(/^['\"]|['\"]$/g, '');\n}\n\nfunction maybeReadSkillDescription(filePath: string): string | undefined {\n try {\n return parseSkillDescription(fs.readFileSync(filePath, 'utf-8'));\n } catch {\n // The description is optional metadata; an unreadable file still lists by name.\n return undefined;\n }\n}\n\nfunction isWithinPath(filePath: string, dir: string): boolean {\n const relative = path.relative(dir, filePath);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\n/** Read a JSON file that is allowed to be absent, but not allowed to be corrupt. */\nfunction readOptionalJsonFile(filePath: string, label: string): unknown {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n return parsed;\n } catch (error) {\n const code =\n typeof error === 'object' && error !== null && 'code' in error ? (error as { code?: unknown }).code : undefined;\n if (code === 'ENOENT') return null;\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read ${label} '${filePath}': ${message}`, {\n cause: error instanceof Error ? error : undefined,\n });\n }\n}\n\n/** Extract the string entries of a settings file's `skills` array. */\nfunction readSettingsSkillList(settings: unknown): string[] {\n if (typeof settings !== 'object' || settings === null || Array.isArray(settings)) return [];\n const skills = (settings as { skills?: unknown }).skills;\n if (!Array.isArray(skills)) return [];\n return skills.filter((entry): entry is string => typeof entry === 'string');\n}\n\nfunction collectSettingsSkillPaths(cwd: string, agentDir: string): SkillSearchPath[] {\n const results: SkillSearchPath[] = [];\n const projectConfigDir = getProjectConfigDir(cwd);\n const settingsFiles = [\n { file: path.join(projectConfigDir, 'settings.json'), base: projectConfigDir, source: 'project-settings' as const },\n { file: path.join(agentDir, 'settings.json'), base: agentDir, source: 'user-settings' as const },\n ];\n\n for (const { file, base, source } of settingsFiles) {\n for (const entry of readSettingsSkillList(readOptionalJsonFile(file, 'skills settings file'))) {\n let resolved = entry;\n if (resolved.startsWith(HOME_ALIAS_PREFIX)) {\n resolved = path.join(os.homedir(), resolved.slice(HOME_ALIAS_PREFIX.length));\n } else if (!path.isAbsolute(resolved)) {\n resolved = path.resolve(base, resolved);\n }\n results.push({ path: resolved, source });\n }\n }\n\n return results;\n}\n\nfunction extraSkillPaths(): SkillSearchPath[] {\n return (process.env[EXTRA_SKILL_DIRS_ENV] ?? '')\n .split(path.delimiter)\n .map((directory) => directory.trim())\n .filter(Boolean)\n .map((directory) => ({ path: directory, source: 'extension' as const }));\n}\n\nfunction buildSkillPaths(cwd: string, agentDir: string): SkillSearchPath[] {\n const projectConfigDir = getProjectConfigDir(cwd);\n return [\n ...extraSkillPaths(),\n { path: path.join(projectConfigDir, 'skills'), source: 'project' },\n { path: path.join(cwd, '.agents', 'skills'), source: 'project' },\n { path: path.join(agentDir, 'skills'), source: 'user' },\n { path: path.join(os.homedir(), '.agents', 'skills'), source: 'user' },\n ...collectSettingsSkillPaths(cwd, agentDir),\n ];\n}\n\n/** Classify a hit that arrived without a source hint, by which root contains it. */\nfunction inferSkillSource(filePath: string, cwd: string, agentDir: string, sourceHint?: SkillSource): SkillSource {\n if (sourceHint) return sourceHint;\n\n const projectConfigRoot = path.resolve(getProjectConfigDir(cwd));\n const projectSkillsRoot = path.resolve(projectConfigRoot, 'skills');\n const projectAgentsRoot = path.resolve(cwd, '.agents');\n const userSkillsRoot = path.resolve(agentDir, 'skills');\n const userAgentRoot = path.resolve(agentDir);\n const userAgentsRoot = path.resolve(os.homedir(), '.agents');\n\n if (isWithinPath(filePath, projectSkillsRoot) || isWithinPath(filePath, projectAgentsRoot)) return 'project';\n if (isWithinPath(filePath, projectConfigRoot)) return 'project-settings';\n\n if (isWithinPath(filePath, userSkillsRoot) || isWithinPath(filePath, userAgentsRoot)) return 'user';\n if (isWithinPath(filePath, userAgentRoot)) return 'user-settings';\n\n return 'unknown';\n}\n\nfunction chooseHigherPrioritySkill(\n existing: CachedSkillEntry | undefined,\n candidate: CachedSkillEntry,\n): CachedSkillEntry {\n if (!existing) return candidate;\n const existingPriority = priorityOf(existing.source);\n const candidatePriority = priorityOf(candidate.source);\n if (candidatePriority > existingPriority) return candidate;\n if (candidatePriority < existingPriority) return existing;\n return candidate.order < existing.order ? candidate : existing;\n}\n\nfunction isMarkdownFile(fileName: string): boolean {\n return fileName.toLowerCase().endsWith(MARKDOWN_EXTENSION);\n}\n\n/** Directory names never worth descending into while hunting for skills. */\nfunction shouldSkipDirectory(name: string): boolean {\n return name.startsWith('.') || name === NODE_MODULES_DIR;\n}\n\nfunction statOrUndefined(target: string): fs.Stats | undefined {\n try {\n return fs.statSync(target);\n } catch {\n // A dangling symlink or a path removed mid-sweep is simply not a skill.\n return undefined;\n }\n}\n\nfunction readDirOrEmpty(dirPath: string): fs.Dirent[] {\n try {\n return fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n // An unreadable root must not abort the sweep over the remaining roots.\n return [];\n }\n}\n\n/**\n * Sweep the given roots for skill files.\n *\n * Pure with respect to the caches, which is what lets it serve both the cached\n * catalogue and an agent's own uncached `skillPath` list.\n */\nfunction collectFilesystemSkills(cwd: string, agentDir: string, skillPaths: SkillSearchPath[]): CachedSkillEntry[] {\n const entries: CachedSkillEntry[] = [];\n const seen = new Map<string, number>();\n const visitedDirectories = new Map<string, number>();\n let order = 0;\n\n const pushEntry = (name: string, filePath: string, sourceHint?: SkillSource) => {\n const resolvedFile = path.resolve(filePath);\n if (!fs.existsSync(resolvedFile)) return;\n const source = inferSkillSource(resolvedFile, cwd, agentDir, sourceHint);\n const existingIndex = seen.get(resolvedFile);\n if (existingIndex !== undefined) {\n const existing = entries[existingIndex];\n if (existing && priorityOf(source) > priorityOf(existing.source)) {\n entries[existingIndex] = {\n ...existing,\n name,\n source,\n description: maybeReadSkillDescription(resolvedFile),\n };\n }\n return;\n }\n seen.set(resolvedFile, entries.length);\n entries.push({\n name,\n filePath: resolvedFile,\n source,\n description: maybeReadSkillDescription(resolvedFile),\n order: order++,\n });\n };\n\n /** False when this directory was already walked at an equal or better priority. */\n const markDirectoryVisited = (dirPath: string, sourceHint?: SkillSource): boolean => {\n let resolvedDir: string;\n try {\n resolvedDir = fs.realpathSync(dirPath);\n } catch {\n // Symlink resolution is only needed to detect cycles; the lexical path is\n // a sound fallback that at worst walks one directory twice.\n resolvedDir = path.resolve(dirPath);\n }\n const priority = sourceHint ? priorityOf(sourceHint) : SOURCE_PRIORITY.unknown;\n const previousPriority = visitedDirectories.get(resolvedDir);\n if (previousPriority !== undefined && previousPriority >= priority) return false;\n visitedDirectories.set(resolvedDir, priority);\n return true;\n };\n\n const walkSkillDirectories = (dirPath: string, sourceHint?: SkillSource) => {\n if (!markDirectoryVisited(dirPath, sourceHint)) return;\n\n // A directory holding SKILL.md is itself the skill; do not descend further.\n const skillFile = path.join(dirPath, SKILL_FILE_NAME);\n if (fs.existsSync(skillFile)) {\n pushEntry(path.basename(dirPath), skillFile, sourceHint);\n return;\n }\n\n for (const entry of readDirOrEmpty(dirPath)) {\n if (shouldSkipDirectory(entry.name)) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n const entryPath = path.join(dirPath, entry.name);\n if (statOrUndefined(entryPath)?.isDirectory()) walkSkillDirectories(entryPath, sourceHint);\n }\n };\n\n for (const skillPath of skillPaths) {\n if (!fs.existsSync(skillPath.path)) continue;\n\n const stat = statOrUndefined(skillPath.path);\n if (!stat) continue;\n\n // A root may point straight at a markdown file rather than a directory.\n if (stat.isFile()) {\n const fileName = path.basename(skillPath.path);\n if (!isMarkdownFile(fileName)) continue;\n const skillName =\n fileName.toLowerCase() === SKILL_FILE_NAME.toLowerCase()\n ? path.basename(path.dirname(skillPath.path))\n : path.basename(fileName, path.extname(fileName));\n pushEntry(skillName, skillPath.path, skillPath.source);\n continue;\n }\n\n if (!stat.isDirectory()) continue;\n\n const rootSkillFile = path.join(skillPath.path, SKILL_FILE_NAME);\n if (fs.existsSync(rootSkillFile)) {\n pushEntry(path.basename(skillPath.path), rootSkillFile, skillPath.source);\n continue;\n }\n\n markDirectoryVisited(skillPath.path, skillPath.source);\n\n for (const child of readDirOrEmpty(skillPath.path)) {\n if (child.name.startsWith('.')) continue;\n const childPath = path.join(skillPath.path, child.name);\n if (child.isDirectory() || child.isSymbolicLink()) {\n if (shouldSkipDirectory(child.name)) continue;\n if (statOrUndefined(childPath)?.isDirectory()) walkSkillDirectories(childPath, skillPath.source);\n continue;\n }\n if (child.isFile() && isMarkdownFile(child.name)) {\n pushEntry(path.basename(child.name, path.extname(child.name)), childPath, skillPath.source);\n }\n }\n }\n\n return entries;\n}\n\n@injectable()\nexport class SkillDiscoveryService implements ISkillDiscoveryService {\n /** Parsed skill bodies, keyed by resolved file path and validated by mtime. */\n private readonly fileCache = new LruCache<string, SkillFileCacheEntry>(SKILL_FILE_CACHE_CAPACITY);\n /** Located-but-unread catalogues, keyed by the (cwd, agentDir) pair. */\n private readonly listingCache = new LruCache<string, SkillListingCacheEntry>(SKILL_LISTING_CACHE_CAPACITY);\n\n /**\n * Seams for tests, as protected members rather than constructor arguments.\n *\n * The container resolves this service by type, and inversify cannot supply a\n * primitive like a TTL, so configuration cannot arrive through the\n * constructor. The repo convention is also not to abstract the clock, so a\n * test subclass overrides these instead.\n */\n protected readonly listingTtlMs: number = SKILL_LISTING_TTL_MS;\n\n protected now(): number {\n return Date.now();\n }\n\n resolveSkillPath(skillName: string, cwd: string): SkillLocation | undefined {\n const skill = this.listSkills(cwd).find((candidate) => candidate.name === skillName);\n if (!skill) return undefined;\n return { path: skill.filePath, source: skill.source };\n }\n\n resolveSkills(skillNames: string[], cwd: string, localSkillPaths?: string[], localBaseDir?: string): SkillResolution {\n const resolved: ResolvedSkill[] = [];\n const missing: string[] = [];\n const localByName = localSkillPaths?.length\n ? collectLocalSkills(cwd, localSkillPaths, localBaseDir)\n : new Map<string, CachedSkillEntry>();\n\n for (const name of skillNames) {\n const trimmed = name.trim();\n if (!trimmed) continue;\n if (trimmed === SUBAGENT_ORCHESTRATION_SKILL) {\n missing.push(trimmed);\n continue;\n }\n\n // An agent's own skillPath outranks anything found in the shared roots.\n const local = localByName.get(trimmed);\n let skill = local ? this.readSkill(trimmed, local.filePath, local.source) : undefined;\n if (!skill) {\n const location = this.resolveSkillPath(trimmed, cwd);\n if (location) skill = this.readSkill(trimmed, location.path, location.source);\n }\n if (skill) resolved.push(skill);\n else missing.push(trimmed);\n }\n\n return { resolved, missing };\n }\n\n /**\n * Resolve against `primaryCwd`, then retry whatever is still missing elsewhere.\n *\n * A child launched into a worktree still needs the skills configured in the\n * repository it was launched from.\n */\n resolveSkillsWithFallback(\n skillNames: string[],\n primaryCwd: string,\n fallbackCwd?: string,\n localSkillPaths?: string[],\n localBaseDir?: string,\n ): SkillResolution {\n const resolvedPrimaryCwd = path.resolve(primaryCwd);\n const primary = this.resolveSkills(skillNames, resolvedPrimaryCwd, localSkillPaths, localBaseDir);\n if (!fallbackCwd || primary.missing.length === 0) return primary;\n const resolvedFallbackCwd = path.resolve(fallbackCwd);\n if (canonicalizeDiscoveryCwd(resolvedPrimaryCwd) === canonicalizeDiscoveryCwd(resolvedFallbackCwd)) return primary;\n\n const fallback = this.resolveSkills(primary.missing, resolvedFallbackCwd);\n return {\n resolved: [...primary.resolved, ...fallback.resolved],\n missing: fallback.missing,\n };\n }\n\n discoverAvailableSkills(cwd: string): DiscoveredSkill[] {\n return this.listSkills(cwd)\n .filter((skill) => skill.name !== SUBAGENT_ORCHESTRATION_SKILL)\n .map((skill) => ({\n name: skill.name,\n source: skill.source,\n description: skill.description,\n }))\n .sort((a, b) => a.name.localeCompare(b.name));\n }\n\n invalidate(): void {\n this.fileCache.clear();\n this.listingCache.clear();\n }\n\n /** The catalogue visible from `cwd`, sweeping the roots only when stale. */\n private listSkills(cwd: string): CachedSkillEntry[] {\n const timestamp = this.now();\n const resolvedCwd = path.resolve(cwd);\n const resolvedAgentDir = path.resolve(getAgentDir());\n const key = `${canonicalizeDiscoveryCwd(resolvedCwd)}${CACHE_KEY_SEPARATOR}${canonicalizeDiscoveryCwd(resolvedAgentDir)}`;\n\n const cached = this.listingCache.get(key);\n if (cached && cached.expiresAt > timestamp) return cached.skills;\n\n const loaded = collectFilesystemSkills(\n resolvedCwd,\n resolvedAgentDir,\n buildSkillPaths(resolvedCwd, resolvedAgentDir),\n );\n const dedupedByName = new Map<string, CachedSkillEntry>();\n for (const entry of loaded) {\n dedupedByName.set(entry.name, chooseHigherPrioritySkill(dedupedByName.get(entry.name), entry));\n }\n\n const skills = [...dedupedByName.values()].sort((a, b) => a.order - b.order);\n this.listingCache.set(key, { skills, expiresAt: timestamp + this.listingTtlMs });\n return skills;\n }\n\n /** Read one skill file, reusing the cached parse while its mtime holds. */\n private readSkill(skillName: string, skillPath: string, source: SkillSource): ResolvedSkill | undefined {\n try {\n const stat = fs.statSync(skillPath);\n const cached = this.fileCache.get(skillPath);\n if (cached && cached.mtimeMs === stat.mtimeMs) return cached.skill;\n\n const raw = fs.readFileSync(skillPath, 'utf-8');\n const skill: ResolvedSkill = {\n name: skillName,\n path: skillPath,\n content: stripSkillFrontmatter(raw),\n description: parseSkillDescription(raw),\n source,\n };\n\n this.fileCache.set(skillPath, { mtimeMs: stat.mtimeMs, skill });\n return skill;\n } catch {\n // Treat an unreadable skill file as unresolved so the caller reports it\n // missing rather than injecting a half-formed block into a child prompt.\n return undefined;\n }\n }\n}\n\n/**\n * Index skill files supplied by an agent's own `skillPath`, keyed by name.\n *\n * Deliberately uncached: these paths are per-agent rather than per-directory, so\n * they would pollute a catalogue cache keyed on cwd.\n */\nfunction collectLocalSkills(\n cwd: string,\n localSkillPaths: string[],\n localBaseDir?: string,\n): Map<string, CachedSkillEntry> {\n const localByName = new Map<string, CachedSkillEntry>();\n const localEntries = collectFilesystemSkills(\n cwd,\n getAgentDir(),\n localSkillPaths.map((entry) => ({\n path: path.resolve(localBaseDir ?? cwd, entry),\n source: 'unknown' as const,\n })),\n );\n for (const entry of localEntries) {\n if (!localByName.has(entry.name)) localByName.set(entry.name, entry);\n }\n return localByName;\n}\n\nfunction escapeXmlText(value: string): string {\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\n/**\n * Render the skill catalogue for a child system prompt.\n *\n * Only names, descriptions and locations are injected. The child reads a skill\n * when its description matches the task, which keeps the prompt small no matter\n * how large the configured skill bodies are.\n */\nexport function buildSkillInjection(skills: ResolvedSkill[]): string {\n if (skills.length === 0) return '';\n\n const lines = [\n 'The following configured skills are available to this subagent.',\n \"Use the read tool to load a skill's file when the task matches its description.\",\n 'When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.',\n '',\n '<available_skills>',\n ];\n const stableSkills = [...skills].sort(\n (left, right) => left.name.localeCompare(right.name) || left.path.localeCompare(right.path),\n );\n for (const skill of stableSkills) {\n lines.push(' <skill>');\n lines.push(` <name>${escapeXmlText(skill.name)}</name>`);\n lines.push(` <description>${escapeXmlText(skill.description ?? '')}</description>`);\n lines.push(` <location>${escapeXmlText(skill.path)}</location>`);\n lines.push(' </skill>');\n }\n lines.push('</available_skills>');\n return lines.join('\\n');\n}\n\nfunction dedupeSkillNames(names: string[]): string[] {\n return [...new Set(names.map((entry) => entry.trim()).filter((entry) => entry.length > 0))];\n}\n\n/**\n * Normalise the `skills` tool parameter into a name list.\n *\n * `false` means \"no skills at all\" and `undefined` means \"use the agent's own\n * configuration\", which is why they are distinct return values rather than both\n * collapsing to an empty array.\n */\nexport function normalizeSkillInput(input: string | string[] | boolean | undefined): string[] | false | undefined {\n if (input === false) return false;\n if (input === true || input === undefined) return undefined;\n if (Array.isArray(input)) return dedupeSkillNames(input);\n\n // Models sometimes serialise the parameter as a JSON string instead of a native\n // array. Splitting '[\"a\",\"b\"]' on commas would embed brackets and quotes into\n // the names, and resolution would then fail with no obvious cause.\n const trimmed = input.trim();\n if (trimmed.startsWith('[')) {\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (Array.isArray(parsed)) {\n return dedupeSkillNames(parsed.filter((entry): entry is string => typeof entry === 'string'));\n }\n } catch {\n // Not valid JSON after all; fall through to the comma-separated reading.\n }\n }\n return dedupeSkillNames(input.split(','));\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SystemPromptMode, ToolBudgetConfig } from "
|
|
1
|
+
import { SystemPromptMode, ToolBudgetConfig } from "../../types/index.cjs";
|
|
2
2
|
|
|
3
|
-
//#region src/agents/types.d.ts
|
|
3
|
+
//#region src/services/agents/types.d.ts
|
|
4
4
|
/** Which directories a discovery pass should read. */
|
|
5
5
|
type AgentScope = 'user' | 'project' | 'both';
|
|
6
6
|
/**
|
|
@@ -20,8 +20,8 @@ interface AgentMemoryConfig {
|
|
|
20
20
|
}
|
|
21
21
|
/** Records that a model came from a settings default rather than frontmatter. */
|
|
22
22
|
interface AgentModelSourceInfo {
|
|
23
|
-
type: 'subagents.defaultModel' | '
|
|
24
|
-
scope: 'user' | 'project' | '
|
|
23
|
+
type: 'subagents.defaultModel' | 'packages.team.defaultModel';
|
|
24
|
+
scope: 'user' | 'project' | 'package';
|
|
25
25
|
path: string;
|
|
26
26
|
model: string;
|
|
27
27
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../../src/services/agents/types.ts"],"mappings":";;;;KAmBY,UAAA;AAaZ;;;;;AAEA;AAFA,KALY,WAAA;;KAGA,mBAAA;AAAA,KAEA,gBAAA;AAAA,UAEK,iBAAA;EACf,OAAA;EACA,KAAA,GAAQ,gBAAA;EACR,UAAA;AAAA;AAIF;AAAA,UAAiB,oBAAA;EACf,IAAA;EACA,KAAA;EACA,IAAA;EACA,KAAA;AAAA;;;;AAUF;;;;UAAiB,wBAAA;EACf,WAAA;EACA,KAAA;EACA,KAAA;EACA,cAAA;EACA,QAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,qBAAA;EACA,aAAA;EACA,MAAA;EACA,SAAA;EACA,UAAA;EACA,sBAAA;EACA,MAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA,GAAiB,mBAAA;EACjB,gBAAA;EAJA;EAMA,OAAA;EACA,WAAA;EACA,gBAAA;EACA,eAAA;EACA,UAAA,GAAa,gBAAA;EACb,MAAA,GAAS,iBAAA;EACT,YAAA;EACA,QAAA;AAAA;;UAsCe,wBAAA;EACf,KAAA;EACA,IAAA;EACA,IAAA,EAAM,wBAAA;AAAA;;;;;;;UASS,WAAA;EACf,IAAA;EAiBA;EAfA,SAAA;EACA,WAAA;EACA,WAAA;EACA,KAAA;EACA,cAAA;EACA,KAAA;EACA,cAAA;EACA,QAAA;EACA,gBAAA,EAAkB,gBAAA;EAClB,qBAAA;EAmBA;EAjBA,aAAA;EACA,cAAA,GAAiB,mBAAA;EACjB,gBAAA;EAmBA;EAjBA,OAAA;EACA,YAAA;EACA,MAAA,EAAQ,WAAA;EACR,QAAA;EAiBA;EAfA,MAAA;EAiBc;EAfd,SAAA;EACA,UAAA;EAgBA;EAdA,qBAAA;EACA,sBAAA;EACA,MAAA;EACA,YAAA;EACA,eAAA;EACA,WAAA;EACA,gBAAA;EACA,eAAA;EACA,UAAA,GAAa,gBAAA;EACb,MAAA,GAAS,iBAAA;EACT,QAAA;;EAEA,WAAA,GAAc,MAAA;EACd,QAAA,GAAW,wBAAA;EACX,WAAA,GAAc,oBAAA;AAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SystemPromptMode, ToolBudgetConfig } from "
|
|
1
|
+
import { SystemPromptMode, ToolBudgetConfig } from "../../types/index.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/agents/types.d.ts
|
|
3
|
+
//#region src/services/agents/types.d.ts
|
|
4
4
|
/** Which directories a discovery pass should read. */
|
|
5
5
|
type AgentScope = 'user' | 'project' | 'both';
|
|
6
6
|
/**
|
|
@@ -20,8 +20,8 @@ interface AgentMemoryConfig {
|
|
|
20
20
|
}
|
|
21
21
|
/** Records that a model came from a settings default rather than frontmatter. */
|
|
22
22
|
interface AgentModelSourceInfo {
|
|
23
|
-
type: 'subagents.defaultModel' | '
|
|
24
|
-
scope: 'user' | 'project' | '
|
|
23
|
+
type: 'subagents.defaultModel' | 'packages.team.defaultModel';
|
|
24
|
+
scope: 'user' | 'project' | 'package';
|
|
25
25
|
path: string;
|
|
26
26
|
model: string;
|
|
27
27
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/services/agents/types.ts"],"mappings":";;;;KAmBY,UAAA;AAaZ;;;;;AAEA;AAFA,KALY,WAAA;;KAGA,mBAAA;AAAA,KAEA,gBAAA;AAAA,UAEK,iBAAA;EACf,OAAA;EACA,KAAA,GAAQ,gBAAA;EACR,UAAA;AAAA;AAIF;AAAA,UAAiB,oBAAA;EACf,IAAA;EACA,KAAA;EACA,IAAA;EACA,KAAA;AAAA;;;;AAUF;;;;UAAiB,wBAAA;EACf,WAAA;EACA,KAAA;EACA,KAAA;EACA,cAAA;EACA,QAAA;EACA,gBAAA,GAAmB,gBAAA;EACnB,qBAAA;EACA,aAAA;EACA,MAAA;EACA,SAAA;EACA,UAAA;EACA,sBAAA;EACA,MAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA,GAAiB,mBAAA;EACjB,gBAAA;EAJA;EAMA,OAAA;EACA,WAAA;EACA,gBAAA;EACA,eAAA;EACA,UAAA,GAAa,gBAAA;EACb,MAAA,GAAS,iBAAA;EACT,YAAA;EACA,QAAA;AAAA;;UAsCe,wBAAA;EACf,KAAA;EACA,IAAA;EACA,IAAA,EAAM,wBAAA;AAAA;;;;;;;UASS,WAAA;EACf,IAAA;EAiBA;EAfA,SAAA;EACA,WAAA;EACA,WAAA;EACA,KAAA;EACA,cAAA;EACA,KAAA;EACA,cAAA;EACA,QAAA;EACA,gBAAA,EAAkB,gBAAA;EAClB,qBAAA;EAmBA;EAjBA,aAAA;EACA,cAAA,GAAiB,mBAAA;EACjB,gBAAA;EAmBA;EAjBA,OAAA;EACA,YAAA;EACA,MAAA,EAAQ,WAAA;EACR,QAAA;EAiBA;EAfA,MAAA;EAiBc;EAfd,SAAA;EACA,UAAA;EAgBA;EAdA,qBAAA;EACA,sBAAA;EACA,MAAA;EACA,YAAA;EACA,eAAA;EACA,WAAA;EACA,gBAAA;EACA,eAAA;EACA,UAAA,GAAa,gBAAA;EACb,MAAA,GAAS,iBAAA;EACT,QAAA;;EAEA,WAAA,GAAc,MAAA;EACd,QAAA,GAAW,wBAAA;EACX,WAAA,GAAc,oBAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require(`../../schemas/team/backgroundWork.cjs`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { BACKGROUND_WORK_PROTOCOL_VERSION, BACKGROUND_WORK_REGISTRATION_BRIDGE_KEY, BACKGROUND_WORK_REGISTRY_KEY, BackgroundWorkItem, BackgroundWorkProvider, BackgroundWorkReconcileContext, BackgroundWorkRegistrationBridge, BackgroundWorkSnapshot, RegisteredBackgroundWorkItem, installBackgroundWorkRegistrationBridge, listBackgroundWorkProviders, listBackgroundWorkWakeChannels, registerBackgroundWorkProvider, snapshotBackgroundWork } from "../../schemas/team/backgroundWork.cjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { BACKGROUND_WORK_PROTOCOL_VERSION, BACKGROUND_WORK_REGISTRATION_BRIDGE_KEY, BACKGROUND_WORK_REGISTRY_KEY, BackgroundWorkItem, BackgroundWorkProvider, BackgroundWorkReconcileContext, BackgroundWorkRegistrationBridge, BackgroundWorkSnapshot, RegisteredBackgroundWorkItem, installBackgroundWorkRegistrationBridge, listBackgroundWorkProviders, listBackgroundWorkWakeChannels, registerBackgroundWorkProvider, snapshotBackgroundWork } from "../../schemas/team/backgroundWork.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../../schemas/team/backgroundWork.mjs";export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require(`../../adapters/process/env.cjs`),require(`../../schemas/team/capabilityCeiling.cjs`);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { SUBAGENT_CAPABILITY_CEILING_ENV } from "../../adapters/process/env.cjs";
|
|
2
|
+
import { RegisterSubagentCapabilityCeilingOptions, ResolvedSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY, SUBAGENT_CAPABILITY_CEILING_VERSION, SubagentCapabilityAudit, SubagentCapabilityCeiling, SubagentCapabilityCeilingHandle, decodeSubagentCapabilityCeiling, encodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, parseSubagentCapabilityCeiling, registerSubagentCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling, resolveSubagentCapabilityCeiling } from "../../schemas/team/capabilityCeiling.cjs";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { SUBAGENT_CAPABILITY_CEILING_ENV } from "../../adapters/process/env.mjs";
|
|
2
|
+
import { RegisterSubagentCapabilityCeilingOptions, ResolvedSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY, SUBAGENT_CAPABILITY_CEILING_VERSION, SubagentCapabilityAudit, SubagentCapabilityCeiling, SubagentCapabilityCeilingHandle, decodeSubagentCapabilityCeiling, encodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, parseSubagentCapabilityCeiling, registerSubagentCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling, resolveSubagentCapabilityCeiling } from "../../schemas/team/capabilityCeiling.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityCeiling.mjs","names":[],"sources":["../../../src/services/api/capabilityCeiling.ts"],"sourcesContent":["/**\n * Public entry point: subagent capability ceilings.\n *\n * Consumed by doom-plan, which registers a ceiling while planning mode is on so\n * spawned subagents inherit the same read-only restriction.\n */\n\nexport {\n decodeSubagentCapabilityCeiling,\n encodeSubagentCapabilityCeiling,\n intersectSubagentCapabilityCeilings,\n parseSubagentCapabilityCeiling,\n type RegisterSubagentCapabilityCeilingOptions,\n type ResolvedSubagentCapabilityCeiling,\n registerSubagentCapabilityCeiling,\n resolveCurrentSubagentCapabilityCeiling,\n resolveSubagentCapabilityCeiling,\n SUBAGENT_CAPABILITY_CEILING_ENV,\n SUBAGENT_CAPABILITY_CEILING_REGISTRY_KEY,\n SUBAGENT_CAPABILITY_CEILING_VERSION,\n type SubagentCapabilityAudit,\n type SubagentCapabilityCeiling,\n type SubagentCapabilityCeilingHandle,\n} from '../../schemas/team/capabilityCeiling.ts';\n"],"mappings":"4HAuBiD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require(`../intercom/nativeTeamChannel.cjs`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { NativeTeamMemberSnapshot, NativeTeamSnapshot, readActiveNativeTeamSnapshot } from "../intercom/nativeTeamChannel.cjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { NativeTeamMemberSnapshot, NativeTeamSnapshot, readActiveNativeTeamSnapshot } from "../intercom/nativeTeamChannel.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teamSnapshot.mjs","names":[],"sources":["../../../src/services/api/teamSnapshot.ts"],"sourcesContent":["export {\n type NativeTeamMemberSnapshot,\n type NativeTeamSnapshot,\n readActiveNativeTeamSnapshot,\n} from '../intercom/nativeTeamChannel.ts';\n"],"mappings":"8EAI0C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intercomBridge.cjs","names":[],"sources":["../../../src/services/intercom/intercomBridge.ts"],"sourcesContent":["/**\n * Whether a child would be wired to talk back to the session that spawned it,\n * reported for diagnostics.\n *\n * WHY THIS IS ONLY A DIAGNOSTIC NOW:\n * Children receive the native intercom runtime directly. This module retains\n * only the human-facing doctor diagnostic and does not register or alias tools.\n *\n * AVOID:\n * - Re-adding a resolution path here without a caller. If the bridge needs to\n * shape an agent again, wire it in the same change\n */\n\nexport const NATIVE_INTERCOM_EXTENSION_DIR = 'native:doom-team-intercom';\n\nexport type IntercomBridgeMode = 'off' | 'always' | 'fork-only';\n\n/** The intercom-bridge slice of this package's extension config. Narrow on purpose. */\nexport interface IntercomBridgeConfigInput {\n mode?: unknown;\n instructionFile?: unknown;\n resultDelivery?: unknown;\n}\n\ninterface ResolvedIntercomBridgeConfig {\n mode: IntercomBridgeMode;\n resultDelivery: boolean;\n}\n\nexport interface IntercomBridgeDiagnostic {\n active: boolean;\n mode: IntercomBridgeMode;\n wantsIntercom: boolean;\n intercomAvailable: boolean;\n extensionDir: string;\n orchestratorTarget?: string;\n reason?: string;\n}\n\ninterface ResolveIntercomBridgeInput {\n config: IntercomBridgeConfigInput | undefined;\n context: 'fresh' | 'fork' | undefined;\n orchestratorTarget?: string;\n}\n\nexport function resolveIntercomBridgeMode(value: unknown): IntercomBridgeMode {\n if (value === 'off' || value === 'always' || value === 'fork-only') return value;\n return 'always';\n}\n\nfunction resolveIntercomBridgeConfig(value: IntercomBridgeConfigInput | undefined): ResolvedIntercomBridgeConfig {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { mode: 'always', resultDelivery: true };\n }\n return { mode: resolveIntercomBridgeMode(value.mode), resultDelivery: value.resultDelivery !== false };\n}\n\n/** Why the bridge is not active, or `undefined` when it is. */\nfunction inactiveReason(\n mode: IntercomBridgeMode,\n context: 'fresh' | 'fork' | undefined,\n orchestratorTarget: string | undefined,\n): string | undefined {\n if (mode === 'off') return 'bridge mode is off';\n if (mode === 'fork-only' && context !== 'fork') return 'bridge mode is fork-only and context is not fork';\n if (!orchestratorTarget) return 'orchestrator target is not available';\n return undefined;\n}\n\n/**\n * Report the bridge's state without changing anything.\n *\n * `wantsIntercom` and `active` differ deliberately: the first says the\n * configuration asks for a bridge, the second says one is actually available.\n * A doctor report needs to distinguish \"you turned it off\" from \"it is on but\n * has no orchestrator to reach\".\n */\nexport function diagnoseIntercomBridge(input: ResolveIntercomBridgeInput): IntercomBridgeDiagnostic {\n const { mode } = resolveIntercomBridgeConfig(input.config);\n const orchestratorTarget = input.orchestratorTarget?.trim();\n const wantsIntercom = mode !== 'off' && !(mode === 'fork-only' && input.context !== 'fork');\n const reason = inactiveReason(mode, input.context, orchestratorTarget);\n return {\n active: reason === undefined,\n mode,\n wantsIntercom,\n intercomAvailable: true,\n extensionDir: NATIVE_INTERCOM_EXTENSION_DIR,\n ...(orchestratorTarget ? { orchestratorTarget } : {}),\n ...(reason ? { reason } : {}),\n };\n}\n"],"mappings":"AA6CA,SAAgB,EAA0B,EAAoC,CAE5E,OADI,IAAU,OAAS,IAAU,UAAY,IAAU,YAAoB,EACpE,SAGT,SAAS,EAA4B,EAA4E,CAI/G,MAHI,CAAC,GAAS,OAAO,GAAU,UAAY,MAAM,QAAQ,EAAM,CACtD,CAAE,KAAM,SAAU,eAAgB,GAAM,CAE1C,CAAE,KAAM,EAA0B,EAAM,KAAK,CAAE,eAAgB,EAAM,iBAAmB,GAAO,CAIxG,SAAS,EACP,EACA,EACA,EACoB,CACpB,GAAI,IAAS,MAAO,MAAO,qBAC3B,GAAI,IAAS,aAAe,IAAY,OAAQ,MAAO,mDACvD,GAAI,CAAC,EAAoB,MAAO,uCAYlC,SAAgB,EAAuB,EAA6D,CAClG,GAAM,CAAE,QAAS,EAA4B,EAAM,OAAO,CACpD,EAAqB,EAAM,oBAAoB,MAAM,CACrD,EAAgB,IAAS,OAAS,EAAE,IAAS,aAAe,EAAM,UAAY,QAC9E,EAAS,EAAe,EAAM,EAAM,QAAS,EAAmB,CACtE,MAAO,CACL,OAAQ,IAAW,IAAA,GACnB,OACA,gBACA,kBAAmB,GACnB,aAAc,4BACd,GAAI,EAAqB,CAAE,qBAAoB,CAAG,EAAE,CACpD,GAAI,EAAS,CAAE,SAAQ,CAAG,EAAE,CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intercomBridge.mjs","names":[],"sources":["../../../src/services/intercom/intercomBridge.ts"],"sourcesContent":["/**\n * Whether a child would be wired to talk back to the session that spawned it,\n * reported for diagnostics.\n *\n * WHY THIS IS ONLY A DIAGNOSTIC NOW:\n * Children receive the native intercom runtime directly. This module retains\n * only the human-facing doctor diagnostic and does not register or alias tools.\n *\n * AVOID:\n * - Re-adding a resolution path here without a caller. If the bridge needs to\n * shape an agent again, wire it in the same change\n */\n\nexport const NATIVE_INTERCOM_EXTENSION_DIR = 'native:doom-team-intercom';\n\nexport type IntercomBridgeMode = 'off' | 'always' | 'fork-only';\n\n/** The intercom-bridge slice of this package's extension config. Narrow on purpose. */\nexport interface IntercomBridgeConfigInput {\n mode?: unknown;\n instructionFile?: unknown;\n resultDelivery?: unknown;\n}\n\ninterface ResolvedIntercomBridgeConfig {\n mode: IntercomBridgeMode;\n resultDelivery: boolean;\n}\n\nexport interface IntercomBridgeDiagnostic {\n active: boolean;\n mode: IntercomBridgeMode;\n wantsIntercom: boolean;\n intercomAvailable: boolean;\n extensionDir: string;\n orchestratorTarget?: string;\n reason?: string;\n}\n\ninterface ResolveIntercomBridgeInput {\n config: IntercomBridgeConfigInput | undefined;\n context: 'fresh' | 'fork' | undefined;\n orchestratorTarget?: string;\n}\n\nexport function resolveIntercomBridgeMode(value: unknown): IntercomBridgeMode {\n if (value === 'off' || value === 'always' || value === 'fork-only') return value;\n return 'always';\n}\n\nfunction resolveIntercomBridgeConfig(value: IntercomBridgeConfigInput | undefined): ResolvedIntercomBridgeConfig {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { mode: 'always', resultDelivery: true };\n }\n return { mode: resolveIntercomBridgeMode(value.mode), resultDelivery: value.resultDelivery !== false };\n}\n\n/** Why the bridge is not active, or `undefined` when it is. */\nfunction inactiveReason(\n mode: IntercomBridgeMode,\n context: 'fresh' | 'fork' | undefined,\n orchestratorTarget: string | undefined,\n): string | undefined {\n if (mode === 'off') return 'bridge mode is off';\n if (mode === 'fork-only' && context !== 'fork') return 'bridge mode is fork-only and context is not fork';\n if (!orchestratorTarget) return 'orchestrator target is not available';\n return undefined;\n}\n\n/**\n * Report the bridge's state without changing anything.\n *\n * `wantsIntercom` and `active` differ deliberately: the first says the\n * configuration asks for a bridge, the second says one is actually available.\n * A doctor report needs to distinguish \"you turned it off\" from \"it is on but\n * has no orchestrator to reach\".\n */\nexport function diagnoseIntercomBridge(input: ResolveIntercomBridgeInput): IntercomBridgeDiagnostic {\n const { mode } = resolveIntercomBridgeConfig(input.config);\n const orchestratorTarget = input.orchestratorTarget?.trim();\n const wantsIntercom = mode !== 'off' && !(mode === 'fork-only' && input.context !== 'fork');\n const reason = inactiveReason(mode, input.context, orchestratorTarget);\n return {\n active: reason === undefined,\n mode,\n wantsIntercom,\n intercomAvailable: true,\n extensionDir: NATIVE_INTERCOM_EXTENSION_DIR,\n ...(orchestratorTarget ? { orchestratorTarget } : {}),\n ...(reason ? { reason } : {}),\n };\n}\n"],"mappings":"AA6CA,SAAgB,EAA0B,EAAoC,CAE5E,OADI,IAAU,OAAS,IAAU,UAAY,IAAU,YAAoB,EACpE,SAGT,SAAS,EAA4B,EAA4E,CAI/G,MAHI,CAAC,GAAS,OAAO,GAAU,UAAY,MAAM,QAAQ,EAAM,CACtD,CAAE,KAAM,SAAU,eAAgB,GAAM,CAE1C,CAAE,KAAM,EAA0B,EAAM,KAAK,CAAE,eAAgB,EAAM,iBAAmB,GAAO,CAIxG,SAAS,EACP,EACA,EACA,EACoB,CACpB,GAAI,IAAS,MAAO,MAAO,qBAC3B,GAAI,IAAS,aAAe,IAAY,OAAQ,MAAO,mDACvD,GAAI,CAAC,EAAoB,MAAO,uCAYlC,SAAgB,EAAuB,EAA6D,CAClG,GAAM,CAAE,QAAS,EAA4B,EAAM,OAAO,CACpD,EAAqB,EAAM,oBAAoB,MAAM,CACrD,EAAgB,IAAS,OAAS,EAAE,IAAS,aAAe,EAAM,UAAY,QAC9E,EAAS,EAAe,EAAM,EAAM,QAAS,EAAmB,CACtE,MAAO,CACL,OAAQ,IAAW,IAAA,GACnB,OACA,gBACA,kBAAmB,GACnB,aAAc,4BACd,GAAI,EAAqB,CAAE,qBAAoB,CAAG,EAAE,CACpD,GAAI,EAAS,CAAE,SAAQ,CAAG,EAAE,CAC7B"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const e=require(`../../_virtual/_rolldown/runtime.cjs`),t=require(`../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.cjs`),n=require(`../../shared/lruCache.cjs`),r=require(`../../adapters/atomicJson.cjs`);require(`../../shared/atomicJson.cjs`);const i=require(`../../adapters/process/env.cjs`),a=require(`../../shared/paths.cjs`),o=require(`../../shared/errors.cjs`),s=require(`../../shared/versioned.cjs`),c=require(`../../shared/boundedKeySet.cjs`);let l=require(`node:fs`);l=e.__toESM(l,1);let u=require(`node:path`);u=e.__toESM(u,1);let d=require(`inversify`),f=require(`node:crypto`);const p=`intercom`,m=`subagent.team.message`,h=`subagent.team.reply`,g=`members`,_=`heartbeats`,ee=`inboxes`,v=`replies`,te=`receipts`,ne=`team.json`,y=`.json`,b=`main`,x=`agent`,S=64*1024,C=4*1024,re=[`members`,`send`,`ask`,`reply`,`pending`],ie=/^[A-Za-z0-9._-]{1,256}$/,ae=/[^a-z0-9._-]+/g,w=/^[-.]+|[-.]+$/g,oe=`sha256`,T=`delivered`,se=`failed`,ce={oneOf:[...[`members`,`pending`].map(e=>({type:`object`,properties:{action:{const:e}},required:[`action`],additionalProperties:!1})),{type:`object`,properties:{action:{const:`send`},to:{type:`string`},message:{type:`string`}},required:[`action`,`to`,`message`],additionalProperties:!1},{type:`object`,properties:{action:{const:`ask`},to:{type:`string`},message:{type:`string`},timeoutMs:{type:`integer`,minimum:1}},required:[`action`,`to`,`message`],additionalProperties:!1},{type:`object`,properties:{action:{const:`reply`},requestId:{type:`string`},message:{type:`string`}},required:[`action`,`requestId`,`message`],additionalProperties:!1}]};function E(e){return typeof e==`string`&&ie.test(e)}function D(e){return typeof e==`number`&&Number.isInteger(e)}function O(e){return typeof e==`number`&&Number.isFinite(e)}function k(e){return typeof e==`string`&&e.trim().length>0}function A(e){return e===void 0||typeof e==`string`}function le(e){return e===void 0||D(e)}function ue(e){return e===`main`||e===`subagent`}function de(e){return e===`send`||e===`ask`}function j(e,t){return Buffer.byteLength(e,`utf-8`)<=t}function fe(e){return e instanceof Error?e.message:String(e)}function M(e){return process.env[e]?.trim()||void 0}function N(e){return(0,f.createHash)(oe).update(e).digest(`hex`)}function pe(){return(0,f.randomBytes)(32).toString(`base64url`)}function me(e){return`session-${N(e).slice(0,32)}`}function P(e){return e.trim().toLowerCase().replace(ae,`-`).replace(w,``).slice(0,48).replace(w,``)||x}function he(e,t){let n=`-${t+1}`,r=48-n.length;return`${e.slice(0,Math.max(r,0)).replace(w,``)||x}${n}`}function ge(e,t){if(e!==b)return e;if(t)throw Error(`Native team member name '${b}' is reserved for the root session.`);return`main-agent`}function F(e){if(!E(e))throw Error(`Invalid native team id.`);return u.join(a.scopeTeamDir(a.requireCurrentSessionScope()),e)}function I(e,t){if(!E(t))throw Error(`Invalid native team member id.`);return u.join(F(e.teamId),g,`${t}${y}`)}function L(e,t){if(!E(t))throw Error(`Invalid native team member id.`);return u.join(F(e.teamId),_,`${t}${y}`)}function R(e,t){if(!E(t))throw Error(`Invalid native team member id.`);return u.join(F(e.teamId),ee,t)}function z(e){return`${e}${y}`}function B(e,t,n){if(!E(n))throw Error(`Invalid native team message id.`);return u.join(R(e,t),z(n))}function _e(e,t){if(!E(t))throw Error(`Invalid native team request id.`);return u.join(F(e.teamId),v,`${t}${y}`)}function V(e,t,n){if(!E(t)||!E(n))throw Error(`Invalid intercom receipt identity.`);return u.join(F(e.teamId),te,t,`${n}${y}`)}function ve(e,t){return(0,f.createHash)(oe).update(`${e}:${t}`).digest(`hex`)}function ye(e){let t=F(e.teamId);for(let e of[g,_,ee,v,te])l.mkdirSync(u.join(t,e),{recursive:!0,mode:448})}function H(e){try{let t=JSON.parse(l.readFileSync(e,`utf-8`));return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}catch{return}}function U(e){try{return l.rmSync(e,{force:!0}),!0}catch(e){return e.code===`ENOENT`}}function be(e){try{l.rmSync(e,{recursive:!0,force:!0})}catch{}}function W(e){if(!(!s.parseVersioned(e,[1]).ok||!e)&&!(!E(e.teamId)||!k(e.rootSessionId)||e.mainMemberId!==b||!O(e.createdAt)||!O(e.updatedAt)))return{version:1,teamId:e.teamId,rootSessionId:e.rootSessionId,mainMemberId:b,createdAt:e.createdAt,updatedAt:e.updatedAt}}function xe(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e;if(!(!k(t.id)||!k(t.subject))&&!(!j(t.id,256)||!j(t.subject,C)))return{id:t.id,subject:t.subject}}function Se(e){if(!s.parseVersioned(e,[1]).ok||!e||!E(e.teamId)||!k(e.rootSessionId)||!k(e.mainMemberId)||!E(e.memberId)||!ue(e.role)||!k(e.tokenHash)||!D(e.pid)||typeof e.active!=`boolean`||!O(e.joinedAt)||!A(e.agent)||!A(e.runId)||!le(e.childIndex)||!A(e.parentMemberId))return;let t=e.task===void 0?void 0:xe(e.task);if(!(e.task!==void 0&&!t))return{version:1,teamId:e.teamId,rootSessionId:e.rootSessionId,mainMemberId:e.mainMemberId,memberId:e.memberId,role:e.role,tokenHash:e.tokenHash,pid:e.pid,active:e.active,joinedAt:e.joinedAt,...O(e.leftAt)?{leftAt:e.leftAt}:{},...e.agent===void 0?{}:{agent:e.agent},...e.runId===void 0?{}:{runId:e.runId},...e.childIndex===void 0?{}:{childIndex:e.childIndex},...e.parentMemberId===void 0?{}:{parentMemberId:e.parentMemberId},...t?{task:t}:{}}}function Ce(e){if(!(!s.parseVersioned(e,[1]).ok||!e)&&!(!E(e.memberId)||!k(e.tokenHash)||!D(e.pid)||!O(e.heartbeatAt)))return{version:1,memberId:e.memberId,tokenHash:e.tokenHash,pid:e.pid,heartbeatAt:e.heartbeatAt}}function we(e){if(!(!s.parseVersioned(e,[2]).ok||!e)&&!(e.type!==m||!E(e.id)||!E(e.teamId)||!de(e.kind)||!E(e.fromMemberId)||!E(e.toMemberId)||!k(e.senderTokenHash)||!D(e.seq)||typeof e.message!=`string`||!j(e.message,S)||!O(e.createdAt)||!O(e.expiresAt)))return{type:m,version:2,id:e.id,teamId:e.teamId,kind:e.kind,fromMemberId:e.fromMemberId,toMemberId:e.toMemberId,senderTokenHash:e.senderTokenHash,seq:e.seq,message:e.message,createdAt:e.createdAt,expiresAt:e.expiresAt}}function Te(e){if(!(!s.parseVersioned(e,[2]).ok||!e)&&!(e.type!==h||!E(e.requestId)||!E(e.teamId)||!E(e.fromMemberId)||!E(e.toMemberId)||!k(e.senderTokenHash)||typeof e.message!=`string`||!j(e.message,S)||!O(e.createdAt)))return{type:h,version:2,requestId:e.requestId,teamId:e.teamId,fromMemberId:e.fromMemberId,toMemberId:e.toMemberId,senderTokenHash:e.senderTokenHash,message:e.message,createdAt:e.createdAt}}function Ee(e){if(!e||typeof e!=`object`||Array.isArray(e))throw o.invalidRequest(`Intercom params must be an object.`,`Use one documented intercom action shape.`);let t=e,n=re.find(e=>e===t.action);if(!n)throw new o.DoomTeamExpectedError(`unsupported_operation`,`Unsupported intercom action: ${String(t.action)}.`,!1,`Use members, send, ask, pending, or reply.`);if(!A(t.to)||!A(t.message)||!A(t.requestId))throw o.invalidRequest(`Intercom to, message and requestId values must be strings.`,`Correct the action fields and retry.`);if(t.timeoutMs!==void 0&&(!D(t.timeoutMs)||t.timeoutMs<1))throw o.invalidRequest(`Intercom timeoutMs must be a positive integer.`,`Correct timeoutMs and retry.`);let r=new Set(n===`members`||n===`pending`?[`action`]:n===`reply`?[`action`,`requestId`,`message`]:n===`ask`?[`action`,`to`,`message`,`timeoutMs`]:[`action`,`to`,`message`]),i=Object.keys(t).filter(e=>!r.has(e));if(i.length)throw o.invalidRequest(`Intercom action '${n}' does not accept: ${i.join(`, `)}.`,`Remove unknown fields and retry.`);return{action:n,...t.to===void 0?{}:{to:t.to},...t.message===void 0?{}:{message:t.message},...t.requestId===void 0?{}:{requestId:t.requestId},...t.timeoutMs===void 0?{}:{timeoutMs:t.timeoutMs}}}function G(e,t){return Se(H(I(e,t)))}function De(e,t){let n=Ce(H(L(e,t.memberId)));if(!(!n||n.memberId!==t.memberId||n.tokenHash!==t.tokenHash))return n}function Oe(e){if(e===process.pid)return!0;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function ke(e,t){return De(e,t)?.heartbeatAt??t.leftAt??t.joinedAt}function K(e,t,n){return t.active&&Oe(t.pid)&&n-ke(e,t)<=3e4}function Ae(e){l.mkdirSync(R(e,e.memberId),{recursive:!0,mode:448}),r.writePrivateAtomicJson(I(e,e.memberId),e)}function q(e,t,n){let i={version:1,memberId:t.memberId,tokenHash:t.tokenHash,pid:t.pid,heartbeatAt:n};r.writePrivateAtomicJson(L(e,t.memberId),i)}function je(e){let t=u.join(F(e.teamId),g),n;try{n=l.readdirSync(t,{withFileTypes:!0})}catch{return[]}return n.filter(e=>e.isFile()&&e.name.endsWith(y)).map(e=>Se(H(u.join(t,e.name)))).filter(e=>!!e).filter(t=>t.teamId===e.teamId&&t.rootSessionId===e.rootSessionId)}function J(e,t){return je(e).filter(n=>K(e,n,t)).sort((e,t)=>e.joinedAt-t.joinedAt||e.memberId.localeCompare(t.memberId))}function Me(e=Date.now()){let t=X();if(t)return{members:J(t,e).map(Je)}}function Ne(e,t,n){let r=0;for(let i of je(e))i.memberId!==t&&(K(e,i,n)||n-ke(e,i)<=33e4||(be(R(e,i.memberId)),U(L(e,i.memberId)),U(I(e,i.memberId)),r+=1));return r}function Pe(e){let t=e.trim();if(!t)throw Error(`A root session id is required for native team communication.`);let n={version:1,teamId:me(t),rootSessionId:t,mainMemberId:b};ye(n);let i=u.join(F(n.teamId),ne),a=W(H(i));if(a&&a.rootSessionId!==t)throw Error(`Native team identity collision detected.`);let o=Date.now();return r.writePrivateAtomicJson(i,{...n,createdAt:a?.createdAt??o,updatedAt:o}),n}function Y(e){return{[i.SUBAGENT_TEAM_ID_ENV]:e.teamId,[i.SUBAGENT_TEAM_ROOT_SESSION_ENV]:e.rootSessionId,[i.SUBAGENT_TEAM_MAIN_MEMBER_ENV]:e.mainMemberId}}function Fe(e){return{...Y(e),[i.SUBAGENT_TEAM_MEMBER_ID_ENV]:e.memberId,[i.SUBAGENT_TEAM_MEMBER_TOKEN_ENV]:e.token}}function Ie(){return{[i.SUBAGENT_TEAM_MEMBER_ID_ENV]:void 0,[i.SUBAGENT_TEAM_MEMBER_TOKEN_ENV]:void 0}}function Le(e){Object.assign(process.env,Y(e))}function Re(e){e&&process.env.PI_SUBAGENT_TEAM_ID!==e.teamId||(delete process.env[i.SUBAGENT_TEAM_ID_ENV],delete process.env[i.SUBAGENT_TEAM_ROOT_SESSION_ENV],delete process.env[i.SUBAGENT_TEAM_MAIN_MEMBER_ENV])}function X(){let e=M(i.SUBAGENT_TEAM_ID_ENV),t=M(i.SUBAGENT_TEAM_ROOT_SESSION_ENV),n=M(i.SUBAGENT_TEAM_MAIN_MEMBER_ENV);if(!e||!E(e)||!t||n!==b||e!==me(t))return;let r=W(H(u.join(F(e),ne)));if(!(!r||r.rootSessionId!==t||r.teamId!==e))return{version:1,teamId:e,rootSessionId:t,mainMemberId:n}}function ze(e){if(!e)return;let t=e.id.trim(),n=e.subject.trim();if(!t||!j(t,256))throw Error(`Native team task id must be between 1 and 256 bytes.`);if(!n||!j(n,C))throw Error(`Native team task subject must be between 1 and ${C} bytes.`);return{id:t,subject:n}}function Be(e){if(e.role===`main`)return e.root.mainMemberId;let t=e.name!==void 0;if(!t&&!e.agent)throw Error(`An intercom member needs a name or an agent to derive one from.`);let n=ge(P(e.name??e.agent??x),t);if(e.runId){let t=P(e.runId).slice(0,8),r=48-t.length-1;return`${n.slice(0,r).replace(w,``)||x}-${t}`}return e.fanoutIndex===void 0?n:he(n,e.fanoutIndex)}function Ve(e){let t=Be(e);if(!E(t))throw Error(`A safe native team member id is required.`);let n=pe(),r=N(n),i=Date.now(),a=ze(e.task),o={...e.root,memberId:t,token:n,role:e.role,...e.agent?{agent:e.agent}:{},...e.runId?{runId:e.runId}:{},...e.childIndex===void 0?{}:{childIndex:e.childIndex},...e.parentMemberId?{parentMemberId:e.parentMemberId}:{},...a?{task:a}:{}},s=G(e.root,t);s&&s.tokenHash!==r&&be(R(e.root,t));let{token:c,version:l,...u}=o,d={...u,version:1,tokenHash:r,pid:e.pid??process.pid,active:!0,joinedAt:i};Ae(d),q(e.root,d,i);let f=!1;return{context:o,dispose:()=>{if(f)return;f=!0;let n=G(e.root,t);if(!n||n.tokenHash!==r)return;let i=Date.now();Ae({...n,active:!1,leftAt:i}),q(e.root,n,i)}}}function He(){let e=X(),t=M(i.SUBAGENT_TEAM_MEMBER_ID_ENV),n=M(i.SUBAGENT_TEAM_MEMBER_TOKEN_ENV);if(!e||!t||!E(t)||!n)return;let r=G(e,t);if(!(!r||r.teamId!==e.teamId||r.rootSessionId!==e.rootSessionId)&&!(r.tokenHash!==N(n)||!r.active))return{...e,memberId:t,token:n,role:r.role,...r.agent?{agent:r.agent}:{},...r.runId?{runId:r.runId}:{},...r.childIndex===void 0?{}:{childIndex:r.childIndex},...r.parentMemberId?{parentMemberId:r.parentMemberId}:{},...r.task?{task:r.task}:{}}}function Z(e,t){let n=G(e,e.memberId);if(!n||n.tokenHash!==N(e.token)||!K(e,n,t))throw Error(`This native team member is no longer active.`);return n}function Ue(e,t,n){let r=t?.trim();if(!r)throw o.invalidRequest(`to is required for intercom send and ask.`,`Provide an explicit recipient.`);let i=J(e,n).filter(t=>t.memberId!==e.memberId),a=P(r),s=i.find(e=>e.memberId===r||e.memberId===a);if(s)return s;let c=r.toLowerCase(),l=i.filter(e=>e.agent?.toLowerCase()===c||e.runId?.toLowerCase()===c||c===b&&e.role===`main`);if(l.length===1)return l[0];throw l.length>1?new o.DoomTeamExpectedError(`recipient_ambiguous`,`Multiple active intercom members match '${r}': ${l.map(e=>e.memberId).join(`, `)}.`,!1,`Retry with one exact member id.`):new o.DoomTeamExpectedError(`recipient_not_found`,`Active intercom member '${r}' was not found.`,!0,`Call intercom({"action":"members"}) and retry with an active member id.`)}function We(e){let t=e?.trim();if(!t)throw o.invalidRequest(`message is required for intercom communication.`,`Provide a nonblank message.`);if(!j(t,S))throw o.invalidRequest(`Intercom message exceeds 64 KiB.`,`Shorten the message and retry.`);return t}function Q(e,t,n){let r=G(e,t);return!!(r&&r.tokenHash===n)}function Ge(e,t,n){let r=R(e,e.memberId),i;try{i=l.readdirSync(r,{withFileTypes:!0})}catch{return{messages:[],foreignFiles:[]}}let a=[],o=[];for(let s of i){if(!s.isFile()||!s.name.endsWith(y)||n?.(s.name))continue;let i=u.join(r,s.name),c=we(H(i));if(!c){U(i);continue}if(c.teamId!==e.teamId||c.toMemberId!==e.memberId){o.push(s.name);continue}if(c.expiresAt<t||!Q(e,c.fromMemberId,c.senderTokenHash)){U(i);continue}a.push(c)}return{messages:Ke(a),foreignFiles:o}}function Ke(e){let t=new Map;for(let n of e){let e=t.get(n.fromMemberId);e?e.push(n):t.set(n.fromMemberId,[n])}let n=[];for(let e of t.values())e.sort((e,t)=>e.seq-t.seq),n.push(e);let r=[];for(;;){let e,t;for(let r of n){let n=r[0];n&&(!t||n.createdAt<t.createdAt||n.createdAt===t.createdAt&&n.fromMemberId<t.fromMemberId)&&(e=r,t=n)}if(!e||!t)break;e.shift(),r.push(t)}return r}function qe(e){let t=e.role===`main`?b:e.agent??e.memberId,n=e.runId?` [${e.runId}]`:``,r=e.task?`, task ${e.task.id}: ${e.task.subject}`:``;return`- ${e.memberId}: ${t}${n}${r}`}function Je(e){return{name:e.memberId,role:e.role,...e.agent?{agent:e.agent}:{},...e.runId?{runId:e.runId}:{},...e.task?{task:e.task}:{}}}function Ye(e,t){return new Promise((n,r)=>{if(t?.aborted){r(Error(`Native team request cancelled.`));return}let i,a=()=>{i&&clearTimeout(i),t?.removeEventListener(`abort`,o)},o=()=>{a(),r(Error(`Native team request cancelled.`))};i=setTimeout(()=>{a(),n()},e),t?.addEventListener(`abort`,o,{once:!0})})}function Xe(e,t){let n=G(e,t.fromMemberId),r=`${t.fromMemberId}${n?.agent?` (${n.agent})`:``}`,i=n?.task?`, task ${n.task.id}`:``,a=[`${t.kind===`ask`?`Question`:`Message`} from ${r}${i}.`];return a.push(``,t.message),t.kind===`ask`&&a.push(``,`Reply with ${p}({ action: "reply", requestId: "${t.id}", message: "..." }).`),a.join(`
|
|
2
|
+
`)}function Ze(e,t){try{return e.getAllTools().some(e=>e.name===t)}catch{return!1}}var Qe=class{context;ownedMembershipDispose;poller;lastHeartbeatAt=0;lastGcAt=0;seenFiles=new c.BoundedKeySet(1024);deliveryAttempts=new n.LruCache(256);undeliverableMessages=[];outboundSeq=0;constructor(e,t){if(this.pi=e,this.options=t,Ze(e,`intercom`))throw Error(`[tool_conflict] A foreign '${p}' tool is already registered. Recovery: disable the competing extension and reload Doom Team.`);e.registerTool(this.buildTool())}current(){return this.context}undeliverable(){return this.undeliverableMessages}bindMainSession(e){let t=Pe(e);Le(t);let n=Ve({root:t,role:`main`});return this.startBinding(n.context,n.dispose)}bindChildFromEnvironment(){let e=He();if(e)return this.context?.memberId===e.memberId&&this.context.token===e.token?this.context:this.startBinding(e)}dispose(){let e=this.context;this.stopBinding(),e?.role===`main`&&Re(e)}startBinding(e,t){return this.stopBinding(),this.context=e,this.ownedMembershipDispose=t,this.poll(),this.poller=setInterval(()=>{this.poll()},this.options.pollIntervalMs),this.poller.unref?.(),e}stopBinding(){this.poller&&clearInterval(this.poller),this.poller=void 0,this.ownedMembershipDispose?.(),this.ownedMembershipDispose=void 0,this.seenFiles.clear(),this.deliveryAttempts.clear(),this.lastHeartbeatAt=0,this.lastGcAt=0,this.outboundSeq=0,this.context=void 0}poll(){let e=this.context;if(!e)return;let t=this.options.now();this.heartbeat(e,t),this.collectGarbageIfDue(e,t);let n=Ge(e,t,e=>this.seenFiles.has(e));for(let e of n.foreignFiles)this.seenFiles.add(e);for(let t of n.messages)this.deliverOnce(e,t)}deliverOnce(e,t){let n=z(t.id);try{this.deliver(e,t)}catch(r){let i=(this.deliveryAttempts.get(n)??0)+1;if(i<this.options.maxDeliveryAttempts){this.deliveryAttempts.set(n,i);return}this.deliveryAttempts.delete(n),this.seenFiles.add(n),this.reportUndeliverable(e,t,i,r);return}this.seenFiles.add(n),this.deliveryAttempts.delete(n),r.writePrivateAtomicJson(V(e,t.fromMemberId,t.id),{version:1,messageId:t.id,state:T,deliveredAt:this.options.now()}),t.kind===`send`&&U(B(e,e.memberId,t.id))}deliver(e,t){let n=Xe(e,t);if(e.role===`subagent`){this.pi.sendUserMessage(n,{deliverAs:`steer`});return}this.pi.sendMessage({customType:`intercom_message`,content:n,display:!0,details:{id:t.id,kind:t.kind,from:t.fromMemberId,to:t.toMemberId,seq:t.seq}},{triggerTurn:!0,deliverAs:`steer`})}reportUndeliverable(e,t,n,i){let a={messageId:t.id,fromMemberId:t.fromMemberId,kind:t.kind,attempts:n,reason:fe(i),at:this.options.now()};for(this.undeliverableMessages.push(a),r.writePrivateAtomicJson(V(e,t.fromMemberId,t.id),{version:1,messageId:t.id,state:se,reason:a.reason,failedAt:a.at});this.undeliverableMessages.length>32;)this.undeliverableMessages.shift();try{this.pi.sendMessage({customType:`intercom_undeliverable`,content:`Native team message ${t.id} from ${t.fromMemberId} could not be delivered after ${n} attempts: ${a.reason}`,display:!0,details:{...a}},{triggerTurn:!0,deliverAs:`steer`})}catch{}}heartbeat(e,t){if(t-this.lastHeartbeatAt<this.options.heartbeatIntervalMs)return;let n=G(e,e.memberId);!n||n.tokenHash!==N(e.token)||!n.active||(this.lastHeartbeatAt=t,q(e,n,t))}collectGarbageIfDue(e,t){if(!(t-this.lastGcAt<this.options.gcIntervalMs)){this.lastGcAt=t;try{Ne(e,e.memberId,t)}catch(n){for(this.undeliverableMessages.push({messageId:``,fromMemberId:e.memberId,kind:`send`,attempts:0,reason:`Native team directory sweep failed: ${fe(n)}`,at:t});this.undeliverableMessages.length>32;)this.undeliverableMessages.shift()}}}nextSeq(){return this.outboundSeq+=1,this.outboundSeq}queueMessage(e,t,n,i,a,o){if(Z(e,a),!K(e,t,a))throw Error(`Native team member '${t.memberId}' is no longer active.`);let s={type:m,version:2,id:o,teamId:e.teamId,kind:n,fromMemberId:e.memberId,toMemberId:t.memberId,senderTokenHash:N(e.token),seq:this.nextSeq(),message:i,createdAt:a,expiresAt:a+864e5};return l.mkdirSync(R(e,t.memberId),{recursive:!0,mode:448}),r.writePrivateAtomicJson(B(e,t.memberId,s.id),s),s}replyToRequest(e,t,n,i){if(!t||!E(t))throw Error(`requestId must be a valid intercom request id.`);Z(e,i);let a=B(e,e.memberId,t),s=we(H(a));if(!s||s.kind!==`ask`||s.teamId!==e.teamId||s.toMemberId!==e.memberId||!Q(e,s.fromMemberId,s.senderTokenHash))throw new o.DoomTeamExpectedError(`recipient_not_found`,`No pending intercom ask matches requestId '${t}'.`,!1,`Call intercom({"action":"pending"}) and retry with an exact requestId.`);let c={type:h,version:2,requestId:t,teamId:e.teamId,fromMemberId:e.memberId,toMemberId:s.fromMemberId,senderTokenHash:N(e.token),message:n,createdAt:i};return r.writePrivateAtomicJson(_e(e,t),c),U(a),this.seenFiles.delete(z(t)),c}async waitForReply(e,t,n,r,i){let a=_e(e,n.id),s=this.options.now()+(i??this.options.askTimeoutMs);for(;this.options.now()<=s;){if(r?.aborted)throw Error(`Native team request cancelled.`);let i=Te(H(a));if(i&&i.teamId===e.teamId&&i.requestId===n.id&&i.fromMemberId===t.memberId&&i.toMemberId===e.memberId&&Q(e,i.fromMemberId,i.senderTokenHash))return U(a),i;let s=G(e,t.memberId);if(!s||!K(e,s,this.options.now()))throw new o.DoomTeamExpectedError(`communication_unavailable`,`Intercom member '${t.memberId}' became unreachable before replying.`,!0,`Call intercom({"action":"members"}) and decide whether to retry with an active member.`);await Ye(this.options.replyPollIntervalMs,r)}throw new o.DoomTeamExpectedError(`reply_timeout`,`Timed out waiting for intercom member '${t.memberId}' to reply.`,!0,`Check member status before deciding whether to ask again.`)}buildTool(){return{name:p,label:`Intercom`,description:`Communicate with active agents in this root session. Use members, send, ask, pending, or reply. The stable root identity is main.`,promptGuidelines:[`Send only new progress, blockers, or decisions. Do not repeat the task brief, sender task, or delegation instructions because the recipient already has them.`],parameters:ce,execute:async(e,t,n,r)=>{let i=this.context;if(!i)throw new o.DoomTeamExpectedError(`communication_unavailable`,`Intercom is not active for this session.`,!0,`Wait for session startup or reload Doom Team.`);let a=Ee(t),s=this.options.now();if(Z(i,s),a.action===`members`){let e=J(i,s);return{content:[{type:`text`,text:e.length?e.map(qe).join(`
|
|
3
|
+
`):`No active members.`}],details:{members:e.map(Je)}}}if(a.action===`pending`){let e=Ge(i,s).messages.filter(e=>e.kind===`ask`),t=e.map(e=>`- ${e.id}: from ${e.fromMemberId}. Reply with ${p}({ action: "reply", requestId: "${e.id}", message: "..." }).`);return{content:[{type:`text`,text:t.length?t.join(`
|
|
4
|
+
`):`No pending native team asks.`}],details:{pending:e.map(e=>({id:e.id,from:e.fromMemberId,message:e.message}))}}}let c=We(a.message);if(a.action===`reply`){let e=this.replyToRequest(i,a.requestId,c,s);return{content:[{type:`text`,text:`Replied to native team request ${e.requestId}.`}],details:{requestId:e.requestId,to:e.toMemberId}}}let l=Ue(i,a.to,s);a.action===`ask`&&r?.({content:[{type:`text`,text:`Waiting for ${l.memberId} to reply...`}],details:{action:`ask`,to:l.memberId,partial:!0}});let u=ve(i.memberId,e),d=H(V(i,i.memberId,u));if(d?.state===se)throw new o.DoomTeamExpectedError(`delivery_unconfirmed`,`Intercom message ${u} failed: ${typeof d.reason==`string`?d.reason:`unknown error`}`,!1,`Call intercom({"action":"members"}) and do not resend automatically.`);if(a.action===`send`&&d?.state===T)return{content:[{type:`text`,text:`Message ${u} delivered to ${l.memberId}.`}],details:{state:T,delivered:!0,messageId:u,to:l.memberId}};let f=this.queueMessage(i,l,a.action,c,s,u);if(a.action===`send`)return{content:[{type:`text`,text:`Message ${f.id} queued for ${l.memberId}; delivery is not yet confirmed. Do not resend.`}],details:{state:`queued`,delivered:!1,messageId:f.id,to:l.memberId,seq:f.seq}};try{let e=await this.waitForReply(i,l,f,n,a.timeoutMs);return{content:[{type:`text`,text:`Reply from ${l.memberId}:\n${e.message}`}],details:{requestId:f.id,from:l.memberId,reply:e.message}}}finally{U(B(i,l.memberId,f.id))}}}}};let $=class{runtimes=new WeakMap;pollIntervalMs=250;replyPollIntervalMs=250;heartbeatIntervalMs=5e3;gcIntervalMs=6e4;askTimeoutMs=6e5;maxDeliveryAttempts=5;now(){return Date.now()}createRuntime(e){let t=this.runtimes.get(e);if(t)return t;let n=new Qe(e,{pollIntervalMs:this.pollIntervalMs,replyPollIntervalMs:this.replyPollIntervalMs,heartbeatIntervalMs:this.heartbeatIntervalMs,gcIntervalMs:this.gcIntervalMs,askTimeoutMs:this.askTimeoutMs,maxDeliveryAttempts:this.maxDeliveryAttempts,now:()=>this.now()});return this.runtimes.set(e,n),e.on(`session_shutdown`,()=>{this.runtimes.get(e)?.dispose()}),n}registerClient(e){a.tryCurrentSessionScope()&&He()&&this.createRuntime(e).bindChildFromEnvironment()}};$=t.__decorate([(0,d.injectable)()],$),exports.NATIVE_TEAM_TOOL_NAME=p,Object.defineProperty(exports,`NativeTeamChannelService`,{enumerable:!0,get:function(){return $}}),exports.clearNativeTeamMemberEnvironment=Ie,exports.nativeTeamMemberEnvironment=Fe,exports.nativeTeamRootEnvironment=Y,exports.readActiveNativeTeamSnapshot=Me,exports.readNativeTeamRootFromEnvironment=X,exports.registerNativeTeamMember=Ve;
|
|
5
|
+
//# sourceMappingURL=nativeTeamChannel.cjs.map
|