@optique/core 1.3.0-dev.2379 → 1.3.0-dev.2381

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/facade.js CHANGED
@@ -6,7 +6,7 @@ import { formatDocPage } from "./doc.js";
6
6
  import { dispatchByMode } from "./internal/mode-dispatch.js";
7
7
  import { collectExplicitSourceValues, collectExplicitSourceValuesAsync, createDependencyRuntimeContext } from "./dependency-runtime.js";
8
8
  import { createInputTrace } from "./input-trace.js";
9
- import { createParserContext, getDocPage } from "./internal/parser.js";
9
+ import { createEffectfulCompletionSession, createParserContext, getDocPage } from "./internal/parser.js";
10
10
  import { bash, fish, nu, pwsh, zsh } from "./completion.js";
11
11
  import { allowDuplicateLeadingCommandNamesKey, hiddenCommandAliasesKey } from "./internal/command-alias.js";
12
12
  import { completeOrExtractPhase2Seed } from "./phase2-seed.js";
@@ -116,7 +116,17 @@ function createParseExec(parser) {
116
116
  function getCommandPath(exec) {
117
117
  return exec?.commandPath ?? [];
118
118
  }
119
- function createCompleteExec(exec, context) {
119
+ const effectfulSessionOptionsKey = Symbol("@optique/core/facade/effectfulSessionOptionsKey");
120
+ function getEffectfulSessionOption(options) {
121
+ return options[effectfulSessionOptionsKey];
122
+ }
123
+ function withEffectfulSessionOption(options, session) {
124
+ return {
125
+ ...options,
126
+ [effectfulSessionOptionsKey]: session
127
+ };
128
+ }
129
+ function createCompleteExec(exec, context, session) {
120
130
  const runtime = createDependencyRuntimeContext();
121
131
  return {
122
132
  ...exec,
@@ -124,10 +134,11 @@ function createCompleteExec(exec, context) {
124
134
  dependencyRuntime: runtime,
125
135
  dependencyRegistry: runtime.registry,
126
136
  commandPath: getCommandPath(context.exec) ?? exec.commandPath,
127
- trace: context.exec?.trace ?? context.trace ?? exec.trace
137
+ trace: context.exec?.trace ?? context.trace ?? exec.trace,
138
+ effectfulCompletionSession: session ?? createEffectfulCompletionSession()
128
139
  };
129
140
  }
130
- function attemptParseSync(parser, args, mode = "complete") {
141
+ function attemptParseSync(parser, args, mode = "complete", session) {
131
142
  const shouldUnwrapAnnotatedValue = isInjectedAnnotationWrapper(parser.initialState);
132
143
  const exec = createParseExec(parser);
133
144
  let context = createParserContext({
@@ -166,7 +177,7 @@ function attemptParseSync(parser, args, mode = "complete") {
166
177
  kind: "success",
167
178
  value: void 0
168
179
  };
169
- const endResult = parser.complete(context.state, createCompleteExec(exec, context));
180
+ const endResult = parser.complete(context.state, createCompleteExec(exec, context, session));
170
181
  if (!endResult.success) return {
171
182
  kind: "failure",
172
183
  error: endResult.error,
@@ -180,7 +191,7 @@ function attemptParseSync(parser, args, mode = "complete") {
180
191
  value: shouldUnwrapAnnotatedValue ? unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
181
192
  };
182
193
  }
183
- async function attemptParseAsync(parser, args, mode = "complete") {
194
+ async function attemptParseAsync(parser, args, mode = "complete", session) {
184
195
  const shouldUnwrapAnnotatedValue = isInjectedAnnotationWrapper(parser.initialState);
185
196
  const exec = createParseExec(parser);
186
197
  let context = createParserContext({
@@ -219,7 +230,7 @@ async function attemptParseAsync(parser, args, mode = "complete") {
219
230
  kind: "success",
220
231
  value: void 0
221
232
  };
222
- const endResult = await parser.complete(context.state, createCompleteExec(exec, context));
233
+ const endResult = await parser.complete(context.state, createCompleteExec(exec, context, session));
223
234
  if (!endResult.success) return {
224
235
  kind: "failure",
225
236
  error: endResult.error,
@@ -233,7 +244,7 @@ async function attemptParseAsync(parser, args, mode = "complete") {
233
244
  value: shouldUnwrapAnnotatedValue ? unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
234
245
  };
235
246
  }
236
- function createPhase2SeedExec(parser, context) {
247
+ function createPhase2SeedExec(parser, context, session) {
237
248
  const exec = {
238
249
  usage: parser.usage,
239
250
  phase: "parse",
@@ -248,7 +259,8 @@ function createPhase2SeedExec(parser, context) {
248
259
  dependencyRuntime: runtime,
249
260
  dependencyRegistry: runtime.registry,
250
261
  commandPath: getCommandPath(context.exec),
251
- trace: context.exec?.trace ?? context.trace ?? exec.trace
262
+ trace: context.exec?.trace ?? context.trace ?? exec.trace,
263
+ effectfulCompletionSession: session ?? createEffectfulCompletionSession()
252
264
  };
253
265
  }
254
266
  function createPhase2SeedContext(parser, args) {
@@ -265,27 +277,27 @@ function createPhase2SeedContext(parser, args) {
265
277
  optionsTerminated: false
266
278
  }, exec);
267
279
  }
268
- function extractPhase2SeedSync(parser, args) {
280
+ function extractPhase2SeedSync(parser, args, session) {
269
281
  let context = createPhase2SeedContext(parser, args);
270
282
  do {
271
283
  const result = parser.parse(context);
272
- if (!result.success) return completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context));
284
+ if (!result.success) return completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context, session));
273
285
  const previousBuffer = context.buffer;
274
286
  context = result.next;
275
- if (isBufferUnchanged(previousBuffer, context.buffer)) return completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context));
287
+ if (isBufferUnchanged(previousBuffer, context.buffer)) return completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context, session));
276
288
  } while (context.buffer.length > 0);
277
- return completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context));
289
+ return completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context, session));
278
290
  }
279
- async function extractPhase2SeedAsync(parser, args) {
291
+ async function extractPhase2SeedAsync(parser, args, session) {
280
292
  let context = createPhase2SeedContext(parser, args);
281
293
  do {
282
294
  const result = await parser.parse(context);
283
- if (!result.success) return await completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context));
295
+ if (!result.success) return await completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context, session));
284
296
  const previousBuffer = context.buffer;
285
297
  context = result.next;
286
- if (isBufferUnchanged(previousBuffer, context.buffer)) return await completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context));
298
+ if (isBufferUnchanged(previousBuffer, context.buffer)) return await completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context, session));
287
299
  } while (context.buffer.length > 0);
288
- return await completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context));
300
+ return await completeOrExtractPhase2Seed(parser, context.state, createPhase2SeedExec(parser, context, session));
289
301
  }
290
302
  function getMetaCommandAliases(names) {
291
303
  const [, firstAlias, ...restAliases] = names;
@@ -1246,7 +1258,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1246
1258
  };
1247
1259
  const parserMode = parser.mode;
1248
1260
  return dispatchByMode(parserMode, () => {
1249
- const attempted = attemptParseSync(parser, args);
1261
+ const attempted = attemptParseSync(parser, args, "complete", getEffectfulSessionOption(options));
1250
1262
  const classified = attempted.kind === "success" ? {
1251
1263
  type: "success",
1252
1264
  value: attempted.value
@@ -1255,7 +1267,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1255
1267
  if (handled instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
1256
1268
  return handled;
1257
1269
  }, async () => {
1258
- const attempted = await attemptParseAsync(parser, args);
1270
+ const attempted = await attemptParseAsync(parser, args, "complete", getEffectfulSessionOption(options));
1259
1271
  const classified = attempted.kind === "success" ? {
1260
1272
  type: "success",
1261
1273
  value: attempted.value
@@ -1603,16 +1615,24 @@ async function runWithBody(parser, programName, contexts, args, options) {
1603
1615
  if (parser.mode === "async") return runParser(augmentedParser1, programName, args, options);
1604
1616
  return Promise.resolve(runParser(augmentedParser1, programName, args, options));
1605
1617
  }
1606
- const firstPassSeed = await dispatchByMode(parser.mode, () => extractPhase2SeedSync(augmentedParser1, args), () => extractPhase2SeedAsync(augmentedParser1, args));
1618
+ const seedSession = createEffectfulCompletionSession("demand-only");
1619
+ const finalSession = {
1620
+ ...seedSession,
1621
+ policy: "eager",
1622
+ effectfulSources: /* @__PURE__ */ new Set(),
1623
+ completedByPath: /* @__PURE__ */ new Map()
1624
+ };
1625
+ const sessionOptions = withEffectfulSessionOption(options, finalSession);
1626
+ const firstPassSeed = await dispatchByMode(parser.mode, () => extractPhase2SeedSync(augmentedParser1, args, seedSession), () => extractPhase2SeedAsync(augmentedParser1, args, seedSession));
1607
1627
  if (firstPassSeed == null) {
1608
1628
  const fallbackParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1609
- if (parser.mode === "async") return runParser(fallbackParser, programName, args, options);
1610
- return Promise.resolve(runParser(fallbackParser, programName, args, options));
1629
+ if (parser.mode === "async") return runParser(fallbackParser, programName, args, sessionOptions);
1630
+ return Promise.resolve(runParser(fallbackParser, programName, args, sessionOptions));
1611
1631
  }
1612
1632
  const { annotations: finalAnnotations } = await collectFinalAnnotations(contexts, phase1Snapshots, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1613
1633
  const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
1614
- if (parser.mode === "async") return runParser(augmentedParser2, programName, args, options);
1615
- return Promise.resolve(runParser(augmentedParser2, programName, args, options));
1634
+ if (parser.mode === "async") return runParser(augmentedParser2, programName, args, sessionOptions);
1635
+ return Promise.resolve(runParser(augmentedParser2, programName, args, sessionOptions));
1616
1636
  }
1617
1637
  /**
1618
1638
  * Runs a parser with multiple source contexts.
@@ -1718,14 +1738,22 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1718
1738
  }
1719
1739
  const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
1720
1740
  if (!needsTwoPhase) return runParser(augmentedParser1, programName, args, options);
1721
- const firstPassSeed = extractPhase2SeedSync(augmentedParser1, args);
1741
+ const seedSession = createEffectfulCompletionSession("demand-only");
1742
+ const finalSession = {
1743
+ ...seedSession,
1744
+ policy: "eager",
1745
+ effectfulSources: /* @__PURE__ */ new Set(),
1746
+ completedByPath: /* @__PURE__ */ new Map()
1747
+ };
1748
+ const sessionOptions = withEffectfulSessionOption(options, finalSession);
1749
+ const firstPassSeed = extractPhase2SeedSync(augmentedParser1, args, seedSession);
1722
1750
  if (firstPassSeed == null) {
1723
1751
  const fallbackParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1724
- return runParser(fallbackParser, programName, args, options);
1752
+ return runParser(fallbackParser, programName, args, sessionOptions);
1725
1753
  }
1726
1754
  const { annotations: finalAnnotations } = collectFinalAnnotationsSync(contexts, phase1Snapshots, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1727
1755
  const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
1728
- return runParser(augmentedParser2, programName, args, options);
1756
+ return runParser(augmentedParser2, programName, args, sessionOptions);
1729
1757
  }
1730
1758
  /**
1731
1759
  * Runs a synchronous parser with multiple source contexts.
package/dist/index.d.cts CHANGED
@@ -4,7 +4,7 @@ import { Message, MessageFormatOptions, MessageTerm, ValueSetOptions, commandLin
4
4
  import { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.cjs";
5
5
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowChoicesOptions, ShowDefaultOptions, cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.cjs";
6
6
  import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.cjs";
7
- import { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.cjs";
7
+ import { CombineModes, DocState, EffectfulCompletionSession, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.cjs";
8
8
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.cjs";
9
9
  import { DeferredValue, DeferredValueOptions, DeferredValueSource, FluentParser, MultipleErrorOptions, MultipleOptions, ParserModifiers, WithDefaultError, WithDefaultOptions, deferredValue, fluent, isDeferredValue, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.cjs";
10
10
  import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, GroupOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, SeqOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, seq, tuple } from "./constructs.cjs";
@@ -12,4 +12,4 @@ import { ParserValuePlaceholder, SourceContext, SourceContextRequest } from "./c
12
12
  import { AnyDependencySource, CombineMode, CombinedDependencyMode, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, dependency, deriveFrom, deriveFromAsync, deriveFromSync, isDependencySource, isDerivedValueParser } from "./internal/dependency.cjs";
13
13
  import { CommandListMode, CommandSubConfig, ContextOptionsParam, ExtractRequiredOptions, OptionSubConfig, RunOptions, RunParserError, RunWithOptions, SubstituteParserValue, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.cjs";
14
14
  import { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, OptionErrorOptions, OptionOptions, OptionState, PassThroughFormat, PassThroughOptions, argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.cjs";
15
- export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EffectfulCompletionSession, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { Message, MessageFormatOptions, MessageTerm, ValueSetOptions, commandLin
4
4
  import { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.js";
5
5
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowChoicesOptions, ShowDefaultOptions, cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.js";
6
6
  import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.js";
7
- import { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.js";
7
+ import { CombineModes, DocState, EffectfulCompletionSession, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.js";
8
8
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.js";
9
9
  import { DeferredValue, DeferredValueOptions, DeferredValueSource, FluentParser, MultipleErrorOptions, MultipleOptions, ParserModifiers, WithDefaultError, WithDefaultOptions, deferredValue, fluent, isDeferredValue, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
10
10
  import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, GroupOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, SeqOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, seq, tuple } from "./constructs.js";
@@ -12,4 +12,4 @@ import { ParserValuePlaceholder, SourceContext, SourceContextRequest } from "./c
12
12
  import { AnyDependencySource, CombineMode, CombinedDependencyMode, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, dependency, deriveFrom, deriveFromAsync, deriveFromSync, isDependencySource, isDerivedValueParser } from "./internal/dependency.js";
13
13
  import { CommandListMode, CommandSubConfig, ContextOptionsParam, ExtractRequiredOptions, OptionSubConfig, RunOptions, RunParserError, RunWithOptions, SubstituteParserValue, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.js";
14
14
  import { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, OptionErrorOptions, OptionOptions, OptionState, PassThroughFormat, PassThroughOptions, argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.js";
15
- export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EffectfulCompletionSession, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
@@ -14,6 +14,21 @@ const require_input_trace = require('../input-trace.cjs');
14
14
  */
15
15
  const parseLanesKey = Symbol("parseLanes");
16
16
  /**
17
+ * Creates a fresh {@link EffectfulCompletionSession}.
18
+ *
19
+ * @internal
20
+ * @since 1.3.0
21
+ */
22
+ function createEffectfulCompletionSession(policy = "eager") {
23
+ return {
24
+ policy,
25
+ results: /* @__PURE__ */ new Map(),
26
+ demanded: /* @__PURE__ */ new Set(),
27
+ effectfulSources: /* @__PURE__ */ new Set(),
28
+ completedByPath: /* @__PURE__ */ new Map()
29
+ };
30
+ }
31
+ /**
17
32
  * Internal marker for wrappers whose `{ hasCliValue: false }` states should
18
33
  * be treated as unmatched dependency-source states during completion-time
19
34
  * Phase 1.
@@ -21,7 +36,9 @@ const parseLanesKey = Symbol("parseLanes");
21
36
  * Wrappers like `bindEnv()` and `bindConfig()` opt in because their missing
22
37
  * CLI states still carry enough fallback context to pre-complete exactly
23
38
  * once. Wrappers like `prompt()` intentionally do not opt in because
24
- * prompted values are not yet registered as dependency sources.
39
+ * Phase 1 must stay effect-free; prompted values register instead through
40
+ * the `completeSource` capability during the serial effectful completion
41
+ * pass that runs before dependency replay.
25
42
  *
26
43
  * @internal
27
44
  */
@@ -130,7 +147,8 @@ function parseSync(parser, args, options) {
130
147
  dependencyRuntime: runtime,
131
148
  dependencyRegistry: runtime.registry,
132
149
  commandPath: context.exec?.commandPath ?? exec.commandPath,
133
- trace: context.exec?.trace ?? context.trace ?? exec.trace
150
+ trace: context.exec?.trace ?? context.trace ?? exec.trace,
151
+ effectfulCompletionSession: createEffectfulCompletionSession()
134
152
  };
135
153
  const endResult = parser.complete(context.state, completeExec);
136
154
  return endResult.success ? {
@@ -203,7 +221,8 @@ async function parseAsync(parser, args, options) {
203
221
  dependencyRuntime: runtime,
204
222
  dependencyRegistry: runtime.registry,
205
223
  commandPath: context.exec?.commandPath ?? exec.commandPath,
206
- trace: context.exec?.trace ?? context.trace ?? exec.trace
224
+ trace: context.exec?.trace ?? context.trace ?? exec.trace,
225
+ effectfulCompletionSession: createEffectfulCompletionSession()
207
226
  };
208
227
  const endResult = await parser.complete(context.state, completeExec);
209
228
  return endResult.success ? {
@@ -884,6 +903,7 @@ function findNextMatchedCommandArgIndex(args, matchedCommandArgIndices, start) {
884
903
  //#endregion
885
904
  exports.annotationWrapperRequiresSourceBindingKey = annotationWrapperRequiresSourceBindingKey;
886
905
  exports.composeWrappedSourceMetadata = composeWrappedSourceMetadata;
906
+ exports.createEffectfulCompletionSession = createEffectfulCompletionSession;
887
907
  exports.createParserContext = createParserContext;
888
908
  exports.defineInheritedAnnotationParser = defineInheritedAnnotationParser;
889
909
  exports.defineParseLanes = defineParseLanes;
@@ -5,8 +5,8 @@ import { DocFragments, DocPage } from "../doc.cjs";
5
5
  import { DependencyRegistryLike } from "../registry-types.cjs";
6
6
  import { DeferredMap, ValueParserResult } from "../valueparser.cjs";
7
7
  import { ParserDependencyMetadata } from "../dependency-metadata.cjs";
8
- import { DependencyRuntimeContext, RuntimeNode } from "../dependency-runtime.cjs";
9
8
  import { InputTrace } from "../input-trace.cjs";
9
+ import { DependencyRuntimeContext, RuntimeNode } from "../dependency-runtime.cjs";
10
10
 
11
11
  //#region src/internal/parser.d.ts
12
12
 
@@ -412,6 +412,72 @@ interface ParseFrame<TState> {
412
412
  * @since 1.0.0
413
413
  */
414
414
  type ExecutionPhase = "parse" | "precomplete" | "resolve" | "complete" | "suggest";
415
+ /**
416
+ * Run-scoped state for effectful source completions such as `prompt()`.
417
+ *
418
+ * A session is created once per parse operation (or once per `runWith()`
419
+ * run, shared by the phase-two seed pass and the final pass) and threaded
420
+ * through {@link ExecutionContext}. It guarantees that an effectful source
421
+ * completion runs at most once per run: the completion result is cached by
422
+ * dependency source ID, and a cache hit is returned without repeating the
423
+ * effect. Results never leak between runs because the session is discarded
424
+ * when the run ends.
425
+ *
426
+ * @internal
427
+ * @since 1.3.0
428
+ */
429
+ interface EffectfulCompletionSession {
430
+ /**
431
+ * The scheduling policy for effectful source completions.
432
+ *
433
+ * `"demand-only"` is used during the phase-two seed pass of a two-pass
434
+ * source context run: an effectful source completion runs only when a
435
+ * phase-one consumer demands its source (see
436
+ * {@link EffectfulCompletionSession.demanded}); otherwise it defers to
437
+ * the final pass. `"eager"` is used everywhere else.
438
+ */
439
+ readonly policy: "demand-only" | "eager";
440
+ /**
441
+ * Effectful completion results keyed by completion occurrence (e.g.,
442
+ * a per-`prompt()`-wrapper cache key), shared across the passes of a
443
+ * run. Occurrence keys, rather than dependency source IDs, keep two
444
+ * distinct effectful wrappers around the same source—such as duplicate
445
+ * `merge()` fields—from observing each other's local results.
446
+ */
447
+ readonly results: Map<symbol, ValueParserResult<unknown>>;
448
+ /**
449
+ * Source IDs demanded by phase-one consumers. Constructs add entries
450
+ * before scheduling effectful completions; the set accumulates across
451
+ * constructs within a run.
452
+ */
453
+ readonly demanded: Set<symbol>;
454
+ /**
455
+ * Source IDs whose registered value came from an effectful completion
456
+ * (a prompt that actually executed) rather than from a structural
457
+ * source such as CLI state, environment, configuration, or a default.
458
+ * The scheduler uses this to keep structural precedence while still
459
+ * letting a later prompted occurrence of the same source overwrite an
460
+ * earlier prompted answer, matching repeated command-line occurrences.
461
+ */
462
+ readonly effectfulSources: Set<symbol>;
463
+ /**
464
+ * Effectful source completion results keyed by serialized node path,
465
+ * scoped to a single pass like {@link effectfulSources}. A completion
466
+ * scheduled for an expanded nested node is recorded here so that the
467
+ * owning nested construct's own scheduling pass reuses it instead of
468
+ * completing the same node again—keeping lazy wrapper defaults at one
469
+ * evaluation per pass and the registered dependency value identical to
470
+ * the field's final value.
471
+ */
472
+ readonly completedByPath: Map<string, ValueParserResult<unknown>>;
473
+ }
474
+ /**
475
+ * Creates a fresh {@link EffectfulCompletionSession}.
476
+ *
477
+ * @internal
478
+ * @since 1.3.0
479
+ */
480
+ declare function createEffectfulCompletionSession(policy?: "demand-only" | "eager"): EffectfulCompletionSession;
415
481
  /**
416
482
  * Shared execution context carrying cross-cutting runtime data.
417
483
  * This includes information that is shared across all parsers in a parse
@@ -495,6 +561,15 @@ interface ExecutionContext {
495
561
  * @internal
496
562
  */
497
563
  readonly excludedSourceFields?: ReadonlySet<string | symbol>;
564
+ /**
565
+ * Run-scoped state for effectful source completions such as `prompt()`.
566
+ * Created at the top-level parse entry points and shared across the
567
+ * passes of a `runWith()` run.
568
+ *
569
+ * @internal
570
+ * @since 1.3.0
571
+ */
572
+ readonly effectfulCompletionSession?: EffectfulCompletionSession;
498
573
  }
499
574
  /**
500
575
  * Internal marker for wrappers whose `{ hasCliValue: false }` states should
@@ -504,7 +579,9 @@ interface ExecutionContext {
504
579
  * Wrappers like `bindEnv()` and `bindConfig()` opt in because their missing
505
580
  * CLI states still carry enough fallback context to pre-complete exactly
506
581
  * once. Wrappers like `prompt()` intentionally do not opt in because
507
- * prompted values are not yet registered as dependency sources.
582
+ * Phase 1 must stay effect-free; prompted values register instead through
583
+ * the `completeSource` capability during the serial effectful completion
584
+ * pass that runs before dependency replay.
508
585
  *
509
586
  * @internal
510
587
  */
@@ -1060,4 +1137,4 @@ declare function getDocPage(parser: Parser<"sync", unknown, unknown>, argsOrOpti
1060
1137
  declare function getDocPage(parser: Parser<"async", unknown, unknown>, argsOrOptions?: readonly string[] | ParseOptions, options?: ParseOptions): Promise<DocPage | undefined>;
1061
1138
  declare function getDocPage<M extends Mode>(parser: Parser<M, unknown, unknown>, argsOrOptions?: readonly string[] | ParseOptions, options?: ParseOptions): ModeValue<M, DocPage | undefined>;
1062
1139
  //#endregion
1063
- export { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, ParseLane, ParseLaneConsumptionGroup, type ParseOptions, Parser, ParserContext, ParserResult, Result, Suggestion, annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };
1140
+ export { CombineModes, DocState, EffectfulCompletionSession, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, ParseLane, ParseLaneConsumptionGroup, type ParseOptions, Parser, ParserContext, ParserResult, Result, Suggestion, annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createEffectfulCompletionSession, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };
@@ -5,8 +5,8 @@ import { DocFragments, DocPage } from "../doc.js";
5
5
  import { DependencyRegistryLike } from "../registry-types.js";
6
6
  import { DeferredMap, ValueParserResult } from "../valueparser.js";
7
7
  import { ParserDependencyMetadata } from "../dependency-metadata.js";
8
- import { DependencyRuntimeContext, RuntimeNode } from "../dependency-runtime.js";
9
8
  import { InputTrace } from "../input-trace.js";
9
+ import { DependencyRuntimeContext, RuntimeNode } from "../dependency-runtime.js";
10
10
 
11
11
  //#region src/internal/parser.d.ts
12
12
 
@@ -412,6 +412,72 @@ interface ParseFrame<TState> {
412
412
  * @since 1.0.0
413
413
  */
414
414
  type ExecutionPhase = "parse" | "precomplete" | "resolve" | "complete" | "suggest";
415
+ /**
416
+ * Run-scoped state for effectful source completions such as `prompt()`.
417
+ *
418
+ * A session is created once per parse operation (or once per `runWith()`
419
+ * run, shared by the phase-two seed pass and the final pass) and threaded
420
+ * through {@link ExecutionContext}. It guarantees that an effectful source
421
+ * completion runs at most once per run: the completion result is cached by
422
+ * dependency source ID, and a cache hit is returned without repeating the
423
+ * effect. Results never leak between runs because the session is discarded
424
+ * when the run ends.
425
+ *
426
+ * @internal
427
+ * @since 1.3.0
428
+ */
429
+ interface EffectfulCompletionSession {
430
+ /**
431
+ * The scheduling policy for effectful source completions.
432
+ *
433
+ * `"demand-only"` is used during the phase-two seed pass of a two-pass
434
+ * source context run: an effectful source completion runs only when a
435
+ * phase-one consumer demands its source (see
436
+ * {@link EffectfulCompletionSession.demanded}); otherwise it defers to
437
+ * the final pass. `"eager"` is used everywhere else.
438
+ */
439
+ readonly policy: "demand-only" | "eager";
440
+ /**
441
+ * Effectful completion results keyed by completion occurrence (e.g.,
442
+ * a per-`prompt()`-wrapper cache key), shared across the passes of a
443
+ * run. Occurrence keys, rather than dependency source IDs, keep two
444
+ * distinct effectful wrappers around the same source—such as duplicate
445
+ * `merge()` fields—from observing each other's local results.
446
+ */
447
+ readonly results: Map<symbol, ValueParserResult<unknown>>;
448
+ /**
449
+ * Source IDs demanded by phase-one consumers. Constructs add entries
450
+ * before scheduling effectful completions; the set accumulates across
451
+ * constructs within a run.
452
+ */
453
+ readonly demanded: Set<symbol>;
454
+ /**
455
+ * Source IDs whose registered value came from an effectful completion
456
+ * (a prompt that actually executed) rather than from a structural
457
+ * source such as CLI state, environment, configuration, or a default.
458
+ * The scheduler uses this to keep structural precedence while still
459
+ * letting a later prompted occurrence of the same source overwrite an
460
+ * earlier prompted answer, matching repeated command-line occurrences.
461
+ */
462
+ readonly effectfulSources: Set<symbol>;
463
+ /**
464
+ * Effectful source completion results keyed by serialized node path,
465
+ * scoped to a single pass like {@link effectfulSources}. A completion
466
+ * scheduled for an expanded nested node is recorded here so that the
467
+ * owning nested construct's own scheduling pass reuses it instead of
468
+ * completing the same node again—keeping lazy wrapper defaults at one
469
+ * evaluation per pass and the registered dependency value identical to
470
+ * the field's final value.
471
+ */
472
+ readonly completedByPath: Map<string, ValueParserResult<unknown>>;
473
+ }
474
+ /**
475
+ * Creates a fresh {@link EffectfulCompletionSession}.
476
+ *
477
+ * @internal
478
+ * @since 1.3.0
479
+ */
480
+ declare function createEffectfulCompletionSession(policy?: "demand-only" | "eager"): EffectfulCompletionSession;
415
481
  /**
416
482
  * Shared execution context carrying cross-cutting runtime data.
417
483
  * This includes information that is shared across all parsers in a parse
@@ -495,6 +561,15 @@ interface ExecutionContext {
495
561
  * @internal
496
562
  */
497
563
  readonly excludedSourceFields?: ReadonlySet<string | symbol>;
564
+ /**
565
+ * Run-scoped state for effectful source completions such as `prompt()`.
566
+ * Created at the top-level parse entry points and shared across the
567
+ * passes of a `runWith()` run.
568
+ *
569
+ * @internal
570
+ * @since 1.3.0
571
+ */
572
+ readonly effectfulCompletionSession?: EffectfulCompletionSession;
498
573
  }
499
574
  /**
500
575
  * Internal marker for wrappers whose `{ hasCliValue: false }` states should
@@ -504,7 +579,9 @@ interface ExecutionContext {
504
579
  * Wrappers like `bindEnv()` and `bindConfig()` opt in because their missing
505
580
  * CLI states still carry enough fallback context to pre-complete exactly
506
581
  * once. Wrappers like `prompt()` intentionally do not opt in because
507
- * prompted values are not yet registered as dependency sources.
582
+ * Phase 1 must stay effect-free; prompted values register instead through
583
+ * the `completeSource` capability during the serial effectful completion
584
+ * pass that runs before dependency replay.
508
585
  *
509
586
  * @internal
510
587
  */
@@ -1060,4 +1137,4 @@ declare function getDocPage(parser: Parser<"sync", unknown, unknown>, argsOrOpti
1060
1137
  declare function getDocPage(parser: Parser<"async", unknown, unknown>, argsOrOptions?: readonly string[] | ParseOptions, options?: ParseOptions): Promise<DocPage | undefined>;
1061
1138
  declare function getDocPage<M extends Mode>(parser: Parser<M, unknown, unknown>, argsOrOptions?: readonly string[] | ParseOptions, options?: ParseOptions): ModeValue<M, DocPage | undefined>;
1062
1139
  //#endregion
1063
- export { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, ParseLane, ParseLaneConsumptionGroup, type ParseOptions, Parser, ParserContext, ParserResult, Result, Suggestion, annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };
1140
+ export { CombineModes, DocState, EffectfulCompletionSession, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, ParseLane, ParseLaneConsumptionGroup, type ParseOptions, Parser, ParserContext, ParserResult, Result, Suggestion, annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createEffectfulCompletionSession, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };
@@ -14,6 +14,21 @@ import { createInputTrace } from "../input-trace.js";
14
14
  */
15
15
  const parseLanesKey = Symbol("parseLanes");
16
16
  /**
17
+ * Creates a fresh {@link EffectfulCompletionSession}.
18
+ *
19
+ * @internal
20
+ * @since 1.3.0
21
+ */
22
+ function createEffectfulCompletionSession(policy = "eager") {
23
+ return {
24
+ policy,
25
+ results: /* @__PURE__ */ new Map(),
26
+ demanded: /* @__PURE__ */ new Set(),
27
+ effectfulSources: /* @__PURE__ */ new Set(),
28
+ completedByPath: /* @__PURE__ */ new Map()
29
+ };
30
+ }
31
+ /**
17
32
  * Internal marker for wrappers whose `{ hasCliValue: false }` states should
18
33
  * be treated as unmatched dependency-source states during completion-time
19
34
  * Phase 1.
@@ -21,7 +36,9 @@ const parseLanesKey = Symbol("parseLanes");
21
36
  * Wrappers like `bindEnv()` and `bindConfig()` opt in because their missing
22
37
  * CLI states still carry enough fallback context to pre-complete exactly
23
38
  * once. Wrappers like `prompt()` intentionally do not opt in because
24
- * prompted values are not yet registered as dependency sources.
39
+ * Phase 1 must stay effect-free; prompted values register instead through
40
+ * the `completeSource` capability during the serial effectful completion
41
+ * pass that runs before dependency replay.
25
42
  *
26
43
  * @internal
27
44
  */
@@ -130,7 +147,8 @@ function parseSync(parser, args, options) {
130
147
  dependencyRuntime: runtime,
131
148
  dependencyRegistry: runtime.registry,
132
149
  commandPath: context.exec?.commandPath ?? exec.commandPath,
133
- trace: context.exec?.trace ?? context.trace ?? exec.trace
150
+ trace: context.exec?.trace ?? context.trace ?? exec.trace,
151
+ effectfulCompletionSession: createEffectfulCompletionSession()
134
152
  };
135
153
  const endResult = parser.complete(context.state, completeExec);
136
154
  return endResult.success ? {
@@ -203,7 +221,8 @@ async function parseAsync(parser, args, options) {
203
221
  dependencyRuntime: runtime,
204
222
  dependencyRegistry: runtime.registry,
205
223
  commandPath: context.exec?.commandPath ?? exec.commandPath,
206
- trace: context.exec?.trace ?? context.trace ?? exec.trace
224
+ trace: context.exec?.trace ?? context.trace ?? exec.trace,
225
+ effectfulCompletionSession: createEffectfulCompletionSession()
207
226
  };
208
227
  const endResult = await parser.complete(context.state, completeExec);
209
228
  return endResult.success ? {
@@ -882,4 +901,4 @@ function findNextMatchedCommandArgIndex(args, matchedCommandArgIndices, start) {
882
901
  }
883
902
 
884
903
  //#endregion
885
- export { annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };
904
+ export { annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createEffectfulCompletionSession, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };