@ashx-j/lunr-dev 0.2.13-dev.4.1 → 0.2.13-dev.7.1

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.
Files changed (208) hide show
  1. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  2. package/dist/builtin-extensions/ashxj-tui.js +4 -4
  3. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  4. package/dist/builtin-extensions/index.d.ts.map +1 -1
  5. package/dist/builtin-extensions/index.js +2 -0
  6. package/dist/builtin-extensions/index.js.map +1 -1
  7. package/dist/builtin-extensions/lunr-settings-tools.d.ts +4 -0
  8. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +1 -0
  9. package/dist/builtin-extensions/lunr-settings-tools.js +120 -0
  10. package/dist/builtin-extensions/lunr-settings-tools.js.map +1 -0
  11. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts +2 -2
  12. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts.map +1 -1
  13. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.js.map +1 -1
  14. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js +3 -3
  16. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts +2 -2
  18. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +2 -1
  23. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +5 -11
  25. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +12 -15
  27. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
  29. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +14 -27
  31. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +6 -4
  34. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +2 -1
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +6 -4
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js +4 -2
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js +3 -35
  46. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +5 -12
  49. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +14 -31
  52. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +2 -0
  54. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +28 -22
  56. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  58. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +9 -4
  62. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +2 -2
  66. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +4 -7
  68. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts +3 -3
  72. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js +7 -6
  74. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.d.ts.map +1 -1
  76. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js +3 -3
  77. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js.map +1 -1
  78. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +1 -1
  79. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +6 -4
  81. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  82. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  84. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +15 -10
  85. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.d.ts.map +1 -1
  87. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js +3 -2
  88. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js.map +1 -1
  89. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -2
  90. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +75 -43
  92. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  93. package/dist/catalog/models.json +1 -1
  94. package/dist/catalog/providers/amazon-bedrock.json +1 -1
  95. package/dist/catalog/providers/anthropic.json +1 -1
  96. package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
  97. package/dist/catalog/providers/fireworks.json +1 -1
  98. package/dist/catalog/providers/github-copilot.json +1 -1
  99. package/dist/catalog/providers/google-vertex.json +1 -1
  100. package/dist/catalog/providers/google.json +1 -1
  101. package/dist/catalog/providers/huggingface.json +1 -1
  102. package/dist/catalog/providers/nvidia.json +1 -1
  103. package/dist/catalog/providers/opencode-go.json +1 -1
  104. package/dist/catalog/providers/opencode.json +1 -1
  105. package/dist/catalog/providers/openrouter.json +1 -1
  106. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  107. package/dist/catalog/publication.json +3 -3
  108. package/dist/core/agent-session-runtime.d.ts +5 -1
  109. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  110. package/dist/core/agent-session-runtime.js +7 -2
  111. package/dist/core/agent-session-runtime.js.map +1 -1
  112. package/dist/core/agent-session.d.ts +2 -0
  113. package/dist/core/agent-session.d.ts.map +1 -1
  114. package/dist/core/agent-session.js +20 -5
  115. package/dist/core/agent-session.js.map +1 -1
  116. package/dist/core/context-breakdown.d.ts +2 -0
  117. package/dist/core/context-breakdown.d.ts.map +1 -1
  118. package/dist/core/context-breakdown.js +6 -2
  119. package/dist/core/context-breakdown.js.map +1 -1
  120. package/dist/core/injected-prompt.d.ts +3 -3
  121. package/dist/core/injected-prompt.d.ts.map +1 -1
  122. package/dist/core/injected-prompt.js +2 -7
  123. package/dist/core/injected-prompt.js.map +1 -1
  124. package/dist/core/large-subagent-launch.d.ts +13 -0
  125. package/dist/core/large-subagent-launch.d.ts.map +1 -0
  126. package/dist/core/large-subagent-launch.js +54 -0
  127. package/dist/core/large-subagent-launch.js.map +1 -0
  128. package/dist/core/model-instructions.d.ts +24 -0
  129. package/dist/core/model-instructions.d.ts.map +1 -0
  130. package/dist/core/model-instructions.js +123 -0
  131. package/dist/core/model-instructions.js.map +1 -0
  132. package/dist/core/permissions.d.ts +11 -10
  133. package/dist/core/permissions.d.ts.map +1 -1
  134. package/dist/core/permissions.js +61 -45
  135. package/dist/core/permissions.js.map +1 -1
  136. package/dist/core/plan-mode.d.ts.map +1 -1
  137. package/dist/core/plan-mode.js +10 -1
  138. package/dist/core/plan-mode.js.map +1 -1
  139. package/dist/core/resource-loader.d.ts +3 -0
  140. package/dist/core/resource-loader.d.ts.map +1 -1
  141. package/dist/core/resource-loader.js +13 -4
  142. package/dist/core/resource-loader.js.map +1 -1
  143. package/dist/core/runtime-bridges.d.ts +4 -0
  144. package/dist/core/runtime-bridges.d.ts.map +1 -0
  145. package/dist/core/runtime-bridges.js +16 -0
  146. package/dist/core/runtime-bridges.js.map +1 -0
  147. package/dist/core/sdk.d.ts.map +1 -1
  148. package/dist/core/sdk.js +1 -0
  149. package/dist/core/sdk.js.map +1 -1
  150. package/dist/core/session-manager.d.ts.map +1 -1
  151. package/dist/core/session-manager.js +17 -16
  152. package/dist/core/session-manager.js.map +1 -1
  153. package/dist/core/settings-manager.d.ts +13 -0
  154. package/dist/core/settings-manager.d.ts.map +1 -1
  155. package/dist/core/settings-manager.js +32 -0
  156. package/dist/core/settings-manager.js.map +1 -1
  157. package/dist/core/settings-tools-bridge.d.ts +35 -0
  158. package/dist/core/settings-tools-bridge.d.ts.map +1 -0
  159. package/dist/core/settings-tools-bridge.js +56 -0
  160. package/dist/core/settings-tools-bridge.js.map +1 -0
  161. package/dist/core/swarm.d.ts +0 -31
  162. package/dist/core/swarm.d.ts.map +1 -1
  163. package/dist/core/swarm.js +2 -76
  164. package/dist/core/swarm.js.map +1 -1
  165. package/dist/core/system-prompt.d.ts.map +1 -1
  166. package/dist/core/system-prompt.js +1 -1
  167. package/dist/core/system-prompt.js.map +1 -1
  168. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  169. package/dist/gateway/agent-bridge.js +3 -2
  170. package/dist/gateway/agent-bridge.js.map +1 -1
  171. package/dist/gateway/approval.d.ts.map +1 -1
  172. package/dist/gateway/approval.js +4 -3
  173. package/dist/gateway/approval.js.map +1 -1
  174. package/dist/gateway/cron.d.ts.map +1 -1
  175. package/dist/gateway/cron.js +3 -2
  176. package/dist/gateway/cron.js.map +1 -1
  177. package/dist/gateway/router.d.ts +1 -1
  178. package/dist/gateway/router.d.ts.map +1 -1
  179. package/dist/gateway/router.js +1 -1
  180. package/dist/gateway/router.js.map +1 -1
  181. package/dist/main.d.ts.map +1 -1
  182. package/dist/main.js +3 -9
  183. package/dist/main.js.map +1 -1
  184. package/dist/migrations.d.ts.map +1 -1
  185. package/dist/migrations.js +4 -0
  186. package/dist/migrations.js.map +1 -1
  187. package/dist/modes/interactive/components/injected-prompt-message.d.ts +1 -1
  188. package/dist/modes/interactive/components/injected-prompt-message.d.ts.map +1 -1
  189. package/dist/modes/interactive/components/injected-prompt-message.js +1 -1
  190. package/dist/modes/interactive/components/injected-prompt-message.js.map +1 -1
  191. package/dist/modes/interactive/components/settings-selector.d.ts +8 -1
  192. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/settings-selector.js +61 -1
  194. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  195. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  196. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  197. package/dist/modes/interactive/interactive-mode.js +31 -23
  198. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  199. package/dist/startup/interactive-shell.d.ts.map +1 -1
  200. package/dist/startup/interactive-shell.js +2 -1
  201. package/dist/startup/interactive-shell.js.map +1 -1
  202. package/docs/features.md +7 -6
  203. package/docs/quickstart.md +3 -2
  204. package/docs/settings.md +3 -1
  205. package/docs/termux.md +1 -1
  206. package/docs/usage.md +2 -1
  207. package/examples/extensions/subagent/README.md +1 -1
  208. package/package.json +4 -4
@@ -72,6 +72,8 @@ export interface ResolveSubagentModelOverrideOptions {
72
72
  export declare function resolveSubagentModelOverride(requestedModel: string | boolean | undefined, parentModel: ParentModel | undefined, availableModels: AvailableModelInfo[] | undefined, preferredProvider?: string, options?: ResolveSubagentModelOverrideOptions): string | undefined;
73
73
  export declare function resolveEffectiveSubagentModel(explicitModel: string | boolean | undefined, agentModel: string | boolean | undefined, parentModel: ParentModel | undefined, availableModels: AvailableModelInfo[] | undefined, preferredProvider?: string, options?: Omit<ResolveSubagentModelOverrideOptions, "source">): string | undefined;
74
74
  export declare function resolveTierModelOverride(tier: unknown): string | undefined;
75
+ /** Resolve a required tier and prove its configured model is available to this session. */
76
+ export declare function resolveRequiredTierModel(tier: unknown, availableModels: AvailableModelInfo[] | undefined, preferredProvider?: string): string;
75
77
  /**
76
78
  * Capture how a child model was selected from the original requested params.
77
79
  * Must run before callers replace `model` with a resolved override.
@@ -1 +1 @@
1
- {"version":3,"file":"model-fallback.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ModelInfo as AvailableModelInfo } from \"../../shared/model-info.ts\";\nimport type { ChildTier, ModelSelection, Usage } from \"../../shared/types.ts\";\nimport { checkModelScope, type ModelScopeConfig, type ModelScopeViolation, type ModelSource } from \"./model-scope.ts\";\nimport { applyThinkingSuffix } from \"./pi-args.ts\";\n\nexport type { AvailableModelInfo };\n\ninterface ModelAttemptSummary {\n\tmodel: string;\n\tsuccess: boolean;\n\texitCode?: number | null;\n\terror?: string;\n\tusage?: Usage;\n}\n\nexport function splitThinkingSuffix(model: string): { baseModel: string; thinkingSuffix: string } {\n\tconst colonIdx = model.lastIndexOf(\":\");\n\tif (colonIdx === -1) return { baseModel: model, thinkingSuffix: \"\" };\n\treturn {\n\t\tbaseModel: model.substring(0, colonIdx),\n\t\tthinkingSuffix: model.substring(colonIdx),\n\t};\n}\n\n/** Sentinel model value requesting that a subagent inherit the parent session's model. */\nexport const INHERIT_MODEL = \"inherit\";\n\n/** Minimal shape of the parent session's in-memory model (`ctx.model`). */\nexport interface ParentModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Normalize a model id or provider segment for fuzzy comparison: case-fold,\n * treat dots/underscores as dashes (so `4.5` matches `4-5`), and collapse\n * repeated separators. Pure.\n */\nexport function normalizeModelSegment(segment: string): string {\n\treturn segment\n\t\t.toLowerCase()\n\t\t.replace(/[._]+/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nfunction isPlausibleDateStamp(year: string, month: string, day: string): boolean {\n\tconst yyyy = Number(year);\n\tconst mm = Number(month);\n\tconst dd = Number(day);\n\treturn yyyy >= 1900 && yyyy <= 2099 && mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31;\n}\n\n/** Drop a trailing date stamp (`-20251001` or `-2025-10-01`) so dated and undated ids match. Pure. */\nfunction stripTrailingDateStamp(segment: string): string {\n\tconst dashed = /^(.*)-(\\d{4})-(\\d{2})-(\\d{2})$/.exec(segment);\n\tif (dashed && isPlausibleDateStamp(dashed[2]!, dashed[3]!, dashed[4]!)) return dashed[1]!;\n\tconst compact = /^(.*)-(\\d{4})(\\d{2})(\\d{2})$/.exec(segment);\n\tif (compact && isPlausibleDateStamp(compact[2]!, compact[3]!, compact[4]!)) return compact[1]!;\n\treturn segment;\n}\n\nfunction resolveBaseModelCandidate(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (baseModel.includes(\"/\")) {\n\t\tconst exact = availableModels.find((entry) => entry.fullId === baseModel);\n\t\tif (exact) return exact.fullId;\n\t} else {\n\t\tconst exactMatches = availableModels.filter((entry) => entry.id === baseModel);\n\t\tif (preferredProvider) {\n\t\t\tconst preferredMatch = exactMatches.find((entry) => entry.provider === preferredProvider);\n\t\t\tif (preferredMatch) return preferredMatch.fullId;\n\t\t}\n\t\tif (exactMatches.length === 1) return exactMatches[0]!.fullId;\n\t}\n\n\treturn fuzzyResolveModel(baseModel, availableModels, preferredProvider);\n}\n\n/**\n * Fuzzy-resolve a base model id (thinking suffix already stripped) against the\n * registry, tolerating separator, case, and optional date-stamp differences so\n * users do not have to spell provider/model exactly. A qualified `provider/id`\n * query only matches within the named provider — this never silently switches\n * providers for security/cost-sensitive configs. Returns the matched `fullId`,\n * or `undefined` when there is no match or the match is ambiguous across\n * providers (and no `preferredProvider` disambiguates). Pure.\n */\nexport function fuzzyResolveModel(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tlet queryProvider: string | undefined;\n\tlet queryIdRaw = baseModel;\n\tconst slashIdx = baseModel.indexOf(\"/\");\n\tif (slashIdx !== -1) {\n\t\tqueryProvider = normalizeModelSegment(baseModel.slice(0, slashIdx));\n\t\tqueryIdRaw = baseModel.slice(slashIdx + 1);\n\t} else {\n\t\tconst providerSeparators = [\":\", \".\"];\n\t\tfor (const separator of providerSeparators) {\n\t\t\tconst separatorIdx = baseModel.indexOf(separator);\n\t\t\tif (separatorIdx <= 0) continue;\n\t\t\tconst providerPart = normalizeModelSegment(baseModel.slice(0, separatorIdx));\n\t\t\tif (!availableModels.some((entry) => normalizeModelSegment(entry.provider) === providerPart)) continue;\n\t\t\tqueryProvider = providerPart;\n\t\t\tqueryIdRaw = baseModel.slice(separatorIdx + 1);\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst queryId = normalizeModelSegment(queryIdRaw);\n\tconst queryIdNoDate = stripTrailingDateStamp(queryId);\n\n\tconst candidates = availableModels.filter((entry) => {\n\t\tconst entryId = normalizeModelSegment(entry.id);\n\t\tif (entryId !== queryId && stripTrailingDateStamp(entryId) !== queryIdNoDate) return false;\n\t\tif (queryProvider !== undefined && normalizeModelSegment(entry.provider) !== queryProvider) return false;\n\t\treturn true;\n\t});\n\tif (candidates.length === 0) return undefined;\n\tif (preferredProvider) {\n\t\tconst preferredProviderNorm = normalizeModelSegment(preferredProvider);\n\t\tconst preferred = candidates.find((entry) => normalizeModelSegment(entry.provider) === preferredProviderNorm);\n\t\tif (preferred) return preferred.fullId;\n\t}\n\tif (candidates.length === 1) return candidates[0]!.fullId;\n\treturn undefined;\n}\n\n/**\n * Resolve a possibly-loose model id to a canonical `provider/id` (plus any\n * thinking suffix). Exact registry matches win; fuzzy normalization\n * (separator/case/date-stamp via {@link fuzzyResolveModel}) is a fallback so\n * spelling differences still resolve. Never switches providers for a qualified\n * query. Pure.\n */\nexport function resolveModelCandidate(\n\tmodel: string | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (!model) return undefined;\n\tif (!availableModels || availableModels.length === 0) return model;\n\n\tconst resolvedWhole = resolveBaseModelCandidate(model, availableModels, preferredProvider);\n\tif (resolvedWhole) return resolvedWhole;\n\n\tconst { baseModel, thinkingSuffix } = splitThinkingSuffix(model);\n\tif (!thinkingSuffix) return model;\n\tconst resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);\n\tif (resolvedBase) return `${resolvedBase}${thinkingSuffix}`;\n\treturn model;\n}\n\nexport interface ResolveSubagentModelOverrideOptions {\n\t/** When set with `enforce: true`, out-of-scope models are rejected. */\n\tscope?: ModelScopeConfig;\n\t/** Origin of the requested model: explicit caller-supplied (hard error) vs inherited (warn). Defaults to `\"inherited\"`. */\n\tsource?: ModelSource;\n\t/** Called for warn-severity violations instead of `console.warn`. */\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nfunction defaultScopeWarn(violation: ModelScopeViolation): void {\n\tconsole.warn(`[pi-subagents] ${violation.message}`);\n}\n\n/**\n * Resolve the `--model` override passed to a spawned subagent.\n *\n * When no model is requested (`undefined`, `false`, empty, or the `\"inherit\"`\n * sentinel), the child must inherit the parent session's *in-memory* model\n * (`provider/id`) instead of being left to resolve its own model. Without an\n * explicit `provider/id`, the child falls back to the global\n * `~/.pi/agent/settings.json` default, which is shared across every open PI\n * session — so a different session that last changed its model in the TUI would\n * silently contaminate this session's subagents (see issue #266). Passing an\n * explicit `provider/id` keeps each session's children isolated to that\n * session's model.\n *\n * An explicitly requested model string is resolved via {@link resolveModelCandidate}.\n * When `options.scope.enforce` is on, an out-of-scope resolved model throws for\n * an explicit (`source: \"explicit\"`) request and warns for an inherited one.\n */\nexport function resolveSubagentModelOverride(\n\trequestedModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: ResolveSubagentModelOverrideOptions,\n): string | undefined {\n\tconst trimmed = typeof requestedModel === \"string\" ? requestedModel.trim() : \"\";\n\tconst explicit = trimmed && trimmed !== INHERIT_MODEL ? trimmed : undefined;\n\tlet resolved: string | undefined;\n\tif (explicit === undefined) {\n\t\tresolved = parentModel ? `${parentModel.provider}/${parentModel.id}` : undefined;\n\t} else {\n\t\tresolved = resolveModelCandidate(explicit, availableModels, preferredProvider);\n\t}\n\tif (resolved && options?.scope?.enforce) {\n\t\tconst source: ModelSource = explicit === undefined ? \"inherited\" : (options.source ?? \"inherited\");\n\t\tconst violation = checkModelScope(resolved, options.scope, source);\n\t\tif (violation) {\n\t\t\tif (violation.severity === \"error\") throw new Error(violation.message);\n\t\t\t(options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t}\n\treturn resolved;\n}\n\nexport function resolveEffectiveSubagentModel(\n\texplicitModel: string | boolean | undefined,\n\tagentModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: Omit<ResolveSubagentModelOverrideOptions, \"source\">,\n): string | undefined {\n\tconst resolved = resolveSubagentModelOverride(\n\t\texplicitModel ?? agentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: explicitModel !== undefined ? \"explicit\" : \"inherited\" },\n\t);\n\tif (resolved || explicitModel === undefined) return resolved;\n\treturn resolveSubagentModelOverride(\n\t\tagentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: \"inherited\" },\n\t);\n}\n\n// lunr: model tier bridge — resolve a subagent `tier` param through lunR core's\n// model-tiers global (Symbol.for(\"@lunr/model-tiers\")). Absent bridge, disabled tier\n// mode, unknown tier, or unconfigured tier all resolve to undefined so callers fall\n// back to normal inherit behavior. Never throws.\nexport function resolveTierModelOverride(tier: unknown): string | undefined {\n\tif (typeof tier !== \"string\" || !tier.trim()) return undefined;\n\tconst tierName = tier.trim();\n\ttry {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[Symbol.for(\"@lunr/model-tiers\")] as\n\t\t\t| { getTierModel?: (tier: string) => unknown; isTierModeEnabled?: () => unknown }\n\t\t\t| undefined;\n\t\tif (typeof bridge?.isTierModeEnabled !== \"function\" || typeof bridge?.getTierModel !== \"function\") {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (bridge.isTierModeEnabled() !== true) return undefined;\n\t\tconst model = bridge.getTierModel(tierName);\n\t\tif (typeof model !== \"string\" || !model.trim()) {\n\t\t\tif (process.env.PI_SUBAGENTS_DEBUG) {\n\t\t\t\tconsole.warn(`[pi-subagents] model tier '${tierName}' has no configured model; inheriting parent model.`);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\tconst trimmed = model.trim();\n\t\tconst thinking =\n\t\t\ttypeof bridge.getTierThinking === \"function\" ? bridge.getTierThinking(tierName) : undefined;\n\t\tconst parent = typeof bridge.getParentThinking === \"function\" ? bridge.getParentThinking() : undefined;\n\t\tconst level = (typeof thinking === \"string\" && thinking ? thinking : undefined) ?? (typeof parent === \"string\" && parent ? parent : undefined);\n\t\tif (!level) return trimmed;\n\t\treturn applyThinkingSuffix(trimmed, level, true) ?? trimmed;\n\t} catch (error) {\n\t\tif (process.env.PI_SUBAGENTS_DEBUG) {\n\t\t\tconsole.warn(\n\t\t\t\t`[pi-subagents] model tier resolution failed for '${tierName}': ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n}\n\nfunction requestedModelString(model: unknown): string | undefined {\n\treturn typeof model === \"string\" && model.trim() && model.trim() !== INHERIT_MODEL ? model.trim() : undefined;\n}\n\nfunction requestedTier(tier: unknown): ChildTier | undefined {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\" ? tier : undefined;\n}\n\n/**\n * Capture how a child model was selected from the original requested params.\n * Must run before callers replace `model` with a resolved override.\n * Explicit model wins; a tier only counts when it actually resolves.\n */\nexport function captureModelSelection(input: { model?: unknown; tier?: unknown }): ModelSelection {\n\tif (requestedModelString(input.model)) return { kind: \"model\" };\n\tconst tier = requestedTier(input.tier);\n\tif (tier && resolveTierModelOverride(tier)) return { kind: \"tier\", tier };\n\treturn { kind: \"inherit\" };\n}\n\nexport interface BuildModelCandidatesOptions {\n\t/** Fallback models are inherited agent config and warn, rather than error, when out of scope. */\n\tscope?: ModelScopeConfig;\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nexport function buildModelCandidates(\n\tprimaryModel: string | undefined,\n\tfallbackModels: string[] | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: BuildModelCandidatesOptions,\n): string[] {\n\tconst seen = new Set<string>();\n\tconst candidates: string[] = [];\n\tconst rawCandidates = [primaryModel, ...(fallbackModels ?? [])];\n\tfor (let index = 0; index < rawCandidates.length; index++) {\n\t\tconst raw = rawCandidates[index];\n\t\tif (!raw) continue;\n\t\tconst normalized = resolveModelCandidate(raw.trim(), availableModels, preferredProvider);\n\t\tif (!normalized || seen.has(normalized)) continue;\n\t\tif (index > 0 && options?.scope?.enforce) {\n\t\t\tconst violation = checkModelScope(normalized, options.scope, \"inherited\");\n\t\t\tif (violation) (options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t\tseen.add(normalized);\n\t\tcandidates.push(normalized);\n\t}\n\treturn candidates;\n}\n\nconst RETRYABLE_MODEL_FAILURE_PATTERNS = [\n\t/rate\\s*limit/i,\n\t/too many requests/i,\n\t/\\b429\\b/,\n\t/quota/i,\n\t/billing/i,\n\t/credit/i,\n\t/auth(?:entication)?/i,\n\t/unauthori[sz]ed/i,\n\t/forbidden/i,\n\t/api key/i,\n\t/token expired/i,\n\t/invalid key/i,\n\t/provider.*unavailable/i,\n\t/model.*unavailable/i,\n\t/model.*disabled/i,\n\t/model.*not found/i,\n\t/unknown model/i,\n\t/overloaded/i,\n\t/service unavailable/i,\n\t/temporar(?:ily)? unavailable/i,\n\t/connection refused/i,\n\t/fetch failed/i,\n\t/network error/i,\n\t/socket hang up/i,\n\t/stream ended without finish_reason/i,\n\t/upstream/i,\n\t/timed? out/i,\n\t/timeout/i,\n\t/\\b502\\b/,\n\t/\\b503\\b/,\n\t/\\b504\\b/,\n\t/cold.?start/i,\n\t/empty response/i,\n\t/no output/i,\n\t/model.*(?:load|fail|error)/i,\n];\n\n/**\n * Failures reported as `<tool> failed (exit N): ...` or `<tool> failed with\n * exit code N` come from a tool call inside the child's task, not from the\n * provider/model, however network-flavored their details read. Retrying a\n * different model cannot fix them and would rerun the whole task. Tool names\n * include namespaced forms like `mcp.server/write`.\n */\nconst TOOL_FAILURE_PREFIX = /^[\\w.:@/-]+ failed (?:(?:\\(exit \\d+\\):)|(?:with exit code \\d+))(?:\\s|$)/i;\n\nexport function isRetryableModelFailure(error: string | undefined): boolean {\n\tif (!error) return false;\n\tif (TOOL_FAILURE_PREFIX.test(error.trim())) return false;\n\treturn RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(error));\n}\n\nexport function formatModelAttemptNote(attempt: ModelAttemptSummary, nextModel?: string): string {\n\tconst failure = attempt.error?.trim() || `exit ${attempt.exitCode ?? 1}`;\n\treturn nextModel\n\t\t? `[fallback] ${attempt.model} failed: ${failure}. Retrying with ${nextModel}.`\n\t\t: `[fallback] ${attempt.model} failed: ${failure}.`;\n}\n"]}
1
+ {"version":3,"file":"model-fallback.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ModelInfo as AvailableModelInfo } from \"../../shared/model-info.ts\";\nimport type { ChildTier, ModelSelection, Usage } from \"../../shared/types.ts\";\nimport { checkModelScope, type ModelScopeConfig, type ModelScopeViolation, type ModelSource } from \"./model-scope.ts\";\nimport { applyThinkingSuffix } from \"./pi-args.ts\";\n\nexport type { AvailableModelInfo };\n\ninterface ModelAttemptSummary {\n\tmodel: string;\n\tsuccess: boolean;\n\texitCode?: number | null;\n\terror?: string;\n\tusage?: Usage;\n}\n\nexport function splitThinkingSuffix(model: string): { baseModel: string; thinkingSuffix: string } {\n\tconst colonIdx = model.lastIndexOf(\":\");\n\tif (colonIdx === -1) return { baseModel: model, thinkingSuffix: \"\" };\n\treturn {\n\t\tbaseModel: model.substring(0, colonIdx),\n\t\tthinkingSuffix: model.substring(colonIdx),\n\t};\n}\n\n/** Sentinel model value requesting that a subagent inherit the parent session's model. */\nexport const INHERIT_MODEL = \"inherit\";\n\n/** Minimal shape of the parent session's in-memory model (`ctx.model`). */\nexport interface ParentModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Normalize a model id or provider segment for fuzzy comparison: case-fold,\n * treat dots/underscores as dashes (so `4.5` matches `4-5`), and collapse\n * repeated separators. Pure.\n */\nexport function normalizeModelSegment(segment: string): string {\n\treturn segment\n\t\t.toLowerCase()\n\t\t.replace(/[._]+/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nfunction isPlausibleDateStamp(year: string, month: string, day: string): boolean {\n\tconst yyyy = Number(year);\n\tconst mm = Number(month);\n\tconst dd = Number(day);\n\treturn yyyy >= 1900 && yyyy <= 2099 && mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31;\n}\n\n/** Drop a trailing date stamp (`-20251001` or `-2025-10-01`) so dated and undated ids match. Pure. */\nfunction stripTrailingDateStamp(segment: string): string {\n\tconst dashed = /^(.*)-(\\d{4})-(\\d{2})-(\\d{2})$/.exec(segment);\n\tif (dashed && isPlausibleDateStamp(dashed[2]!, dashed[3]!, dashed[4]!)) return dashed[1]!;\n\tconst compact = /^(.*)-(\\d{4})(\\d{2})(\\d{2})$/.exec(segment);\n\tif (compact && isPlausibleDateStamp(compact[2]!, compact[3]!, compact[4]!)) return compact[1]!;\n\treturn segment;\n}\n\nfunction resolveBaseModelCandidate(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (baseModel.includes(\"/\")) {\n\t\tconst exact = availableModels.find((entry) => entry.fullId === baseModel);\n\t\tif (exact) return exact.fullId;\n\t} else {\n\t\tconst exactMatches = availableModels.filter((entry) => entry.id === baseModel);\n\t\tif (preferredProvider) {\n\t\t\tconst preferredMatch = exactMatches.find((entry) => entry.provider === preferredProvider);\n\t\t\tif (preferredMatch) return preferredMatch.fullId;\n\t\t}\n\t\tif (exactMatches.length === 1) return exactMatches[0]!.fullId;\n\t}\n\n\treturn fuzzyResolveModel(baseModel, availableModels, preferredProvider);\n}\n\n/**\n * Fuzzy-resolve a base model id (thinking suffix already stripped) against the\n * registry, tolerating separator, case, and optional date-stamp differences so\n * users do not have to spell provider/model exactly. A qualified `provider/id`\n * query only matches within the named provider — this never silently switches\n * providers for security/cost-sensitive configs. Returns the matched `fullId`,\n * or `undefined` when there is no match or the match is ambiguous across\n * providers (and no `preferredProvider` disambiguates). Pure.\n */\nexport function fuzzyResolveModel(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tlet queryProvider: string | undefined;\n\tlet queryIdRaw = baseModel;\n\tconst slashIdx = baseModel.indexOf(\"/\");\n\tif (slashIdx !== -1) {\n\t\tqueryProvider = normalizeModelSegment(baseModel.slice(0, slashIdx));\n\t\tqueryIdRaw = baseModel.slice(slashIdx + 1);\n\t} else {\n\t\tconst providerSeparators = [\":\", \".\"];\n\t\tfor (const separator of providerSeparators) {\n\t\t\tconst separatorIdx = baseModel.indexOf(separator);\n\t\t\tif (separatorIdx <= 0) continue;\n\t\t\tconst providerPart = normalizeModelSegment(baseModel.slice(0, separatorIdx));\n\t\t\tif (!availableModels.some((entry) => normalizeModelSegment(entry.provider) === providerPart)) continue;\n\t\t\tqueryProvider = providerPart;\n\t\t\tqueryIdRaw = baseModel.slice(separatorIdx + 1);\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst queryId = normalizeModelSegment(queryIdRaw);\n\tconst queryIdNoDate = stripTrailingDateStamp(queryId);\n\n\tconst candidates = availableModels.filter((entry) => {\n\t\tconst entryId = normalizeModelSegment(entry.id);\n\t\tif (entryId !== queryId && stripTrailingDateStamp(entryId) !== queryIdNoDate) return false;\n\t\tif (queryProvider !== undefined && normalizeModelSegment(entry.provider) !== queryProvider) return false;\n\t\treturn true;\n\t});\n\tif (candidates.length === 0) return undefined;\n\tif (preferredProvider) {\n\t\tconst preferredProviderNorm = normalizeModelSegment(preferredProvider);\n\t\tconst preferred = candidates.find((entry) => normalizeModelSegment(entry.provider) === preferredProviderNorm);\n\t\tif (preferred) return preferred.fullId;\n\t}\n\tif (candidates.length === 1) return candidates[0]!.fullId;\n\treturn undefined;\n}\n\n/**\n * Resolve a possibly-loose model id to a canonical `provider/id` (plus any\n * thinking suffix). Exact registry matches win; fuzzy normalization\n * (separator/case/date-stamp via {@link fuzzyResolveModel}) is a fallback so\n * spelling differences still resolve. Never switches providers for a qualified\n * query. Pure.\n */\nexport function resolveModelCandidate(\n\tmodel: string | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (!model) return undefined;\n\tif (!availableModels || availableModels.length === 0) return model;\n\n\tconst resolvedWhole = resolveBaseModelCandidate(model, availableModels, preferredProvider);\n\tif (resolvedWhole) return resolvedWhole;\n\n\tconst { baseModel, thinkingSuffix } = splitThinkingSuffix(model);\n\tif (!thinkingSuffix) return model;\n\tconst resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);\n\tif (resolvedBase) return `${resolvedBase}${thinkingSuffix}`;\n\treturn model;\n}\n\nexport interface ResolveSubagentModelOverrideOptions {\n\t/** When set with `enforce: true`, out-of-scope models are rejected. */\n\tscope?: ModelScopeConfig;\n\t/** Origin of the requested model: explicit caller-supplied (hard error) vs inherited (warn). Defaults to `\"inherited\"`. */\n\tsource?: ModelSource;\n\t/** Called for warn-severity violations instead of `console.warn`. */\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nfunction defaultScopeWarn(violation: ModelScopeViolation): void {\n\tconsole.warn(`[pi-subagents] ${violation.message}`);\n}\n\n/**\n * Resolve the `--model` override passed to a spawned subagent.\n *\n * When no model is requested (`undefined`, `false`, empty, or the `\"inherit\"`\n * sentinel), the child must inherit the parent session's *in-memory* model\n * (`provider/id`) instead of being left to resolve its own model. Without an\n * explicit `provider/id`, the child falls back to the global\n * `~/.pi/agent/settings.json` default, which is shared across every open PI\n * session — so a different session that last changed its model in the TUI would\n * silently contaminate this session's subagents (see issue #266). Passing an\n * explicit `provider/id` keeps each session's children isolated to that\n * session's model.\n *\n * An explicitly requested model string is resolved via {@link resolveModelCandidate}.\n * When `options.scope.enforce` is on, an out-of-scope resolved model throws for\n * an explicit (`source: \"explicit\"`) request and warns for an inherited one.\n */\nexport function resolveSubagentModelOverride(\n\trequestedModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: ResolveSubagentModelOverrideOptions,\n): string | undefined {\n\tconst trimmed = typeof requestedModel === \"string\" ? requestedModel.trim() : \"\";\n\tconst explicit = trimmed && trimmed !== INHERIT_MODEL ? trimmed : undefined;\n\tlet resolved: string | undefined;\n\tif (explicit === undefined) {\n\t\tresolved = parentModel ? `${parentModel.provider}/${parentModel.id}` : undefined;\n\t} else {\n\t\tresolved = resolveModelCandidate(explicit, availableModels, preferredProvider);\n\t}\n\tif (resolved && options?.scope?.enforce) {\n\t\tconst source: ModelSource = explicit === undefined ? \"inherited\" : (options.source ?? \"inherited\");\n\t\tconst violation = checkModelScope(resolved, options.scope, source);\n\t\tif (violation) {\n\t\t\tif (violation.severity === \"error\") throw new Error(violation.message);\n\t\t\t(options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t}\n\treturn resolved;\n}\n\nexport function resolveEffectiveSubagentModel(\n\texplicitModel: string | boolean | undefined,\n\tagentModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: Omit<ResolveSubagentModelOverrideOptions, \"source\">,\n): string | undefined {\n\tconst resolved = resolveSubagentModelOverride(\n\t\texplicitModel ?? agentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: explicitModel !== undefined ? \"explicit\" : \"inherited\" },\n\t);\n\tif (resolved || explicitModel === undefined) return resolved;\n\treturn resolveSubagentModelOverride(\n\t\tagentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: \"inherited\" },\n\t);\n}\n\n// lunr: model tier bridge — every executable child must resolve one configured tier.\nexport function resolveTierModelOverride(tier: unknown): string | undefined {\n\tif (tier !== \"light\" && tier !== \"standard\" && tier !== \"heavy\") {\n\t\tthrow new Error(\"Every subagent execution requires tier: \\\"light\\\", \\\"standard\\\", or \\\"heavy\\\".\");\n\t}\n\tconst tierName = tier.trim();\n\ttry {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[Symbol.for(\"@lunr/model-tiers\")] as\n\t\t\t| { getTierModel?: (tier: string) => unknown; isTierModeEnabled?: () => unknown }\n\t\t\t| undefined;\n\t\tif (typeof bridge?.isTierModeEnabled !== \"function\" || typeof bridge?.getTierModel !== \"function\") {\n\t\t\tthrow new Error(\"Model tier settings are unavailable. Reload lunR and try again.\");\n\t\t}\n\t\tif (bridge.isTierModeEnabled() !== true) {\n\t\t\tthrow new Error(\"Model tiers are disabled. Enable them in /settings before launching a subagent.\");\n\t\t}\n\t\tconst model = bridge.getTierModel(tierName);\n\t\tif (typeof model !== \"string\" || !model.trim()) {\n\t\t\tthrow new Error(`Model tier '${tierName}' has no configured model. Configure it in /settings before launching a subagent.`);\n\t\t}\n\t\tconst trimmed = model.trim();\n\t\tconst thinking =\n\t\t\ttypeof bridge.getTierThinking === \"function\" ? bridge.getTierThinking(tierName) : undefined;\n\t\tconst parent = typeof bridge.getParentThinking === \"function\" ? bridge.getParentThinking() : undefined;\n\t\tconst level = (typeof thinking === \"string\" && thinking ? thinking : undefined) ?? (typeof parent === \"string\" && parent ? parent : undefined);\n\t\tif (!level) return trimmed;\n\t\treturn applyThinkingSuffix(trimmed, level, true) ?? trimmed;\n\t} catch (error) {\n\t\tthrow error instanceof Error ? error : new Error(String(error));\n\t}\n}\n\n/** Resolve a required tier and prove its configured model is available to this session. */\nexport function resolveRequiredTierModel(\n\ttier: unknown,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n): string {\n\tconst configured = resolveTierModelOverride(tier);\n\tif (!configured) throw new Error(`Model tier '${String(tier)}' could not be resolved.`);\n\tif (!availableModels?.length) {\n\t\tthrow new Error(`Model tier '${String(tier)}' cannot launch because no authenticated models are available.`);\n\t}\n\tconst { baseModel, thinkingSuffix } = splitThinkingSuffix(configured);\n\tconst resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);\n\tif (!resolvedBase) {\n\t\tthrow new Error(\n\t\t\t`Model tier '${String(tier)}' resolves to '${baseModel}', but that model is unavailable or unauthenticated. Configure an available model in /settings.`,\n\t\t);\n\t}\n\treturn `${resolvedBase}${thinkingSuffix}`;\n}\n\nfunction requestedModelString(model: unknown): string | undefined {\n\treturn typeof model === \"string\" && model.trim() && model.trim() !== INHERIT_MODEL ? model.trim() : undefined;\n}\n\nfunction requestedTier(tier: unknown): ChildTier | undefined {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\" ? tier : undefined;\n}\n\n/**\n * Capture how a child model was selected from the original requested params.\n * Must run before callers replace `model` with a resolved override.\n * Explicit model wins; a tier only counts when it actually resolves.\n */\nexport function captureModelSelection(input: { model?: unknown; tier?: unknown }): ModelSelection {\n\tconst tier = requestedTier(input.tier);\n\tif (!tier) throw new Error(\"Every subagent execution requires tier: \\\"light\\\", \\\"standard\\\", or \\\"heavy\\\".\");\n\treturn { kind: \"tier\", tier };\n}\n\nexport interface BuildModelCandidatesOptions {\n\t/** Fallback models are inherited agent config and warn, rather than error, when out of scope. */\n\tscope?: ModelScopeConfig;\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nexport function buildModelCandidates(\n\tprimaryModel: string | undefined,\n\tfallbackModels: string[] | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: BuildModelCandidatesOptions,\n): string[] {\n\tconst seen = new Set<string>();\n\tconst candidates: string[] = [];\n\tconst rawCandidates = [primaryModel, ...(fallbackModels ?? [])];\n\tfor (let index = 0; index < rawCandidates.length; index++) {\n\t\tconst raw = rawCandidates[index];\n\t\tif (!raw) continue;\n\t\tconst normalized = resolveModelCandidate(raw.trim(), availableModels, preferredProvider);\n\t\tif (!normalized || seen.has(normalized)) continue;\n\t\tif (index > 0 && options?.scope?.enforce) {\n\t\t\tconst violation = checkModelScope(normalized, options.scope, \"inherited\");\n\t\t\tif (violation) (options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t\tseen.add(normalized);\n\t\tcandidates.push(normalized);\n\t}\n\treturn candidates;\n}\n\nconst RETRYABLE_MODEL_FAILURE_PATTERNS = [\n\t/rate\\s*limit/i,\n\t/too many requests/i,\n\t/\\b429\\b/,\n\t/quota/i,\n\t/billing/i,\n\t/credit/i,\n\t/auth(?:entication)?/i,\n\t/unauthori[sz]ed/i,\n\t/forbidden/i,\n\t/api key/i,\n\t/token expired/i,\n\t/invalid key/i,\n\t/provider.*unavailable/i,\n\t/model.*unavailable/i,\n\t/model.*disabled/i,\n\t/model.*not found/i,\n\t/unknown model/i,\n\t/overloaded/i,\n\t/service unavailable/i,\n\t/temporar(?:ily)? unavailable/i,\n\t/connection refused/i,\n\t/fetch failed/i,\n\t/network error/i,\n\t/socket hang up/i,\n\t/stream ended without finish_reason/i,\n\t/upstream/i,\n\t/timed? out/i,\n\t/timeout/i,\n\t/\\b502\\b/,\n\t/\\b503\\b/,\n\t/\\b504\\b/,\n\t/cold.?start/i,\n\t/empty response/i,\n\t/no output/i,\n\t/model.*(?:load|fail|error)/i,\n];\n\n/**\n * Failures reported as `<tool> failed (exit N): ...` or `<tool> failed with\n * exit code N` come from a tool call inside the child's task, not from the\n * provider/model, however network-flavored their details read. Retrying a\n * different model cannot fix them and would rerun the whole task. Tool names\n * include namespaced forms like `mcp.server/write`.\n */\nconst TOOL_FAILURE_PREFIX = /^[\\w.:@/-]+ failed (?:(?:\\(exit \\d+\\):)|(?:with exit code \\d+))(?:\\s|$)/i;\n\nexport function isRetryableModelFailure(error: string | undefined): boolean {\n\tif (!error) return false;\n\tif (TOOL_FAILURE_PREFIX.test(error.trim())) return false;\n\treturn RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(error));\n}\n\nexport function formatModelAttemptNote(attempt: ModelAttemptSummary, nextModel?: string): string {\n\tconst failure = attempt.error?.trim() || `exit ${attempt.exitCode ?? 1}`;\n\treturn nextModel\n\t\t? `[fallback] ${attempt.model} failed: ${failure}. Retrying with ${nextModel}.`\n\t\t: `[fallback] ${attempt.model} failed: ${failure}.`;\n}\n"]}
@@ -180,27 +180,23 @@ export function resolveEffectiveSubagentModel(explicitModel, agentModel, parentM
180
180
  return resolved;
181
181
  return resolveSubagentModelOverride(agentModel, parentModel, availableModels, preferredProvider, { ...options, source: "inherited" });
182
182
  }
183
- // lunr: model tier bridge — resolve a subagent `tier` param through lunR core's
184
- // model-tiers global (Symbol.for("@lunr/model-tiers")). Absent bridge, disabled tier
185
- // mode, unknown tier, or unconfigured tier all resolve to undefined so callers fall
186
- // back to normal inherit behavior. Never throws.
183
+ // lunr: model tier bridge — every executable child must resolve one configured tier.
187
184
  export function resolveTierModelOverride(tier) {
188
- if (typeof tier !== "string" || !tier.trim())
189
- return undefined;
185
+ if (tier !== "light" && tier !== "standard" && tier !== "heavy") {
186
+ throw new Error("Every subagent execution requires tier: \"light\", \"standard\", or \"heavy\".");
187
+ }
190
188
  const tierName = tier.trim();
191
189
  try {
192
190
  const bridge = globalThis[Symbol.for("@lunr/model-tiers")];
193
191
  if (typeof bridge?.isTierModeEnabled !== "function" || typeof bridge?.getTierModel !== "function") {
194
- return undefined;
192
+ throw new Error("Model tier settings are unavailable. Reload lunR and try again.");
193
+ }
194
+ if (bridge.isTierModeEnabled() !== true) {
195
+ throw new Error("Model tiers are disabled. Enable them in /settings before launching a subagent.");
195
196
  }
196
- if (bridge.isTierModeEnabled() !== true)
197
- return undefined;
198
197
  const model = bridge.getTierModel(tierName);
199
198
  if (typeof model !== "string" || !model.trim()) {
200
- if (process.env.PI_SUBAGENTS_DEBUG) {
201
- console.warn(`[pi-subagents] model tier '${tierName}' has no configured model; inheriting parent model.`);
202
- }
203
- return undefined;
199
+ throw new Error(`Model tier '${tierName}' has no configured model. Configure it in /settings before launching a subagent.`);
204
200
  }
205
201
  const trimmed = model.trim();
206
202
  const thinking = typeof bridge.getTierThinking === "function" ? bridge.getTierThinking(tierName) : undefined;
@@ -211,11 +207,23 @@ export function resolveTierModelOverride(tier) {
211
207
  return applyThinkingSuffix(trimmed, level, true) ?? trimmed;
212
208
  }
213
209
  catch (error) {
214
- if (process.env.PI_SUBAGENTS_DEBUG) {
215
- console.warn(`[pi-subagents] model tier resolution failed for '${tierName}': ${error instanceof Error ? error.message : String(error)}`);
216
- }
217
- return undefined;
210
+ throw error instanceof Error ? error : new Error(String(error));
211
+ }
212
+ }
213
+ /** Resolve a required tier and prove its configured model is available to this session. */
214
+ export function resolveRequiredTierModel(tier, availableModels, preferredProvider) {
215
+ const configured = resolveTierModelOverride(tier);
216
+ if (!configured)
217
+ throw new Error(`Model tier '${String(tier)}' could not be resolved.`);
218
+ if (!availableModels?.length) {
219
+ throw new Error(`Model tier '${String(tier)}' cannot launch because no authenticated models are available.`);
220
+ }
221
+ const { baseModel, thinkingSuffix } = splitThinkingSuffix(configured);
222
+ const resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);
223
+ if (!resolvedBase) {
224
+ throw new Error(`Model tier '${String(tier)}' resolves to '${baseModel}', but that model is unavailable or unauthenticated. Configure an available model in /settings.`);
218
225
  }
226
+ return `${resolvedBase}${thinkingSuffix}`;
219
227
  }
220
228
  function requestedModelString(model) {
221
229
  return typeof model === "string" && model.trim() && model.trim() !== INHERIT_MODEL ? model.trim() : undefined;
@@ -229,12 +237,10 @@ function requestedTier(tier) {
229
237
  * Explicit model wins; a tier only counts when it actually resolves.
230
238
  */
231
239
  export function captureModelSelection(input) {
232
- if (requestedModelString(input.model))
233
- return { kind: "model" };
234
240
  const tier = requestedTier(input.tier);
235
- if (tier && resolveTierModelOverride(tier))
236
- return { kind: "tier", tier };
237
- return { kind: "inherit" };
241
+ if (!tier)
242
+ throw new Error("Every subagent execution requires tier: \"light\", \"standard\", or \"heavy\".");
243
+ return { kind: "tier", tier };
238
244
  }
239
245
  export function buildModelCandidates(primaryModel, fallbackModels, availableModels, preferredProvider, options) {
240
246
  const seen = new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"model-fallback.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ModelInfo as AvailableModelInfo } from \"../../shared/model-info.ts\";\nimport type { ChildTier, ModelSelection, Usage } from \"../../shared/types.ts\";\nimport { checkModelScope, type ModelScopeConfig, type ModelScopeViolation, type ModelSource } from \"./model-scope.ts\";\nimport { applyThinkingSuffix } from \"./pi-args.ts\";\n\nexport type { AvailableModelInfo };\n\ninterface ModelAttemptSummary {\n\tmodel: string;\n\tsuccess: boolean;\n\texitCode?: number | null;\n\terror?: string;\n\tusage?: Usage;\n}\n\nexport function splitThinkingSuffix(model: string): { baseModel: string; thinkingSuffix: string } {\n\tconst colonIdx = model.lastIndexOf(\":\");\n\tif (colonIdx === -1) return { baseModel: model, thinkingSuffix: \"\" };\n\treturn {\n\t\tbaseModel: model.substring(0, colonIdx),\n\t\tthinkingSuffix: model.substring(colonIdx),\n\t};\n}\n\n/** Sentinel model value requesting that a subagent inherit the parent session's model. */\nexport const INHERIT_MODEL = \"inherit\";\n\n/** Minimal shape of the parent session's in-memory model (`ctx.model`). */\nexport interface ParentModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Normalize a model id or provider segment for fuzzy comparison: case-fold,\n * treat dots/underscores as dashes (so `4.5` matches `4-5`), and collapse\n * repeated separators. Pure.\n */\nexport function normalizeModelSegment(segment: string): string {\n\treturn segment\n\t\t.toLowerCase()\n\t\t.replace(/[._]+/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nfunction isPlausibleDateStamp(year: string, month: string, day: string): boolean {\n\tconst yyyy = Number(year);\n\tconst mm = Number(month);\n\tconst dd = Number(day);\n\treturn yyyy >= 1900 && yyyy <= 2099 && mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31;\n}\n\n/** Drop a trailing date stamp (`-20251001` or `-2025-10-01`) so dated and undated ids match. Pure. */\nfunction stripTrailingDateStamp(segment: string): string {\n\tconst dashed = /^(.*)-(\\d{4})-(\\d{2})-(\\d{2})$/.exec(segment);\n\tif (dashed && isPlausibleDateStamp(dashed[2]!, dashed[3]!, dashed[4]!)) return dashed[1]!;\n\tconst compact = /^(.*)-(\\d{4})(\\d{2})(\\d{2})$/.exec(segment);\n\tif (compact && isPlausibleDateStamp(compact[2]!, compact[3]!, compact[4]!)) return compact[1]!;\n\treturn segment;\n}\n\nfunction resolveBaseModelCandidate(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (baseModel.includes(\"/\")) {\n\t\tconst exact = availableModels.find((entry) => entry.fullId === baseModel);\n\t\tif (exact) return exact.fullId;\n\t} else {\n\t\tconst exactMatches = availableModels.filter((entry) => entry.id === baseModel);\n\t\tif (preferredProvider) {\n\t\t\tconst preferredMatch = exactMatches.find((entry) => entry.provider === preferredProvider);\n\t\t\tif (preferredMatch) return preferredMatch.fullId;\n\t\t}\n\t\tif (exactMatches.length === 1) return exactMatches[0]!.fullId;\n\t}\n\n\treturn fuzzyResolveModel(baseModel, availableModels, preferredProvider);\n}\n\n/**\n * Fuzzy-resolve a base model id (thinking suffix already stripped) against the\n * registry, tolerating separator, case, and optional date-stamp differences so\n * users do not have to spell provider/model exactly. A qualified `provider/id`\n * query only matches within the named provider — this never silently switches\n * providers for security/cost-sensitive configs. Returns the matched `fullId`,\n * or `undefined` when there is no match or the match is ambiguous across\n * providers (and no `preferredProvider` disambiguates). Pure.\n */\nexport function fuzzyResolveModel(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tlet queryProvider: string | undefined;\n\tlet queryIdRaw = baseModel;\n\tconst slashIdx = baseModel.indexOf(\"/\");\n\tif (slashIdx !== -1) {\n\t\tqueryProvider = normalizeModelSegment(baseModel.slice(0, slashIdx));\n\t\tqueryIdRaw = baseModel.slice(slashIdx + 1);\n\t} else {\n\t\tconst providerSeparators = [\":\", \".\"];\n\t\tfor (const separator of providerSeparators) {\n\t\t\tconst separatorIdx = baseModel.indexOf(separator);\n\t\t\tif (separatorIdx <= 0) continue;\n\t\t\tconst providerPart = normalizeModelSegment(baseModel.slice(0, separatorIdx));\n\t\t\tif (!availableModels.some((entry) => normalizeModelSegment(entry.provider) === providerPart)) continue;\n\t\t\tqueryProvider = providerPart;\n\t\t\tqueryIdRaw = baseModel.slice(separatorIdx + 1);\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst queryId = normalizeModelSegment(queryIdRaw);\n\tconst queryIdNoDate = stripTrailingDateStamp(queryId);\n\n\tconst candidates = availableModels.filter((entry) => {\n\t\tconst entryId = normalizeModelSegment(entry.id);\n\t\tif (entryId !== queryId && stripTrailingDateStamp(entryId) !== queryIdNoDate) return false;\n\t\tif (queryProvider !== undefined && normalizeModelSegment(entry.provider) !== queryProvider) return false;\n\t\treturn true;\n\t});\n\tif (candidates.length === 0) return undefined;\n\tif (preferredProvider) {\n\t\tconst preferredProviderNorm = normalizeModelSegment(preferredProvider);\n\t\tconst preferred = candidates.find((entry) => normalizeModelSegment(entry.provider) === preferredProviderNorm);\n\t\tif (preferred) return preferred.fullId;\n\t}\n\tif (candidates.length === 1) return candidates[0]!.fullId;\n\treturn undefined;\n}\n\n/**\n * Resolve a possibly-loose model id to a canonical `provider/id` (plus any\n * thinking suffix). Exact registry matches win; fuzzy normalization\n * (separator/case/date-stamp via {@link fuzzyResolveModel}) is a fallback so\n * spelling differences still resolve. Never switches providers for a qualified\n * query. Pure.\n */\nexport function resolveModelCandidate(\n\tmodel: string | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (!model) return undefined;\n\tif (!availableModels || availableModels.length === 0) return model;\n\n\tconst resolvedWhole = resolveBaseModelCandidate(model, availableModels, preferredProvider);\n\tif (resolvedWhole) return resolvedWhole;\n\n\tconst { baseModel, thinkingSuffix } = splitThinkingSuffix(model);\n\tif (!thinkingSuffix) return model;\n\tconst resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);\n\tif (resolvedBase) return `${resolvedBase}${thinkingSuffix}`;\n\treturn model;\n}\n\nexport interface ResolveSubagentModelOverrideOptions {\n\t/** When set with `enforce: true`, out-of-scope models are rejected. */\n\tscope?: ModelScopeConfig;\n\t/** Origin of the requested model: explicit caller-supplied (hard error) vs inherited (warn). Defaults to `\"inherited\"`. */\n\tsource?: ModelSource;\n\t/** Called for warn-severity violations instead of `console.warn`. */\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nfunction defaultScopeWarn(violation: ModelScopeViolation): void {\n\tconsole.warn(`[pi-subagents] ${violation.message}`);\n}\n\n/**\n * Resolve the `--model` override passed to a spawned subagent.\n *\n * When no model is requested (`undefined`, `false`, empty, or the `\"inherit\"`\n * sentinel), the child must inherit the parent session's *in-memory* model\n * (`provider/id`) instead of being left to resolve its own model. Without an\n * explicit `provider/id`, the child falls back to the global\n * `~/.pi/agent/settings.json` default, which is shared across every open PI\n * session — so a different session that last changed its model in the TUI would\n * silently contaminate this session's subagents (see issue #266). Passing an\n * explicit `provider/id` keeps each session's children isolated to that\n * session's model.\n *\n * An explicitly requested model string is resolved via {@link resolveModelCandidate}.\n * When `options.scope.enforce` is on, an out-of-scope resolved model throws for\n * an explicit (`source: \"explicit\"`) request and warns for an inherited one.\n */\nexport function resolveSubagentModelOverride(\n\trequestedModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: ResolveSubagentModelOverrideOptions,\n): string | undefined {\n\tconst trimmed = typeof requestedModel === \"string\" ? requestedModel.trim() : \"\";\n\tconst explicit = trimmed && trimmed !== INHERIT_MODEL ? trimmed : undefined;\n\tlet resolved: string | undefined;\n\tif (explicit === undefined) {\n\t\tresolved = parentModel ? `${parentModel.provider}/${parentModel.id}` : undefined;\n\t} else {\n\t\tresolved = resolveModelCandidate(explicit, availableModels, preferredProvider);\n\t}\n\tif (resolved && options?.scope?.enforce) {\n\t\tconst source: ModelSource = explicit === undefined ? \"inherited\" : (options.source ?? \"inherited\");\n\t\tconst violation = checkModelScope(resolved, options.scope, source);\n\t\tif (violation) {\n\t\t\tif (violation.severity === \"error\") throw new Error(violation.message);\n\t\t\t(options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t}\n\treturn resolved;\n}\n\nexport function resolveEffectiveSubagentModel(\n\texplicitModel: string | boolean | undefined,\n\tagentModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: Omit<ResolveSubagentModelOverrideOptions, \"source\">,\n): string | undefined {\n\tconst resolved = resolveSubagentModelOverride(\n\t\texplicitModel ?? agentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: explicitModel !== undefined ? \"explicit\" : \"inherited\" },\n\t);\n\tif (resolved || explicitModel === undefined) return resolved;\n\treturn resolveSubagentModelOverride(\n\t\tagentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: \"inherited\" },\n\t);\n}\n\n// lunr: model tier bridge — resolve a subagent `tier` param through lunR core's\n// model-tiers global (Symbol.for(\"@lunr/model-tiers\")). Absent bridge, disabled tier\n// mode, unknown tier, or unconfigured tier all resolve to undefined so callers fall\n// back to normal inherit behavior. Never throws.\nexport function resolveTierModelOverride(tier: unknown): string | undefined {\n\tif (typeof tier !== \"string\" || !tier.trim()) return undefined;\n\tconst tierName = tier.trim();\n\ttry {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[Symbol.for(\"@lunr/model-tiers\")] as\n\t\t\t| { getTierModel?: (tier: string) => unknown; isTierModeEnabled?: () => unknown }\n\t\t\t| undefined;\n\t\tif (typeof bridge?.isTierModeEnabled !== \"function\" || typeof bridge?.getTierModel !== \"function\") {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (bridge.isTierModeEnabled() !== true) return undefined;\n\t\tconst model = bridge.getTierModel(tierName);\n\t\tif (typeof model !== \"string\" || !model.trim()) {\n\t\t\tif (process.env.PI_SUBAGENTS_DEBUG) {\n\t\t\t\tconsole.warn(`[pi-subagents] model tier '${tierName}' has no configured model; inheriting parent model.`);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\tconst trimmed = model.trim();\n\t\tconst thinking =\n\t\t\ttypeof bridge.getTierThinking === \"function\" ? bridge.getTierThinking(tierName) : undefined;\n\t\tconst parent = typeof bridge.getParentThinking === \"function\" ? bridge.getParentThinking() : undefined;\n\t\tconst level = (typeof thinking === \"string\" && thinking ? thinking : undefined) ?? (typeof parent === \"string\" && parent ? parent : undefined);\n\t\tif (!level) return trimmed;\n\t\treturn applyThinkingSuffix(trimmed, level, true) ?? trimmed;\n\t} catch (error) {\n\t\tif (process.env.PI_SUBAGENTS_DEBUG) {\n\t\t\tconsole.warn(\n\t\t\t\t`[pi-subagents] model tier resolution failed for '${tierName}': ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n}\n\nfunction requestedModelString(model: unknown): string | undefined {\n\treturn typeof model === \"string\" && model.trim() && model.trim() !== INHERIT_MODEL ? model.trim() : undefined;\n}\n\nfunction requestedTier(tier: unknown): ChildTier | undefined {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\" ? tier : undefined;\n}\n\n/**\n * Capture how a child model was selected from the original requested params.\n * Must run before callers replace `model` with a resolved override.\n * Explicit model wins; a tier only counts when it actually resolves.\n */\nexport function captureModelSelection(input: { model?: unknown; tier?: unknown }): ModelSelection {\n\tif (requestedModelString(input.model)) return { kind: \"model\" };\n\tconst tier = requestedTier(input.tier);\n\tif (tier && resolveTierModelOverride(tier)) return { kind: \"tier\", tier };\n\treturn { kind: \"inherit\" };\n}\n\nexport interface BuildModelCandidatesOptions {\n\t/** Fallback models are inherited agent config and warn, rather than error, when out of scope. */\n\tscope?: ModelScopeConfig;\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nexport function buildModelCandidates(\n\tprimaryModel: string | undefined,\n\tfallbackModels: string[] | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: BuildModelCandidatesOptions,\n): string[] {\n\tconst seen = new Set<string>();\n\tconst candidates: string[] = [];\n\tconst rawCandidates = [primaryModel, ...(fallbackModels ?? [])];\n\tfor (let index = 0; index < rawCandidates.length; index++) {\n\t\tconst raw = rawCandidates[index];\n\t\tif (!raw) continue;\n\t\tconst normalized = resolveModelCandidate(raw.trim(), availableModels, preferredProvider);\n\t\tif (!normalized || seen.has(normalized)) continue;\n\t\tif (index > 0 && options?.scope?.enforce) {\n\t\t\tconst violation = checkModelScope(normalized, options.scope, \"inherited\");\n\t\t\tif (violation) (options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t\tseen.add(normalized);\n\t\tcandidates.push(normalized);\n\t}\n\treturn candidates;\n}\n\nconst RETRYABLE_MODEL_FAILURE_PATTERNS = [\n\t/rate\\s*limit/i,\n\t/too many requests/i,\n\t/\\b429\\b/,\n\t/quota/i,\n\t/billing/i,\n\t/credit/i,\n\t/auth(?:entication)?/i,\n\t/unauthori[sz]ed/i,\n\t/forbidden/i,\n\t/api key/i,\n\t/token expired/i,\n\t/invalid key/i,\n\t/provider.*unavailable/i,\n\t/model.*unavailable/i,\n\t/model.*disabled/i,\n\t/model.*not found/i,\n\t/unknown model/i,\n\t/overloaded/i,\n\t/service unavailable/i,\n\t/temporar(?:ily)? unavailable/i,\n\t/connection refused/i,\n\t/fetch failed/i,\n\t/network error/i,\n\t/socket hang up/i,\n\t/stream ended without finish_reason/i,\n\t/upstream/i,\n\t/timed? out/i,\n\t/timeout/i,\n\t/\\b502\\b/,\n\t/\\b503\\b/,\n\t/\\b504\\b/,\n\t/cold.?start/i,\n\t/empty response/i,\n\t/no output/i,\n\t/model.*(?:load|fail|error)/i,\n];\n\n/**\n * Failures reported as `<tool> failed (exit N): ...` or `<tool> failed with\n * exit code N` come from a tool call inside the child's task, not from the\n * provider/model, however network-flavored their details read. Retrying a\n * different model cannot fix them and would rerun the whole task. Tool names\n * include namespaced forms like `mcp.server/write`.\n */\nconst TOOL_FAILURE_PREFIX = /^[\\w.:@/-]+ failed (?:(?:\\(exit \\d+\\):)|(?:with exit code \\d+))(?:\\s|$)/i;\n\nexport function isRetryableModelFailure(error: string | undefined): boolean {\n\tif (!error) return false;\n\tif (TOOL_FAILURE_PREFIX.test(error.trim())) return false;\n\treturn RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(error));\n}\n\nexport function formatModelAttemptNote(attempt: ModelAttemptSummary, nextModel?: string): string {\n\tconst failure = attempt.error?.trim() || `exit ${attempt.exitCode ?? 1}`;\n\treturn nextModel\n\t\t? `[fallback] ${attempt.model} failed: ${failure}. Retrying with ${nextModel}.`\n\t\t: `[fallback] ${attempt.model} failed: ${failure}.`;\n}\n"]}
1
+ {"version":3,"file":"model-fallback.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ModelInfo as AvailableModelInfo } from \"../../shared/model-info.ts\";\nimport type { ChildTier, ModelSelection, Usage } from \"../../shared/types.ts\";\nimport { checkModelScope, type ModelScopeConfig, type ModelScopeViolation, type ModelSource } from \"./model-scope.ts\";\nimport { applyThinkingSuffix } from \"./pi-args.ts\";\n\nexport type { AvailableModelInfo };\n\ninterface ModelAttemptSummary {\n\tmodel: string;\n\tsuccess: boolean;\n\texitCode?: number | null;\n\terror?: string;\n\tusage?: Usage;\n}\n\nexport function splitThinkingSuffix(model: string): { baseModel: string; thinkingSuffix: string } {\n\tconst colonIdx = model.lastIndexOf(\":\");\n\tif (colonIdx === -1) return { baseModel: model, thinkingSuffix: \"\" };\n\treturn {\n\t\tbaseModel: model.substring(0, colonIdx),\n\t\tthinkingSuffix: model.substring(colonIdx),\n\t};\n}\n\n/** Sentinel model value requesting that a subagent inherit the parent session's model. */\nexport const INHERIT_MODEL = \"inherit\";\n\n/** Minimal shape of the parent session's in-memory model (`ctx.model`). */\nexport interface ParentModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Normalize a model id or provider segment for fuzzy comparison: case-fold,\n * treat dots/underscores as dashes (so `4.5` matches `4-5`), and collapse\n * repeated separators. Pure.\n */\nexport function normalizeModelSegment(segment: string): string {\n\treturn segment\n\t\t.toLowerCase()\n\t\t.replace(/[._]+/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nfunction isPlausibleDateStamp(year: string, month: string, day: string): boolean {\n\tconst yyyy = Number(year);\n\tconst mm = Number(month);\n\tconst dd = Number(day);\n\treturn yyyy >= 1900 && yyyy <= 2099 && mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31;\n}\n\n/** Drop a trailing date stamp (`-20251001` or `-2025-10-01`) so dated and undated ids match. Pure. */\nfunction stripTrailingDateStamp(segment: string): string {\n\tconst dashed = /^(.*)-(\\d{4})-(\\d{2})-(\\d{2})$/.exec(segment);\n\tif (dashed && isPlausibleDateStamp(dashed[2]!, dashed[3]!, dashed[4]!)) return dashed[1]!;\n\tconst compact = /^(.*)-(\\d{4})(\\d{2})(\\d{2})$/.exec(segment);\n\tif (compact && isPlausibleDateStamp(compact[2]!, compact[3]!, compact[4]!)) return compact[1]!;\n\treturn segment;\n}\n\nfunction resolveBaseModelCandidate(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (baseModel.includes(\"/\")) {\n\t\tconst exact = availableModels.find((entry) => entry.fullId === baseModel);\n\t\tif (exact) return exact.fullId;\n\t} else {\n\t\tconst exactMatches = availableModels.filter((entry) => entry.id === baseModel);\n\t\tif (preferredProvider) {\n\t\t\tconst preferredMatch = exactMatches.find((entry) => entry.provider === preferredProvider);\n\t\t\tif (preferredMatch) return preferredMatch.fullId;\n\t\t}\n\t\tif (exactMatches.length === 1) return exactMatches[0]!.fullId;\n\t}\n\n\treturn fuzzyResolveModel(baseModel, availableModels, preferredProvider);\n}\n\n/**\n * Fuzzy-resolve a base model id (thinking suffix already stripped) against the\n * registry, tolerating separator, case, and optional date-stamp differences so\n * users do not have to spell provider/model exactly. A qualified `provider/id`\n * query only matches within the named provider — this never silently switches\n * providers for security/cost-sensitive configs. Returns the matched `fullId`,\n * or `undefined` when there is no match or the match is ambiguous across\n * providers (and no `preferredProvider` disambiguates). Pure.\n */\nexport function fuzzyResolveModel(\n\tbaseModel: string,\n\tavailableModels: AvailableModelInfo[],\n\tpreferredProvider?: string,\n): string | undefined {\n\tlet queryProvider: string | undefined;\n\tlet queryIdRaw = baseModel;\n\tconst slashIdx = baseModel.indexOf(\"/\");\n\tif (slashIdx !== -1) {\n\t\tqueryProvider = normalizeModelSegment(baseModel.slice(0, slashIdx));\n\t\tqueryIdRaw = baseModel.slice(slashIdx + 1);\n\t} else {\n\t\tconst providerSeparators = [\":\", \".\"];\n\t\tfor (const separator of providerSeparators) {\n\t\t\tconst separatorIdx = baseModel.indexOf(separator);\n\t\t\tif (separatorIdx <= 0) continue;\n\t\t\tconst providerPart = normalizeModelSegment(baseModel.slice(0, separatorIdx));\n\t\t\tif (!availableModels.some((entry) => normalizeModelSegment(entry.provider) === providerPart)) continue;\n\t\t\tqueryProvider = providerPart;\n\t\t\tqueryIdRaw = baseModel.slice(separatorIdx + 1);\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst queryId = normalizeModelSegment(queryIdRaw);\n\tconst queryIdNoDate = stripTrailingDateStamp(queryId);\n\n\tconst candidates = availableModels.filter((entry) => {\n\t\tconst entryId = normalizeModelSegment(entry.id);\n\t\tif (entryId !== queryId && stripTrailingDateStamp(entryId) !== queryIdNoDate) return false;\n\t\tif (queryProvider !== undefined && normalizeModelSegment(entry.provider) !== queryProvider) return false;\n\t\treturn true;\n\t});\n\tif (candidates.length === 0) return undefined;\n\tif (preferredProvider) {\n\t\tconst preferredProviderNorm = normalizeModelSegment(preferredProvider);\n\t\tconst preferred = candidates.find((entry) => normalizeModelSegment(entry.provider) === preferredProviderNorm);\n\t\tif (preferred) return preferred.fullId;\n\t}\n\tif (candidates.length === 1) return candidates[0]!.fullId;\n\treturn undefined;\n}\n\n/**\n * Resolve a possibly-loose model id to a canonical `provider/id` (plus any\n * thinking suffix). Exact registry matches win; fuzzy normalization\n * (separator/case/date-stamp via {@link fuzzyResolveModel}) is a fallback so\n * spelling differences still resolve. Never switches providers for a qualified\n * query. Pure.\n */\nexport function resolveModelCandidate(\n\tmodel: string | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n): string | undefined {\n\tif (!model) return undefined;\n\tif (!availableModels || availableModels.length === 0) return model;\n\n\tconst resolvedWhole = resolveBaseModelCandidate(model, availableModels, preferredProvider);\n\tif (resolvedWhole) return resolvedWhole;\n\n\tconst { baseModel, thinkingSuffix } = splitThinkingSuffix(model);\n\tif (!thinkingSuffix) return model;\n\tconst resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);\n\tif (resolvedBase) return `${resolvedBase}${thinkingSuffix}`;\n\treturn model;\n}\n\nexport interface ResolveSubagentModelOverrideOptions {\n\t/** When set with `enforce: true`, out-of-scope models are rejected. */\n\tscope?: ModelScopeConfig;\n\t/** Origin of the requested model: explicit caller-supplied (hard error) vs inherited (warn). Defaults to `\"inherited\"`. */\n\tsource?: ModelSource;\n\t/** Called for warn-severity violations instead of `console.warn`. */\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nfunction defaultScopeWarn(violation: ModelScopeViolation): void {\n\tconsole.warn(`[pi-subagents] ${violation.message}`);\n}\n\n/**\n * Resolve the `--model` override passed to a spawned subagent.\n *\n * When no model is requested (`undefined`, `false`, empty, or the `\"inherit\"`\n * sentinel), the child must inherit the parent session's *in-memory* model\n * (`provider/id`) instead of being left to resolve its own model. Without an\n * explicit `provider/id`, the child falls back to the global\n * `~/.pi/agent/settings.json` default, which is shared across every open PI\n * session — so a different session that last changed its model in the TUI would\n * silently contaminate this session's subagents (see issue #266). Passing an\n * explicit `provider/id` keeps each session's children isolated to that\n * session's model.\n *\n * An explicitly requested model string is resolved via {@link resolveModelCandidate}.\n * When `options.scope.enforce` is on, an out-of-scope resolved model throws for\n * an explicit (`source: \"explicit\"`) request and warns for an inherited one.\n */\nexport function resolveSubagentModelOverride(\n\trequestedModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: ResolveSubagentModelOverrideOptions,\n): string | undefined {\n\tconst trimmed = typeof requestedModel === \"string\" ? requestedModel.trim() : \"\";\n\tconst explicit = trimmed && trimmed !== INHERIT_MODEL ? trimmed : undefined;\n\tlet resolved: string | undefined;\n\tif (explicit === undefined) {\n\t\tresolved = parentModel ? `${parentModel.provider}/${parentModel.id}` : undefined;\n\t} else {\n\t\tresolved = resolveModelCandidate(explicit, availableModels, preferredProvider);\n\t}\n\tif (resolved && options?.scope?.enforce) {\n\t\tconst source: ModelSource = explicit === undefined ? \"inherited\" : (options.source ?? \"inherited\");\n\t\tconst violation = checkModelScope(resolved, options.scope, source);\n\t\tif (violation) {\n\t\t\tif (violation.severity === \"error\") throw new Error(violation.message);\n\t\t\t(options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t}\n\treturn resolved;\n}\n\nexport function resolveEffectiveSubagentModel(\n\texplicitModel: string | boolean | undefined,\n\tagentModel: string | boolean | undefined,\n\tparentModel: ParentModel | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: Omit<ResolveSubagentModelOverrideOptions, \"source\">,\n): string | undefined {\n\tconst resolved = resolveSubagentModelOverride(\n\t\texplicitModel ?? agentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: explicitModel !== undefined ? \"explicit\" : \"inherited\" },\n\t);\n\tif (resolved || explicitModel === undefined) return resolved;\n\treturn resolveSubagentModelOverride(\n\t\tagentModel,\n\t\tparentModel,\n\t\tavailableModels,\n\t\tpreferredProvider,\n\t\t{ ...options, source: \"inherited\" },\n\t);\n}\n\n// lunr: model tier bridge — every executable child must resolve one configured tier.\nexport function resolveTierModelOverride(tier: unknown): string | undefined {\n\tif (tier !== \"light\" && tier !== \"standard\" && tier !== \"heavy\") {\n\t\tthrow new Error(\"Every subagent execution requires tier: \\\"light\\\", \\\"standard\\\", or \\\"heavy\\\".\");\n\t}\n\tconst tierName = tier.trim();\n\ttry {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[Symbol.for(\"@lunr/model-tiers\")] as\n\t\t\t| { getTierModel?: (tier: string) => unknown; isTierModeEnabled?: () => unknown }\n\t\t\t| undefined;\n\t\tif (typeof bridge?.isTierModeEnabled !== \"function\" || typeof bridge?.getTierModel !== \"function\") {\n\t\t\tthrow new Error(\"Model tier settings are unavailable. Reload lunR and try again.\");\n\t\t}\n\t\tif (bridge.isTierModeEnabled() !== true) {\n\t\t\tthrow new Error(\"Model tiers are disabled. Enable them in /settings before launching a subagent.\");\n\t\t}\n\t\tconst model = bridge.getTierModel(tierName);\n\t\tif (typeof model !== \"string\" || !model.trim()) {\n\t\t\tthrow new Error(`Model tier '${tierName}' has no configured model. Configure it in /settings before launching a subagent.`);\n\t\t}\n\t\tconst trimmed = model.trim();\n\t\tconst thinking =\n\t\t\ttypeof bridge.getTierThinking === \"function\" ? bridge.getTierThinking(tierName) : undefined;\n\t\tconst parent = typeof bridge.getParentThinking === \"function\" ? bridge.getParentThinking() : undefined;\n\t\tconst level = (typeof thinking === \"string\" && thinking ? thinking : undefined) ?? (typeof parent === \"string\" && parent ? parent : undefined);\n\t\tif (!level) return trimmed;\n\t\treturn applyThinkingSuffix(trimmed, level, true) ?? trimmed;\n\t} catch (error) {\n\t\tthrow error instanceof Error ? error : new Error(String(error));\n\t}\n}\n\n/** Resolve a required tier and prove its configured model is available to this session. */\nexport function resolveRequiredTierModel(\n\ttier: unknown,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n): string {\n\tconst configured = resolveTierModelOverride(tier);\n\tif (!configured) throw new Error(`Model tier '${String(tier)}' could not be resolved.`);\n\tif (!availableModels?.length) {\n\t\tthrow new Error(`Model tier '${String(tier)}' cannot launch because no authenticated models are available.`);\n\t}\n\tconst { baseModel, thinkingSuffix } = splitThinkingSuffix(configured);\n\tconst resolvedBase = resolveBaseModelCandidate(baseModel, availableModels, preferredProvider);\n\tif (!resolvedBase) {\n\t\tthrow new Error(\n\t\t\t`Model tier '${String(tier)}' resolves to '${baseModel}', but that model is unavailable or unauthenticated. Configure an available model in /settings.`,\n\t\t);\n\t}\n\treturn `${resolvedBase}${thinkingSuffix}`;\n}\n\nfunction requestedModelString(model: unknown): string | undefined {\n\treturn typeof model === \"string\" && model.trim() && model.trim() !== INHERIT_MODEL ? model.trim() : undefined;\n}\n\nfunction requestedTier(tier: unknown): ChildTier | undefined {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\" ? tier : undefined;\n}\n\n/**\n * Capture how a child model was selected from the original requested params.\n * Must run before callers replace `model` with a resolved override.\n * Explicit model wins; a tier only counts when it actually resolves.\n */\nexport function captureModelSelection(input: { model?: unknown; tier?: unknown }): ModelSelection {\n\tconst tier = requestedTier(input.tier);\n\tif (!tier) throw new Error(\"Every subagent execution requires tier: \\\"light\\\", \\\"standard\\\", or \\\"heavy\\\".\");\n\treturn { kind: \"tier\", tier };\n}\n\nexport interface BuildModelCandidatesOptions {\n\t/** Fallback models are inherited agent config and warn, rather than error, when out of scope. */\n\tscope?: ModelScopeConfig;\n\tonWarn?: (violation: ModelScopeViolation) => void;\n}\n\nexport function buildModelCandidates(\n\tprimaryModel: string | undefined,\n\tfallbackModels: string[] | undefined,\n\tavailableModels: AvailableModelInfo[] | undefined,\n\tpreferredProvider?: string,\n\toptions?: BuildModelCandidatesOptions,\n): string[] {\n\tconst seen = new Set<string>();\n\tconst candidates: string[] = [];\n\tconst rawCandidates = [primaryModel, ...(fallbackModels ?? [])];\n\tfor (let index = 0; index < rawCandidates.length; index++) {\n\t\tconst raw = rawCandidates[index];\n\t\tif (!raw) continue;\n\t\tconst normalized = resolveModelCandidate(raw.trim(), availableModels, preferredProvider);\n\t\tif (!normalized || seen.has(normalized)) continue;\n\t\tif (index > 0 && options?.scope?.enforce) {\n\t\t\tconst violation = checkModelScope(normalized, options.scope, \"inherited\");\n\t\t\tif (violation) (options.onWarn ?? defaultScopeWarn)(violation);\n\t\t}\n\t\tseen.add(normalized);\n\t\tcandidates.push(normalized);\n\t}\n\treturn candidates;\n}\n\nconst RETRYABLE_MODEL_FAILURE_PATTERNS = [\n\t/rate\\s*limit/i,\n\t/too many requests/i,\n\t/\\b429\\b/,\n\t/quota/i,\n\t/billing/i,\n\t/credit/i,\n\t/auth(?:entication)?/i,\n\t/unauthori[sz]ed/i,\n\t/forbidden/i,\n\t/api key/i,\n\t/token expired/i,\n\t/invalid key/i,\n\t/provider.*unavailable/i,\n\t/model.*unavailable/i,\n\t/model.*disabled/i,\n\t/model.*not found/i,\n\t/unknown model/i,\n\t/overloaded/i,\n\t/service unavailable/i,\n\t/temporar(?:ily)? unavailable/i,\n\t/connection refused/i,\n\t/fetch failed/i,\n\t/network error/i,\n\t/socket hang up/i,\n\t/stream ended without finish_reason/i,\n\t/upstream/i,\n\t/timed? out/i,\n\t/timeout/i,\n\t/\\b502\\b/,\n\t/\\b503\\b/,\n\t/\\b504\\b/,\n\t/cold.?start/i,\n\t/empty response/i,\n\t/no output/i,\n\t/model.*(?:load|fail|error)/i,\n];\n\n/**\n * Failures reported as `<tool> failed (exit N): ...` or `<tool> failed with\n * exit code N` come from a tool call inside the child's task, not from the\n * provider/model, however network-flavored their details read. Retrying a\n * different model cannot fix them and would rerun the whole task. Tool names\n * include namespaced forms like `mcp.server/write`.\n */\nconst TOOL_FAILURE_PREFIX = /^[\\w.:@/-]+ failed (?:(?:\\(exit \\d+\\):)|(?:with exit code \\d+))(?:\\s|$)/i;\n\nexport function isRetryableModelFailure(error: string | undefined): boolean {\n\tif (!error) return false;\n\tif (TOOL_FAILURE_PREFIX.test(error.trim())) return false;\n\treturn RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(error));\n}\n\nexport function formatModelAttemptNote(attempt: ModelAttemptSummary, nextModel?: string): string {\n\tconst failure = attempt.error?.trim() || `exit ${attempt.exitCode ?? 1}`;\n\treturn nextModel\n\t\t? `[fallback] ${attempt.model} failed: ${failure}. Retrying with ${nextModel}.`\n\t\t: `[fallback] ${attempt.model} failed: ${failure}.`;\n}\n"]}
@@ -7,6 +7,7 @@ export interface RunnerSubagentStep {
7
7
  childId?: string;
8
8
  description?: string;
9
9
  permissions?: "full" | "read-only";
10
+ tier?: import("../../shared/types.ts").ChildTier;
10
11
  task: string;
11
12
  importAsyncRoot?: {
12
13
  runId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-utils.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,kBAAkB;IAClC,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,CAAC;IAChE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACxC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE;QAClB,MAAM,EAAE,OAAO,uBAAuB,EAAE,gBAAgB,CAAC;QACzD,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,sBAAsB,CAAC,EAAE,OAAO,uBAAuB,EAAE,gBAAgB,CAAC;IAC1E,mBAAmB,CAAC,EAAE,OAAO,uBAAuB,EAAE,wBAAwB,CAAC;IAC/E,eAAe,CAAC,EAAE,OAAO,uBAAuB,EAAE,eAAe,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,CAAC;IAChE,UAAU,CAAC,EAAE,OAAO,uBAAuB,EAAE,kBAAkB,CAAC;CAChE;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,OAAO,0BAA0B,EAAE,iBAAiB,CAAC;IAC7D,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,OAAO,0BAA0B,EAAE,kBAAkB,CAAC;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IACtC,iBAAiB,CAAC,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAC3C,mBAAmB,CAAC,EAAE,OAAO,uBAAuB,EAAE,wBAAwB,CAAC;IAC/E,eAAe,CAAC,EAAE,OAAO,uBAAuB,EAAE,eAAe,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,CAAC;CAChE;AAED,MAAM,MAAM,UAAU,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAErF,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,IAAI,iBAAiB,CAE3E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,IAAI,kBAAkB,CAEjF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,kBAAkB,EAAE,CAYtE;AAED,eAAO,MAAM,gCAAgC,QAA0B,CAAC;AAOxE;;;;;GAKG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAE/C,YAAY,KAAK,EAAE,MAAM,EAExB;IAED,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAQvB;IAED,OAAO,IAAI,IAAI,CAOd;CACD;AAED,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,EACvC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,eAAe,CAAC,EAAE,SAAS,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,CA8Bd;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,kBAAkB,EAAE,EAC7B,YAAY,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MACJ,GAC1C,MAAM,CAuBR;AAED,eAAO,MAAM,wBAAwB,QAA0B,CAAC","sourcesContent":["// @ts-nocheck\nexport interface RunnerSubagentStep {\n\t/** Session id of the direct parent session for permission-system ask forwarding. */\n\tparentSessionId?: string;\n\t/** Live parent permission mode snapshotted at spawn. */\n\tparentPermissionMode?: string;\n\tagent?: string;\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\ttask: string;\n\timportAsyncRoot?: {\n\t\trunId: string;\n\t\tasyncDir: string;\n\t\tresultPath: string;\n\t\tindex: number;\n\t};\n\tphase?: string;\n\tlabel?: string;\n\toutputName?: string;\n\tstructured?: boolean;\n\tcwd?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tmodelSelection?: import(\"../../shared/types.ts\").ModelSelection;\n\tmodelCandidates?: string[];\n\ttools?: string[];\n\textensions?: string[];\n\tsubagentOnlyExtensions?: string[];\n\tmcpDirectTools?: string[];\n\tcompletionGuard?: boolean;\n\tsystemPrompt?: string | null;\n\tsystemPromptMode?: \"append\" | \"replace\";\n\tinheritProjectContext: boolean;\n\tinheritSkills: boolean;\n\tskills?: string[];\n\toutputPath?: string;\n\t/** Defer the authoritative output instruction until a dynamic fanout item is materialized. */\n\tnamespaceOutputPath?: boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\tsessionFile?: string;\n\tmaxSubagentDepth?: number;\n\twaitToolEnabled?: boolean;\n\tstructuredOutput?: {\n\t\tschema: import(\"../../shared/types.ts\").JsonSchemaObject;\n\t\tschemaPath: string;\n\t\toutputPath: string;\n\t};\n\tstructuredOutputSchema?: import(\"../../shared/types.ts\").JsonSchemaObject;\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n\ttoolBudget?: import(\"../../shared/types.ts\").ResolvedToolBudget;\n}\n\nexport interface ParallelStepGroup {\n\tparallel: RunnerSubagentStep[];\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tworktree?: boolean;\n}\n\nexport interface DynamicRunnerGroup {\n\texpand: import(\"../../shared/settings.ts\").DynamicExpandSpec;\n\tparallel: RunnerSubagentStep;\n\tcollect: import(\"../../shared/settings.ts\").DynamicCollectSpec;\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tphase?: string;\n\tlabel?: string;\n\tsessionFiles?: (string | undefined)[];\n\tthinkingOverrides?: (string | undefined)[];\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n}\n\nexport type RunnerStep = RunnerSubagentStep | ParallelStepGroup | DynamicRunnerGroup;\n\nexport function isParallelGroup(step: RunnerStep): step is ParallelStepGroup {\n\treturn \"parallel\" in step && Array.isArray(step.parallel);\n}\n\nexport function isDynamicRunnerGroup(step: RunnerStep): step is DynamicRunnerGroup {\n\treturn \"expand\" in step && \"collect\" in step && \"parallel\" in step && !Array.isArray((step as { parallel?: unknown }).parallel);\n}\n\nexport function flattenSteps(steps: RunnerStep[]): RunnerSubagentStep[] {\n\tconst flat: RunnerSubagentStep[] = [];\n\tfor (const step of steps) {\n\t\tif (isParallelGroup(step)) {\n\t\t\tfor (const task of step.parallel) flat.push(task);\n\t\t} else if (isDynamicRunnerGroup(step)) {\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tflat.push(step);\n\t\t}\n\t}\n\treturn flat;\n}\n\nexport const DEFAULT_GLOBAL_CONCURRENCY_LIMIT = Number.MAX_SAFE_INTEGER;\n\n// lunr: stagger parallel cold starts so the first child's response begins\n// (creating the Anthropic cache entry) before siblings fire identical\n// system prompts. Sequential mode (limit=1) is untouched.\nconst PARALLEL_COLD_START_STAGGER_MS = 1000;\n\n/**\n * A promise-based semaphore for limiting concurrent access across multiple\n * mapConcurrent calls within a single run. Enforces a global cap on the total\n * number of subagent tasks executing simultaneously, regardless of each step's\n * per-step concurrency limit.\n */\nexport class Semaphore {\n\tprivate available: number;\n\tprivate readonly queue: Array<() => void> = [];\n\n\tconstructor(limit: number) {\n\t\tthis.available = Math.max(1, Math.floor(limit) || 1);\n\t}\n\n\tacquire(): Promise<void> {\n\t\tif (this.available > 0) {\n\t\t\tthis.available--;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.queue.push(resolve);\n\t\t});\n\t}\n\n\trelease(): void {\n\t\tconst next = this.queue.shift();\n\t\tif (next) {\n\t\t\tnext();\n\t\t} else {\n\t\t\tthis.available++;\n\t\t}\n\t}\n}\n\nexport async function mapConcurrent<T, R>(\n\titems: T[],\n\tlimit: number,\n\tfn: (item: T, i: number) => Promise<R>,\n\tglobalSemaphore?: Semaphore,\n): Promise<R[]> {\n\tconst safeLimit = Math.max(1, Math.floor(limit) || 1);\n\tconst results: R[] = new Array(items.length);\n\tlet next = 0;\n\n\tasync function worker(_workerIndex: number): Promise<void> {\n\t\twhile (next < items.length) {\n\t\t\tconst i = next++;\n\t\t\tif (safeLimit > 1 && i > 0 && PARALLEL_COLD_START_STAGGER_MS > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tsetTimeout(resolve, PARALLEL_COLD_START_STAGGER_MS * i);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (globalSemaphore) {\n\t\t\t\tawait globalSemaphore.acquire();\n\t\t\t\ttry {\n\t\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t\t} finally {\n\t\t\t\t\tglobalSemaphore.release();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait Promise.all(\n\t\tArray.from({ length: Math.min(safeLimit, items.length) }, (_, wi) => worker(wi)),\n\t);\n\treturn results;\n}\n\nexport interface ParallelTaskResult {\n\tagent: string;\n\ttaskIndex?: number;\n\toutput: string;\n\texitCode: number | null;\n\terror?: string;\n\ttimedOut?: boolean;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\toutputTargetPath?: string;\n\toutputTargetExists?: boolean;\n}\n\nexport function aggregateParallelOutputs(\n\tresults: ParallelTaskResult[],\n\theaderFormat: (index: number, agent: string) => string = (i, agent) =>\n\t\t`=== Parallel Task ${i + 1} (${agent}) ===`,\n): string {\n\treturn results\n\t\t.map((r, i) => {\n\t\t\tconst header = headerFormat(r.taskIndex ?? i, r.agent);\n\t\t\tconst hasOutput = Boolean(r.output?.trim());\n\t\t\tconst status =\n\t\t\t\tr.timedOut\n\t\t\t\t\t? `TIMED OUT${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t: r.exitCode === -1\n\t\t\t\t\t? \"SKIPPED\"\n\t\t\t\t\t: r.exitCode !== 0 && r.exitCode !== null\n\t\t\t\t\t\t? `FAILED (exit code ${r.exitCode})${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t\t: r.error\n\t\t\t\t\t\t\t? `WARNING: ${r.error}`\n\t\t\t\t\t\t\t: !hasOutput && r.outputTargetPath && r.outputTargetExists === false\n\t\t\t\t\t\t\t\t? `EMPTY OUTPUT (expected output file missing: ${r.outputTargetPath})`\n\t\t\t\t\t\t\t\t: !hasOutput && !r.outputTargetPath\n\t\t\t\t\t\t\t\t\t? \"EMPTY OUTPUT (no textual response returned)\"\n\t\t\t\t\t\t\t: \"\";\n\t\t\tconst body = status ? (hasOutput ? `${status}\\n${r.output}` : status) : r.output;\n\t\t\treturn `${header}\\n${body}`;\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nexport const MAX_PARALLEL_CONCURRENCY = Number.MAX_SAFE_INTEGER;\n"]}
1
+ {"version":3,"file":"parallel-utils.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nexport interface RunnerSubagentStep {\n\t/** Session id of the direct parent session for permission-system ask forwarding. */\n\tparentSessionId?: string;\n\t/** Live parent permission mode snapshotted at spawn. */\n\tparentPermissionMode?: string;\n\tagent?: string;\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\ttier?: import(\"../../shared/types.ts\").ChildTier;\n\ttask: string;\n\timportAsyncRoot?: {\n\t\trunId: string;\n\t\tasyncDir: string;\n\t\tresultPath: string;\n\t\tindex: number;\n\t};\n\tphase?: string;\n\tlabel?: string;\n\toutputName?: string;\n\tstructured?: boolean;\n\tcwd?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tmodelSelection?: import(\"../../shared/types.ts\").ModelSelection;\n\tmodelCandidates?: string[];\n\ttools?: string[];\n\textensions?: string[];\n\tsubagentOnlyExtensions?: string[];\n\tmcpDirectTools?: string[];\n\tcompletionGuard?: boolean;\n\tsystemPrompt?: string | null;\n\tsystemPromptMode?: \"append\" | \"replace\";\n\tinheritProjectContext: boolean;\n\tinheritSkills: boolean;\n\tskills?: string[];\n\toutputPath?: string;\n\t/** Defer the authoritative output instruction until a dynamic fanout item is materialized. */\n\tnamespaceOutputPath?: boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\tsessionFile?: string;\n\tmaxSubagentDepth?: number;\n\twaitToolEnabled?: boolean;\n\tstructuredOutput?: {\n\t\tschema: import(\"../../shared/types.ts\").JsonSchemaObject;\n\t\tschemaPath: string;\n\t\toutputPath: string;\n\t};\n\tstructuredOutputSchema?: import(\"../../shared/types.ts\").JsonSchemaObject;\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n\ttoolBudget?: import(\"../../shared/types.ts\").ResolvedToolBudget;\n}\n\nexport interface ParallelStepGroup {\n\tparallel: RunnerSubagentStep[];\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tworktree?: boolean;\n}\n\nexport interface DynamicRunnerGroup {\n\texpand: import(\"../../shared/settings.ts\").DynamicExpandSpec;\n\tparallel: RunnerSubagentStep;\n\tcollect: import(\"../../shared/settings.ts\").DynamicCollectSpec;\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tphase?: string;\n\tlabel?: string;\n\tsessionFiles?: (string | undefined)[];\n\tthinkingOverrides?: (string | undefined)[];\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n}\n\nexport type RunnerStep = RunnerSubagentStep | ParallelStepGroup | DynamicRunnerGroup;\n\nexport function isParallelGroup(step: RunnerStep): step is ParallelStepGroup {\n\treturn \"parallel\" in step && Array.isArray(step.parallel);\n}\n\nexport function isDynamicRunnerGroup(step: RunnerStep): step is DynamicRunnerGroup {\n\treturn \"expand\" in step && \"collect\" in step && \"parallel\" in step && !Array.isArray((step as { parallel?: unknown }).parallel);\n}\n\nexport function flattenSteps(steps: RunnerStep[]): RunnerSubagentStep[] {\n\tconst flat: RunnerSubagentStep[] = [];\n\tfor (const step of steps) {\n\t\tif (isParallelGroup(step)) {\n\t\t\tfor (const task of step.parallel) flat.push(task);\n\t\t} else if (isDynamicRunnerGroup(step)) {\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tflat.push(step);\n\t\t}\n\t}\n\treturn flat;\n}\n\nexport const DEFAULT_GLOBAL_CONCURRENCY_LIMIT = Number.MAX_SAFE_INTEGER;\n\n// lunr: stagger parallel cold starts so the first child's response begins\n// (creating the Anthropic cache entry) before siblings fire identical\n// system prompts. Sequential mode (limit=1) is untouched.\nconst PARALLEL_COLD_START_STAGGER_MS = 1000;\n\n/**\n * A promise-based semaphore for limiting concurrent access across multiple\n * mapConcurrent calls within a single run. Enforces a global cap on the total\n * number of subagent tasks executing simultaneously, regardless of each step's\n * per-step concurrency limit.\n */\nexport class Semaphore {\n\tprivate available: number;\n\tprivate readonly queue: Array<() => void> = [];\n\n\tconstructor(limit: number) {\n\t\tthis.available = Math.max(1, Math.floor(limit) || 1);\n\t}\n\n\tacquire(): Promise<void> {\n\t\tif (this.available > 0) {\n\t\t\tthis.available--;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.queue.push(resolve);\n\t\t});\n\t}\n\n\trelease(): void {\n\t\tconst next = this.queue.shift();\n\t\tif (next) {\n\t\t\tnext();\n\t\t} else {\n\t\t\tthis.available++;\n\t\t}\n\t}\n}\n\nexport async function mapConcurrent<T, R>(\n\titems: T[],\n\tlimit: number,\n\tfn: (item: T, i: number) => Promise<R>,\n\tglobalSemaphore?: Semaphore,\n): Promise<R[]> {\n\tconst safeLimit = Math.max(1, Math.floor(limit) || 1);\n\tconst results: R[] = new Array(items.length);\n\tlet next = 0;\n\n\tasync function worker(_workerIndex: number): Promise<void> {\n\t\twhile (next < items.length) {\n\t\t\tconst i = next++;\n\t\t\tif (safeLimit > 1 && i > 0 && PARALLEL_COLD_START_STAGGER_MS > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tsetTimeout(resolve, PARALLEL_COLD_START_STAGGER_MS * i);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (globalSemaphore) {\n\t\t\t\tawait globalSemaphore.acquire();\n\t\t\t\ttry {\n\t\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t\t} finally {\n\t\t\t\t\tglobalSemaphore.release();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait Promise.all(\n\t\tArray.from({ length: Math.min(safeLimit, items.length) }, (_, wi) => worker(wi)),\n\t);\n\treturn results;\n}\n\nexport interface ParallelTaskResult {\n\tagent: string;\n\ttaskIndex?: number;\n\toutput: string;\n\texitCode: number | null;\n\terror?: string;\n\ttimedOut?: boolean;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\toutputTargetPath?: string;\n\toutputTargetExists?: boolean;\n}\n\nexport function aggregateParallelOutputs(\n\tresults: ParallelTaskResult[],\n\theaderFormat: (index: number, agent: string) => string = (i, agent) =>\n\t\t`=== Parallel Task ${i + 1} (${agent}) ===`,\n): string {\n\treturn results\n\t\t.map((r, i) => {\n\t\t\tconst header = headerFormat(r.taskIndex ?? i, r.agent);\n\t\t\tconst hasOutput = Boolean(r.output?.trim());\n\t\t\tconst status =\n\t\t\t\tr.timedOut\n\t\t\t\t\t? `TIMED OUT${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t: r.exitCode === -1\n\t\t\t\t\t? \"SKIPPED\"\n\t\t\t\t\t: r.exitCode !== 0 && r.exitCode !== null\n\t\t\t\t\t\t? `FAILED (exit code ${r.exitCode})${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t\t: r.error\n\t\t\t\t\t\t\t? `WARNING: ${r.error}`\n\t\t\t\t\t\t\t: !hasOutput && r.outputTargetPath && r.outputTargetExists === false\n\t\t\t\t\t\t\t\t? `EMPTY OUTPUT (expected output file missing: ${r.outputTargetPath})`\n\t\t\t\t\t\t\t\t: !hasOutput && !r.outputTargetPath\n\t\t\t\t\t\t\t\t\t? \"EMPTY OUTPUT (no textual response returned)\"\n\t\t\t\t\t\t\t: \"\";\n\t\t\tconst body = status ? (hasOutput ? `${status}\\n${r.output}` : status) : r.output;\n\t\t\treturn `${header}\\n${body}`;\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nexport const MAX_PARALLEL_CONCURRENCY = Number.MAX_SAFE_INTEGER;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-utils.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nexport interface RunnerSubagentStep {\n\t/** Session id of the direct parent session for permission-system ask forwarding. */\n\tparentSessionId?: string;\n\t/** Live parent permission mode snapshotted at spawn. */\n\tparentPermissionMode?: string;\n\tagent?: string;\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\ttask: string;\n\timportAsyncRoot?: {\n\t\trunId: string;\n\t\tasyncDir: string;\n\t\tresultPath: string;\n\t\tindex: number;\n\t};\n\tphase?: string;\n\tlabel?: string;\n\toutputName?: string;\n\tstructured?: boolean;\n\tcwd?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tmodelSelection?: import(\"../../shared/types.ts\").ModelSelection;\n\tmodelCandidates?: string[];\n\ttools?: string[];\n\textensions?: string[];\n\tsubagentOnlyExtensions?: string[];\n\tmcpDirectTools?: string[];\n\tcompletionGuard?: boolean;\n\tsystemPrompt?: string | null;\n\tsystemPromptMode?: \"append\" | \"replace\";\n\tinheritProjectContext: boolean;\n\tinheritSkills: boolean;\n\tskills?: string[];\n\toutputPath?: string;\n\t/** Defer the authoritative output instruction until a dynamic fanout item is materialized. */\n\tnamespaceOutputPath?: boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\tsessionFile?: string;\n\tmaxSubagentDepth?: number;\n\twaitToolEnabled?: boolean;\n\tstructuredOutput?: {\n\t\tschema: import(\"../../shared/types.ts\").JsonSchemaObject;\n\t\tschemaPath: string;\n\t\toutputPath: string;\n\t};\n\tstructuredOutputSchema?: import(\"../../shared/types.ts\").JsonSchemaObject;\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n\ttoolBudget?: import(\"../../shared/types.ts\").ResolvedToolBudget;\n}\n\nexport interface ParallelStepGroup {\n\tparallel: RunnerSubagentStep[];\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tworktree?: boolean;\n}\n\nexport interface DynamicRunnerGroup {\n\texpand: import(\"../../shared/settings.ts\").DynamicExpandSpec;\n\tparallel: RunnerSubagentStep;\n\tcollect: import(\"../../shared/settings.ts\").DynamicCollectSpec;\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tphase?: string;\n\tlabel?: string;\n\tsessionFiles?: (string | undefined)[];\n\tthinkingOverrides?: (string | undefined)[];\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n}\n\nexport type RunnerStep = RunnerSubagentStep | ParallelStepGroup | DynamicRunnerGroup;\n\nexport function isParallelGroup(step: RunnerStep): step is ParallelStepGroup {\n\treturn \"parallel\" in step && Array.isArray(step.parallel);\n}\n\nexport function isDynamicRunnerGroup(step: RunnerStep): step is DynamicRunnerGroup {\n\treturn \"expand\" in step && \"collect\" in step && \"parallel\" in step && !Array.isArray((step as { parallel?: unknown }).parallel);\n}\n\nexport function flattenSteps(steps: RunnerStep[]): RunnerSubagentStep[] {\n\tconst flat: RunnerSubagentStep[] = [];\n\tfor (const step of steps) {\n\t\tif (isParallelGroup(step)) {\n\t\t\tfor (const task of step.parallel) flat.push(task);\n\t\t} else if (isDynamicRunnerGroup(step)) {\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tflat.push(step);\n\t\t}\n\t}\n\treturn flat;\n}\n\nexport const DEFAULT_GLOBAL_CONCURRENCY_LIMIT = Number.MAX_SAFE_INTEGER;\n\n// lunr: stagger parallel cold starts so the first child's response begins\n// (creating the Anthropic cache entry) before siblings fire identical\n// system prompts. Sequential mode (limit=1) is untouched.\nconst PARALLEL_COLD_START_STAGGER_MS = 1000;\n\n/**\n * A promise-based semaphore for limiting concurrent access across multiple\n * mapConcurrent calls within a single run. Enforces a global cap on the total\n * number of subagent tasks executing simultaneously, regardless of each step's\n * per-step concurrency limit.\n */\nexport class Semaphore {\n\tprivate available: number;\n\tprivate readonly queue: Array<() => void> = [];\n\n\tconstructor(limit: number) {\n\t\tthis.available = Math.max(1, Math.floor(limit) || 1);\n\t}\n\n\tacquire(): Promise<void> {\n\t\tif (this.available > 0) {\n\t\t\tthis.available--;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.queue.push(resolve);\n\t\t});\n\t}\n\n\trelease(): void {\n\t\tconst next = this.queue.shift();\n\t\tif (next) {\n\t\t\tnext();\n\t\t} else {\n\t\t\tthis.available++;\n\t\t}\n\t}\n}\n\nexport async function mapConcurrent<T, R>(\n\titems: T[],\n\tlimit: number,\n\tfn: (item: T, i: number) => Promise<R>,\n\tglobalSemaphore?: Semaphore,\n): Promise<R[]> {\n\tconst safeLimit = Math.max(1, Math.floor(limit) || 1);\n\tconst results: R[] = new Array(items.length);\n\tlet next = 0;\n\n\tasync function worker(_workerIndex: number): Promise<void> {\n\t\twhile (next < items.length) {\n\t\t\tconst i = next++;\n\t\t\tif (safeLimit > 1 && i > 0 && PARALLEL_COLD_START_STAGGER_MS > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tsetTimeout(resolve, PARALLEL_COLD_START_STAGGER_MS * i);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (globalSemaphore) {\n\t\t\t\tawait globalSemaphore.acquire();\n\t\t\t\ttry {\n\t\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t\t} finally {\n\t\t\t\t\tglobalSemaphore.release();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait Promise.all(\n\t\tArray.from({ length: Math.min(safeLimit, items.length) }, (_, wi) => worker(wi)),\n\t);\n\treturn results;\n}\n\nexport interface ParallelTaskResult {\n\tagent: string;\n\ttaskIndex?: number;\n\toutput: string;\n\texitCode: number | null;\n\terror?: string;\n\ttimedOut?: boolean;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\toutputTargetPath?: string;\n\toutputTargetExists?: boolean;\n}\n\nexport function aggregateParallelOutputs(\n\tresults: ParallelTaskResult[],\n\theaderFormat: (index: number, agent: string) => string = (i, agent) =>\n\t\t`=== Parallel Task ${i + 1} (${agent}) ===`,\n): string {\n\treturn results\n\t\t.map((r, i) => {\n\t\t\tconst header = headerFormat(r.taskIndex ?? i, r.agent);\n\t\t\tconst hasOutput = Boolean(r.output?.trim());\n\t\t\tconst status =\n\t\t\t\tr.timedOut\n\t\t\t\t\t? `TIMED OUT${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t: r.exitCode === -1\n\t\t\t\t\t? \"SKIPPED\"\n\t\t\t\t\t: r.exitCode !== 0 && r.exitCode !== null\n\t\t\t\t\t\t? `FAILED (exit code ${r.exitCode})${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t\t: r.error\n\t\t\t\t\t\t\t? `WARNING: ${r.error}`\n\t\t\t\t\t\t\t: !hasOutput && r.outputTargetPath && r.outputTargetExists === false\n\t\t\t\t\t\t\t\t? `EMPTY OUTPUT (expected output file missing: ${r.outputTargetPath})`\n\t\t\t\t\t\t\t\t: !hasOutput && !r.outputTargetPath\n\t\t\t\t\t\t\t\t\t? \"EMPTY OUTPUT (no textual response returned)\"\n\t\t\t\t\t\t\t: \"\";\n\t\t\tconst body = status ? (hasOutput ? `${status}\\n${r.output}` : status) : r.output;\n\t\t\treturn `${header}\\n${body}`;\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nexport const MAX_PARALLEL_CONCURRENCY = Number.MAX_SAFE_INTEGER;\n"]}
1
+ {"version":3,"file":"parallel-utils.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nexport interface RunnerSubagentStep {\n\t/** Session id of the direct parent session for permission-system ask forwarding. */\n\tparentSessionId?: string;\n\t/** Live parent permission mode snapshotted at spawn. */\n\tparentPermissionMode?: string;\n\tagent?: string;\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\ttier?: import(\"../../shared/types.ts\").ChildTier;\n\ttask: string;\n\timportAsyncRoot?: {\n\t\trunId: string;\n\t\tasyncDir: string;\n\t\tresultPath: string;\n\t\tindex: number;\n\t};\n\tphase?: string;\n\tlabel?: string;\n\toutputName?: string;\n\tstructured?: boolean;\n\tcwd?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tmodelSelection?: import(\"../../shared/types.ts\").ModelSelection;\n\tmodelCandidates?: string[];\n\ttools?: string[];\n\textensions?: string[];\n\tsubagentOnlyExtensions?: string[];\n\tmcpDirectTools?: string[];\n\tcompletionGuard?: boolean;\n\tsystemPrompt?: string | null;\n\tsystemPromptMode?: \"append\" | \"replace\";\n\tinheritProjectContext: boolean;\n\tinheritSkills: boolean;\n\tskills?: string[];\n\toutputPath?: string;\n\t/** Defer the authoritative output instruction until a dynamic fanout item is materialized. */\n\tnamespaceOutputPath?: boolean;\n\toutputMode?: \"inline\" | \"file-only\";\n\tsessionFile?: string;\n\tmaxSubagentDepth?: number;\n\twaitToolEnabled?: boolean;\n\tstructuredOutput?: {\n\t\tschema: import(\"../../shared/types.ts\").JsonSchemaObject;\n\t\tschemaPath: string;\n\t\toutputPath: string;\n\t};\n\tstructuredOutputSchema?: import(\"../../shared/types.ts\").JsonSchemaObject;\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n\ttoolBudget?: import(\"../../shared/types.ts\").ResolvedToolBudget;\n}\n\nexport interface ParallelStepGroup {\n\tparallel: RunnerSubagentStep[];\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tworktree?: boolean;\n}\n\nexport interface DynamicRunnerGroup {\n\texpand: import(\"../../shared/settings.ts\").DynamicExpandSpec;\n\tparallel: RunnerSubagentStep;\n\tcollect: import(\"../../shared/settings.ts\").DynamicCollectSpec;\n\tconcurrency?: number;\n\tfailFast?: boolean;\n\tphase?: string;\n\tlabel?: string;\n\tsessionFiles?: (string | undefined)[];\n\tthinkingOverrides?: (string | undefined)[];\n\teffectiveAcceptance?: import(\"../../shared/types.ts\").ResolvedAcceptanceConfig;\n\tacceptanceInput?: import(\"../../shared/types.ts\").AcceptanceInput;\n\tacceptanceRole?: import(\"../../shared/types.ts\").AcceptanceRole;\n}\n\nexport type RunnerStep = RunnerSubagentStep | ParallelStepGroup | DynamicRunnerGroup;\n\nexport function isParallelGroup(step: RunnerStep): step is ParallelStepGroup {\n\treturn \"parallel\" in step && Array.isArray(step.parallel);\n}\n\nexport function isDynamicRunnerGroup(step: RunnerStep): step is DynamicRunnerGroup {\n\treturn \"expand\" in step && \"collect\" in step && \"parallel\" in step && !Array.isArray((step as { parallel?: unknown }).parallel);\n}\n\nexport function flattenSteps(steps: RunnerStep[]): RunnerSubagentStep[] {\n\tconst flat: RunnerSubagentStep[] = [];\n\tfor (const step of steps) {\n\t\tif (isParallelGroup(step)) {\n\t\t\tfor (const task of step.parallel) flat.push(task);\n\t\t} else if (isDynamicRunnerGroup(step)) {\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tflat.push(step);\n\t\t}\n\t}\n\treturn flat;\n}\n\nexport const DEFAULT_GLOBAL_CONCURRENCY_LIMIT = Number.MAX_SAFE_INTEGER;\n\n// lunr: stagger parallel cold starts so the first child's response begins\n// (creating the Anthropic cache entry) before siblings fire identical\n// system prompts. Sequential mode (limit=1) is untouched.\nconst PARALLEL_COLD_START_STAGGER_MS = 1000;\n\n/**\n * A promise-based semaphore for limiting concurrent access across multiple\n * mapConcurrent calls within a single run. Enforces a global cap on the total\n * number of subagent tasks executing simultaneously, regardless of each step's\n * per-step concurrency limit.\n */\nexport class Semaphore {\n\tprivate available: number;\n\tprivate readonly queue: Array<() => void> = [];\n\n\tconstructor(limit: number) {\n\t\tthis.available = Math.max(1, Math.floor(limit) || 1);\n\t}\n\n\tacquire(): Promise<void> {\n\t\tif (this.available > 0) {\n\t\t\tthis.available--;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.queue.push(resolve);\n\t\t});\n\t}\n\n\trelease(): void {\n\t\tconst next = this.queue.shift();\n\t\tif (next) {\n\t\t\tnext();\n\t\t} else {\n\t\t\tthis.available++;\n\t\t}\n\t}\n}\n\nexport async function mapConcurrent<T, R>(\n\titems: T[],\n\tlimit: number,\n\tfn: (item: T, i: number) => Promise<R>,\n\tglobalSemaphore?: Semaphore,\n): Promise<R[]> {\n\tconst safeLimit = Math.max(1, Math.floor(limit) || 1);\n\tconst results: R[] = new Array(items.length);\n\tlet next = 0;\n\n\tasync function worker(_workerIndex: number): Promise<void> {\n\t\twhile (next < items.length) {\n\t\t\tconst i = next++;\n\t\t\tif (safeLimit > 1 && i > 0 && PARALLEL_COLD_START_STAGGER_MS > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tsetTimeout(resolve, PARALLEL_COLD_START_STAGGER_MS * i);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (globalSemaphore) {\n\t\t\t\tawait globalSemaphore.acquire();\n\t\t\t\ttry {\n\t\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t\t} finally {\n\t\t\t\t\tglobalSemaphore.release();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults[i] = await fn(items[i], i);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait Promise.all(\n\t\tArray.from({ length: Math.min(safeLimit, items.length) }, (_, wi) => worker(wi)),\n\t);\n\treturn results;\n}\n\nexport interface ParallelTaskResult {\n\tagent: string;\n\ttaskIndex?: number;\n\toutput: string;\n\texitCode: number | null;\n\terror?: string;\n\ttimedOut?: boolean;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\toutputTargetPath?: string;\n\toutputTargetExists?: boolean;\n}\n\nexport function aggregateParallelOutputs(\n\tresults: ParallelTaskResult[],\n\theaderFormat: (index: number, agent: string) => string = (i, agent) =>\n\t\t`=== Parallel Task ${i + 1} (${agent}) ===`,\n): string {\n\treturn results\n\t\t.map((r, i) => {\n\t\t\tconst header = headerFormat(r.taskIndex ?? i, r.agent);\n\t\t\tconst hasOutput = Boolean(r.output?.trim());\n\t\t\tconst status =\n\t\t\t\tr.timedOut\n\t\t\t\t\t? `TIMED OUT${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t: r.exitCode === -1\n\t\t\t\t\t? \"SKIPPED\"\n\t\t\t\t\t: r.exitCode !== 0 && r.exitCode !== null\n\t\t\t\t\t\t? `FAILED (exit code ${r.exitCode})${r.error ? `: ${r.error}` : \"\"}`\n\t\t\t\t\t\t: r.error\n\t\t\t\t\t\t\t? `WARNING: ${r.error}`\n\t\t\t\t\t\t\t: !hasOutput && r.outputTargetPath && r.outputTargetExists === false\n\t\t\t\t\t\t\t\t? `EMPTY OUTPUT (expected output file missing: ${r.outputTargetPath})`\n\t\t\t\t\t\t\t\t: !hasOutput && !r.outputTargetPath\n\t\t\t\t\t\t\t\t\t? \"EMPTY OUTPUT (no textual response returned)\"\n\t\t\t\t\t\t\t: \"\";\n\t\t\tconst body = status ? (hasOutput ? `${status}\\n${r.output}` : status) : r.output;\n\t\t\treturn `${header}\\n${body}`;\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nexport const MAX_PARALLEL_CONCURRENCY = Number.MAX_SAFE_INTEGER;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"child-spec.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/shared/child-spec.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\n/**\n * Normalize model-authored delegated tasks into ChildSpec before validation,\n * rendering, persistence, or process spawning.\n */\n\nimport {\n\tPLAN_MODE_WRITE_SPAWN_ERROR,\n\tresolveChildPermissions,\n\ttype ChildPermission,\n} from \"../../../../core/subagent-permission-inherit.ts\";\nimport { resolveChildExcludeTools } from \"../runs/shared/child-tools.ts\";\nimport { captureModelSelection } from \"../runs/shared/model-fallback.ts\";\nimport type { AcceptanceInput, ChildSpec, ChildTier, JsonSchemaObject, ModelSelection, ToolBudgetConfig } from \"./types.ts\";\n\nexport type { ChildSpec, ChildTier, ModelSelection } from \"./types.ts\";\n\nexport const CHILD_DESCRIPTION_MAX_LENGTH = 80;\n\nexport interface DelegatedTaskInput {\n\ttask?: unknown;\n\tdescription?: unknown;\n\tpermissions?: unknown;\n\tmodel?: unknown;\n\ttier?: unknown;\n\tmodelSelection?: unknown;\n\tskill?: unknown;\n\tcwd?: unknown;\n\toutput?: unknown;\n\toutputMode?: unknown;\n\tacceptance?: unknown;\n\ttoolBudget?: unknown;\n\tcount?: unknown;\n\treads?: unknown;\n\tprogress?: unknown;\n\tlabel?: unknown;\n\tphase?: unknown;\n\tas?: unknown;\n\toutputSchema?: unknown;\n}\n\nexport interface NormalizeChildSpecOptions {\n\tparentMode?: string;\n\trunId: string;\n\tindex: number;\n\tchildId?: string;\n\tdefaultTask?: string;\n\tfanoutAuthorized?: boolean;\n\tpathLabel?: string;\n}\n\nexport function allocateChildId(runId: string, index: number): string {\n\treturn `${runId}-${index}`;\n}\n\nexport function sanitizeChildDescription(value: string, max = CHILD_DESCRIPTION_MAX_LENGTH): string {\n\tconst collapsed = value.replace(/\\s+/g, \" \").trim();\n\tif (collapsed.length <= max) return collapsed;\n\treturn `${collapsed.slice(0, Math.max(1, max - 1))}…`;\n}\n\nexport function validateChildDescription(value: unknown, pathLabel = \"description\"): string {\n\tif (typeof value !== \"string\") {\n\t\tthrow new Error(`${pathLabel} is required and must be a concise single-line label (max ${CHILD_DESCRIPTION_MAX_LENGTH} characters).`);\n\t}\n\tif (/[\\r\\n]/.test(value)) {\n\t\tthrow new Error(`${pathLabel} must be a single line with no newlines.`);\n\t}\n\tconst trimmed = value.trim();\n\tif (!trimmed) {\n\t\tthrow new Error(`${pathLabel} is required and must be a concise single-line label (max ${CHILD_DESCRIPTION_MAX_LENGTH} characters).`);\n\t}\n\tif (trimmed.length > CHILD_DESCRIPTION_MAX_LENGTH) {\n\t\tthrow new Error(`${pathLabel} must be at most ${CHILD_DESCRIPTION_MAX_LENGTH} characters.`);\n\t}\n\treturn trimmed;\n}\n\nexport function parseChildPermissionsInput(value: unknown, pathLabel = \"permissions\"): ChildPermission | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === \"full\" || value === \"read-only\") return value;\n\tthrow new Error(`${pathLabel} must be \"full\" or \"read-only\".`);\n}\n\nfunction optionalString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction optionalSkill(value: unknown): string | string[] | false | undefined {\n\tif (value === false) return false;\n\tif (typeof value === \"string\") return value;\n\tif (Array.isArray(value) && value.every((entry) => typeof entry === \"string\")) return value as string[];\n\treturn undefined;\n}\n\nfunction optionalOutput(value: unknown): string | false | undefined {\n\tif (value === false) return false;\n\tif (typeof value === \"string\") return value;\n\treturn undefined;\n}\n\nfunction optionalReads(value: unknown): string[] | false | undefined {\n\tif (value === false) return false;\n\tif (Array.isArray(value) && value.every((entry) => typeof entry === \"string\")) return value as string[];\n\treturn undefined;\n}\n\nfunction optionalCount(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isInteger(value) && value >= 1) return value;\n\treturn undefined;\n}\n\nfunction isModelSelection(value: unknown): value is ModelSelection {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst kind = (value as { kind?: unknown }).kind;\n\tif (kind === \"model\" || kind === \"inherit\") return true;\n\tif (kind === \"tier\") {\n\t\tconst tier = (value as { tier?: unknown }).tier;\n\t\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\";\n\t}\n\treturn false;\n}\n\nexport function normalizeChildSpec(input: DelegatedTaskInput, options: NormalizeChildSpecOptions): ChildSpec {\n\tconst pathLabel = options.pathLabel ?? \"task\";\n\tconst description = validateChildDescription(input.description, `${pathLabel}.description`);\n\tconst task = typeof input.task === \"string\" && input.task.trim()\n\t\t? input.task\n\t\t: options.defaultTask;\n\tif (typeof task !== \"string\" || !task.trim()) {\n\t\tthrow new Error(`${pathLabel}.task is required.`);\n\t}\n\tconst requested = parseChildPermissionsInput(input.permissions, `${pathLabel}.permissions`);\n\tconst resolved = resolveChildPermissions(options.parentMode, requested);\n\tif (!resolved.ok) {\n\t\tthrow new Error(resolved.error || PLAN_MODE_WRITE_SPAWN_ERROR);\n\t}\n\tconst tier = input.tier === \"light\" || input.tier === \"standard\" || input.tier === \"heavy\" ? input.tier : undefined;\n\tconst outputMode = input.outputMode === \"inline\" || input.outputMode === \"file-only\" ? input.outputMode : undefined;\n\tconst modelSelection = isModelSelection(input.modelSelection)\n\t\t? input.modelSelection\n\t\t: captureModelSelection({ model: input.model, tier: input.tier });\n\treturn {\n\t\tchildId: options.childId ?? allocateChildId(options.runId, options.index),\n\t\ttask,\n\t\tdescription,\n\t\trequestedPermissions: resolved.requested,\n\t\teffectivePermissions: resolved.effective,\n\t\tmodel: optionalString(input.model),\n\t\ttier,\n\t\tmodelSelection,\n\t\tskill: optionalSkill(input.skill),\n\t\tcwd: optionalString(input.cwd),\n\t\toutput: optionalOutput(input.output),\n\t\toutputMode,\n\t\tacceptance: input.acceptance as AcceptanceInput | undefined,\n\t\ttoolBudget: input.toolBudget as ToolBudgetConfig | undefined,\n\t\tcount: optionalCount(input.count),\n\t\treads: optionalReads(input.reads),\n\t\tprogress: typeof input.progress === \"boolean\" ? input.progress : undefined,\n\t\tlabel: optionalString(input.label),\n\t\tphase: optionalString(input.phase),\n\t\tas: optionalString(input.as),\n\t\toutputSchema: input.outputSchema && typeof input.outputSchema === \"object\"\n\t\t\t? input.outputSchema as JsonSchemaObject\n\t\t\t: undefined,\n\t\tfanoutAuthorized: options.fanoutAuthorized === true,\n\t};\n}\n\nexport function childDisplayLabel(spec: Pick<ChildSpec, \"description\" | \"label\">): string {\n\treturn spec.label?.trim() || spec.description;\n}\n\nexport function tryNormalizeChildSpec(\n\tinput: DelegatedTaskInput,\n\toptions: NormalizeChildSpecOptions,\n): { ok: true; spec: ChildSpec } | { ok: false; error: string } {\n\ttry {\n\t\treturn { ok: true, spec: normalizeChildSpec(input, options) };\n\t} catch (error) {\n\t\treturn { ok: false, error: error instanceof Error ? error.message : String(error) };\n\t}\n}\n\nexport function childIdentityFields(spec: ChildSpec): {\n\tchildId: string;\n\tdescription: string;\n\tpermissions: ChildPermission;\n\tagent: string;\n} {\n\treturn {\n\t\tchildId: spec.childId,\n\t\tdescription: spec.description,\n\t\tpermissions: spec.effectivePermissions,\n\t\tagent: spec.description,\n\t};\n}\n\nexport function childOutputCapabilities(permissions: ChildPermission): { tools: string[] } {\n\treturn permissions === \"read-only\"\n\t\t? { tools: [\"read\"] }\n\t\t: { tools: [\"read\", \"edit\", \"write\", \"bash\"] };\n}\n\nexport function childSpawnPiArgDefaults(spec: ChildSpec): {\n\tinheritProjectContext: true;\n\tinheritSkills: false;\n\tsystemPromptMode: \"append\";\n\texcludeTools: string[];\n\tchildPermission: ChildPermission;\n\tchildId: string;\n\tchildDescription: string;\n\tchildAgentName: string;\n} {\n\treturn {\n\t\tinheritProjectContext: true,\n\t\tinheritSkills: false,\n\t\tsystemPromptMode: \"append\",\n\t\texcludeTools: resolveChildExcludeTools({\n\t\t\tpermissions: spec.effectivePermissions,\n\t\t\tfanoutAuthorized: spec.fanoutAuthorized,\n\t\t}),\n\t\tchildPermission: spec.effectivePermissions,\n\t\tchildId: spec.childId,\n\t\tchildDescription: spec.description,\n\t\tchildAgentName: spec.childId,\n\t};\n}\n"]}
1
+ {"version":3,"file":"child-spec.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/shared/child-spec.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\n/**\n * Normalize model-authored delegated tasks into ChildSpec before validation,\n * rendering, persistence, or process spawning.\n */\n\nimport {\n\tPLAN_MODE_WRITE_SPAWN_ERROR,\n\tresolveChildPermissions,\n\ttype ChildPermission,\n} from \"../../../../core/subagent-permission-inherit.ts\";\nimport { resolveChildExcludeTools } from \"../runs/shared/child-tools.ts\";\nimport { captureModelSelection } from \"../runs/shared/model-fallback.ts\";\nimport type { AcceptanceInput, ChildSpec, ChildTier, JsonSchemaObject, ModelSelection, ToolBudgetConfig } from \"./types.ts\";\n\nexport type { ChildSpec, ChildTier, ModelSelection } from \"./types.ts\";\n\nexport const CHILD_DESCRIPTION_MAX_LENGTH = 80;\n\nexport interface DelegatedTaskInput {\n\ttask?: unknown;\n\tdescription?: unknown;\n\tpermissions?: unknown;\n\tmodel?: unknown;\n\ttier?: unknown;\n\tmodelSelection?: unknown;\n\tskill?: unknown;\n\tcwd?: unknown;\n\toutput?: unknown;\n\toutputMode?: unknown;\n\tacceptance?: unknown;\n\ttoolBudget?: unknown;\n\tcount?: unknown;\n\treads?: unknown;\n\tprogress?: unknown;\n\tlabel?: unknown;\n\tphase?: unknown;\n\tas?: unknown;\n\toutputSchema?: unknown;\n}\n\nexport interface NormalizeChildSpecOptions {\n\tparentMode?: string;\n\trunId: string;\n\tindex: number;\n\tchildId?: string;\n\tdefaultTask?: string;\n\tfanoutAuthorized?: boolean;\n\tpathLabel?: string;\n}\n\nexport function allocateChildId(runId: string, index: number): string {\n\treturn `${runId}-${index}`;\n}\n\nexport function sanitizeChildDescription(value: string, max = CHILD_DESCRIPTION_MAX_LENGTH): string {\n\tconst collapsed = value.replace(/\\s+/g, \" \").trim();\n\tif (collapsed.length <= max) return collapsed;\n\treturn `${collapsed.slice(0, Math.max(1, max - 1))}…`;\n}\n\nexport function validateChildDescription(value: unknown, pathLabel = \"description\"): string {\n\tif (typeof value !== \"string\") {\n\t\tthrow new Error(`${pathLabel} is required and must be a concise single-line label (max ${CHILD_DESCRIPTION_MAX_LENGTH} characters).`);\n\t}\n\tif (/[\\r\\n]/.test(value)) {\n\t\tthrow new Error(`${pathLabel} must be a single line with no newlines.`);\n\t}\n\tconst trimmed = value.trim();\n\tif (!trimmed) {\n\t\tthrow new Error(`${pathLabel} is required and must be a concise single-line label (max ${CHILD_DESCRIPTION_MAX_LENGTH} characters).`);\n\t}\n\tif (trimmed.length > CHILD_DESCRIPTION_MAX_LENGTH) {\n\t\tthrow new Error(`${pathLabel} must be at most ${CHILD_DESCRIPTION_MAX_LENGTH} characters.`);\n\t}\n\treturn trimmed;\n}\n\nexport function parseChildPermissionsInput(value: unknown, pathLabel = \"permissions\"): ChildPermission | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === \"full\" || value === \"read-only\") return value;\n\tthrow new Error(`${pathLabel} must be \"full\" or \"read-only\".`);\n}\n\nfunction optionalString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction optionalSkill(value: unknown): string | string[] | false | undefined {\n\tif (value === false) return false;\n\tif (typeof value === \"string\") return value;\n\tif (Array.isArray(value) && value.every((entry) => typeof entry === \"string\")) return value as string[];\n\treturn undefined;\n}\n\nfunction optionalOutput(value: unknown): string | false | undefined {\n\tif (value === false) return false;\n\tif (typeof value === \"string\") return value;\n\treturn undefined;\n}\n\nfunction optionalReads(value: unknown): string[] | false | undefined {\n\tif (value === false) return false;\n\tif (Array.isArray(value) && value.every((entry) => typeof entry === \"string\")) return value as string[];\n\treturn undefined;\n}\n\nfunction optionalCount(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isInteger(value) && value >= 1) return value;\n\treturn undefined;\n}\n\nfunction isModelSelection(value: unknown): value is ModelSelection {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst kind = (value as { kind?: unknown }).kind;\n\tif (kind === \"tier\") {\n\t\tconst tier = (value as { tier?: unknown }).tier;\n\t\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\";\n\t}\n\treturn false;\n}\n\nexport function normalizeChildSpec(input: DelegatedTaskInput, options: NormalizeChildSpecOptions): ChildSpec {\n\tconst pathLabel = options.pathLabel ?? \"task\";\n\tconst description = validateChildDescription(input.description, `${pathLabel}.description`);\n\tconst task = typeof input.task === \"string\" && input.task.trim()\n\t\t? input.task\n\t\t: options.defaultTask;\n\tif (typeof task !== \"string\" || !task.trim()) {\n\t\tthrow new Error(`${pathLabel}.task is required.`);\n\t}\n\tconst requested = parseChildPermissionsInput(input.permissions, `${pathLabel}.permissions`);\n\tconst resolved = resolveChildPermissions(options.parentMode, requested);\n\tif (!resolved.ok) {\n\t\tthrow new Error(resolved.error || PLAN_MODE_WRITE_SPAWN_ERROR);\n\t}\n\tif (input.model !== undefined && !isModelSelection(input.modelSelection)) {\n\t\tthrow new Error(`${pathLabel}.model is not supported for executable children; choose tier: \"light\", \"standard\", or \"heavy\".`);\n\t}\n\tconst selectedTier = isModelSelection(input.modelSelection) ? input.modelSelection.tier : input.tier;\n\tif (selectedTier !== \"light\" && selectedTier !== \"standard\" && selectedTier !== \"heavy\") {\n\t\tthrow new Error(`${pathLabel}.tier is required and must be \"light\", \"standard\", or \"heavy\".`);\n\t}\n\tconst tier = selectedTier;\n\tconst outputMode = input.outputMode === \"inline\" || input.outputMode === \"file-only\" ? input.outputMode : undefined;\n\tconst modelSelection = isModelSelection(input.modelSelection)\n\t\t? input.modelSelection\n\t\t: captureModelSelection({ tier });\n\treturn {\n\t\tchildId: options.childId ?? allocateChildId(options.runId, options.index),\n\t\ttask,\n\t\tdescription,\n\t\trequestedPermissions: resolved.requested,\n\t\teffectivePermissions: resolved.effective,\n\t\tmodel: optionalString(input.model),\n\t\ttier,\n\t\tmodelSelection,\n\t\tskill: optionalSkill(input.skill),\n\t\tcwd: optionalString(input.cwd),\n\t\toutput: optionalOutput(input.output),\n\t\toutputMode,\n\t\tacceptance: input.acceptance as AcceptanceInput | undefined,\n\t\ttoolBudget: input.toolBudget as ToolBudgetConfig | undefined,\n\t\tcount: optionalCount(input.count),\n\t\treads: optionalReads(input.reads),\n\t\tprogress: typeof input.progress === \"boolean\" ? input.progress : undefined,\n\t\tlabel: optionalString(input.label),\n\t\tphase: optionalString(input.phase),\n\t\tas: optionalString(input.as),\n\t\toutputSchema: input.outputSchema && typeof input.outputSchema === \"object\"\n\t\t\t? input.outputSchema as JsonSchemaObject\n\t\t\t: undefined,\n\t\tfanoutAuthorized: options.fanoutAuthorized === true,\n\t};\n}\n\nexport function childDisplayLabel(spec: Pick<ChildSpec, \"description\" | \"label\">): string {\n\treturn spec.label?.trim() || spec.description;\n}\n\nexport function tryNormalizeChildSpec(\n\tinput: DelegatedTaskInput,\n\toptions: NormalizeChildSpecOptions,\n): { ok: true; spec: ChildSpec } | { ok: false; error: string } {\n\ttry {\n\t\treturn { ok: true, spec: normalizeChildSpec(input, options) };\n\t} catch (error) {\n\t\treturn { ok: false, error: error instanceof Error ? error.message : String(error) };\n\t}\n}\n\nexport function childIdentityFields(spec: ChildSpec): {\n\tchildId: string;\n\tdescription: string;\n\tpermissions: ChildPermission;\n\tagent: string;\n} {\n\treturn {\n\t\tchildId: spec.childId,\n\t\tdescription: spec.description,\n\t\tpermissions: spec.effectivePermissions,\n\t\tagent: spec.description,\n\t};\n}\n\nexport function childOutputCapabilities(permissions: ChildPermission): { tools: string[] } {\n\treturn permissions === \"read-only\"\n\t\t? { tools: [\"read\"] }\n\t\t: { tools: [\"read\", \"edit\", \"write\", \"bash\"] };\n}\n\nexport function childSpawnPiArgDefaults(spec: ChildSpec): {\n\tinheritProjectContext: true;\n\tinheritSkills: false;\n\tsystemPromptMode: \"append\";\n\texcludeTools: string[];\n\tchildPermission: ChildPermission;\n\tchildId: string;\n\tchildDescription: string;\n\tchildAgentName: string;\n} {\n\treturn {\n\t\tinheritProjectContext: true,\n\t\tinheritSkills: false,\n\t\tsystemPromptMode: \"append\",\n\t\texcludeTools: resolveChildExcludeTools({\n\t\t\tpermissions: spec.effectivePermissions,\n\t\t\tfanoutAuthorized: spec.fanoutAuthorized,\n\t\t}),\n\t\tchildPermission: spec.effectivePermissions,\n\t\tchildId: spec.childId,\n\t\tchildDescription: spec.description,\n\t\tchildAgentName: spec.childId,\n\t};\n}\n"]}
@@ -74,8 +74,6 @@ function isModelSelection(value) {
74
74
  if (!value || typeof value !== "object")
75
75
  return false;
76
76
  const kind = value.kind;
77
- if (kind === "model" || kind === "inherit")
78
- return true;
79
77
  if (kind === "tier") {
80
78
  const tier = value.tier;
81
79
  return tier === "light" || tier === "standard" || tier === "heavy";
@@ -96,11 +94,18 @@ export function normalizeChildSpec(input, options) {
96
94
  if (!resolved.ok) {
97
95
  throw new Error(resolved.error || PLAN_MODE_WRITE_SPAWN_ERROR);
98
96
  }
99
- const tier = input.tier === "light" || input.tier === "standard" || input.tier === "heavy" ? input.tier : undefined;
97
+ if (input.model !== undefined && !isModelSelection(input.modelSelection)) {
98
+ throw new Error(`${pathLabel}.model is not supported for executable children; choose tier: "light", "standard", or "heavy".`);
99
+ }
100
+ const selectedTier = isModelSelection(input.modelSelection) ? input.modelSelection.tier : input.tier;
101
+ if (selectedTier !== "light" && selectedTier !== "standard" && selectedTier !== "heavy") {
102
+ throw new Error(`${pathLabel}.tier is required and must be "light", "standard", or "heavy".`);
103
+ }
104
+ const tier = selectedTier;
100
105
  const outputMode = input.outputMode === "inline" || input.outputMode === "file-only" ? input.outputMode : undefined;
101
106
  const modelSelection = isModelSelection(input.modelSelection)
102
107
  ? input.modelSelection
103
- : captureModelSelection({ model: input.model, tier: input.tier });
108
+ : captureModelSelection({ tier });
104
109
  return {
105
110
  childId: options.childId ?? allocateChildId(options.runId, options.index),
106
111
  task,